Sync from Piper @353127564

PROTOBUF_SYNC_PIPER
diff --git a/.gitignore b/.gitignore
index 4e745eb..44ab2d4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -192,6 +192,7 @@
 ruby/tests/test_import_pb.rb
 ruby/tests/test_ruby_package_pb.rb
 ruby/tests/generated_code_proto2_pb.rb
+ruby/tests/multi_level_nesting_test_pb.rb
 ruby/tests/test_import_proto2_pb.rb
 ruby/tests/test_ruby_package_proto2_pb.rb
 ruby/Gemfile.lock
diff --git a/conformance/conformance_ruby.rb b/conformance/conformance_ruby.rb
index 79d8d3d..4af7659 100755
--- a/conformance/conformance_ruby.rb
+++ b/conformance/conformance_ruby.rb
@@ -32,6 +32,7 @@
 
 require 'conformance_pb'
 require 'google/protobuf/test_messages_proto3_pb'
+require 'google/protobuf/test_messages_proto2_pb'
 
 $test_count = 0
 $verbose = false
@@ -39,39 +40,39 @@
 def do_test(request)
   test_message = ProtobufTestMessages::Proto3::TestAllTypesProto3.new
   response = Conformance::ConformanceResponse.new
+  descriptor = Google::Protobuf::DescriptorPool.generated_pool.lookup(request.message_type)
+
+  unless descriptor
+    response.skipped = "Unknown message type: " + request.message_type
+  end
 
   begin
     case request.payload
     when :protobuf_payload
-      if request.message_type.eql?('protobuf_test_messages.proto3.TestAllTypesProto3')
-        begin
-          test_message = ProtobufTestMessages::Proto3::TestAllTypesProto3.decode(
-              request.protobuf_payload)
-        rescue Google::Protobuf::ParseError => err
-          response.parse_error = err.message.encode('utf-8')
-          return response
-        end
-      elsif request.message_type.eql?('protobuf_test_messages.proto2.TestAllTypesProto2')
-        response.skipped = "Ruby doesn't support proto2"
-        return response
-      else
-        fail "Protobuf request doesn't have specific payload type"
-      end
-
-    when :json_payload
       begin
-        test_message = ProtobufTestMessages::Proto3::TestAllTypesProto3.decode_json(
-            request.json_payload)
+        test_message = descriptor.msgclass.decode(request.protobuf_payload)
       rescue Google::Protobuf::ParseError => err
         response.parse_error = err.message.encode('utf-8')
         return response
       end
-	
-	when :text_payload
-	  begin
-		response.skipped = "Ruby doesn't support proto2"
-        return response   
-	  end
+
+    when :json_payload
+      begin
+        options = {}
+        if request.test_category == :JSON_IGNORE_UNKNOWN_PARSING_TEST
+          options[:ignore_unknown_fields] = true
+        end
+        test_message = descriptor.msgclass.decode_json(request.json_payload, options)
+      rescue Google::Protobuf::ParseError => err
+        response.parse_error = err.message.encode('utf-8')
+        return response
+      end
+
+    when :text_payload
+      begin
+        response.skipped = "Ruby doesn't support text format"
+        return response
+      end
 
     when nil
       fail "Request didn't have payload"
@@ -82,10 +83,18 @@
       fail 'Unspecified output format'
 
     when :PROTOBUF
-      response.protobuf_payload = test_message.to_proto
+      begin
+        response.protobuf_payload = test_message.to_proto
+      rescue Google::Protobuf::ParseError => err
+        response.serialize_error = err.message.encode('utf-8')
+      end
 
     when :JSON
-      response.json_payload = test_message.to_json
+      begin
+        response.json_payload = test_message.to_json
+      rescue Google::Protobuf::ParseError => err
+        response.serialize_error = err.message.encode('utf-8')
+      end
 
     when nil
       fail "Request didn't have requested output format"
diff --git a/conformance/failure_list_jruby.txt b/conformance/failure_list_jruby.txt
deleted file mode 100644
index ceaaf92..0000000
--- a/conformance/failure_list_jruby.txt
+++ /dev/null
@@ -1,810 +0,0 @@
-Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
-Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
-Recommended.FieldMaskTooManyUnderscore.JsonOutput
-Recommended.Proto2.JsonInput.FieldNameExtension.Validator
-Recommended.Proto3.JsonInput.BoolFieldAllCapitalFalse
-Recommended.Proto3.JsonInput.BoolFieldAllCapitalTrue
-Recommended.Proto3.JsonInput.BoolFieldCamelCaseFalse
-Recommended.Proto3.JsonInput.BoolFieldCamelCaseTrue
-Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedFalse
-Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedTrue
-Recommended.Proto3.JsonInput.BoolMapFieldKeyNotQuoted
-Recommended.Proto3.JsonInput.DoubleFieldInfinityNotQuoted
-Recommended.Proto3.JsonInput.DoubleFieldNanNotQuoted
-Recommended.Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted
-Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
-Recommended.Proto3.JsonInput.FieldNameDuplicate
-Recommended.Proto3.JsonInput.FieldNameNotQuoted
-Recommended.Proto3.JsonInput.FloatFieldInfinityNotQuoted
-Recommended.Proto3.JsonInput.FloatFieldNanNotQuoted
-Recommended.Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted
-Recommended.Proto3.JsonInput.Int32MapFieldKeyNotQuoted
-Recommended.Proto3.JsonInput.Int64MapFieldKeyNotQuoted
-Recommended.Proto3.JsonInput.JsonWithComments
-Recommended.Proto3.JsonInput.StringFieldSingleQuoteBoth
-Recommended.Proto3.JsonInput.StringFieldSingleQuoteKey
-Recommended.Proto3.JsonInput.StringFieldSingleQuoteValue
-Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder
-Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate
-Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
-Recommended.Proto3.JsonInput.Uint32MapFieldKeyNotQuoted
-Recommended.Proto3.JsonInput.Uint64MapFieldKeyNotQuoted
-Recommended.Proto3.ProtobufInput.OneofZeroBool.JsonOutput
-Recommended.Proto3.ProtobufInput.OneofZeroBool.ProtobufOutput
-Recommended.Proto3.ProtobufInput.OneofZeroBytes.JsonOutput
-Recommended.Proto3.ProtobufInput.OneofZeroBytes.ProtobufOutput
-Recommended.Proto3.ProtobufInput.OneofZeroDouble.JsonOutput
-Recommended.Proto3.ProtobufInput.OneofZeroDouble.ProtobufOutput
-Recommended.Proto3.ProtobufInput.OneofZeroEnum.JsonOutput
-Recommended.Proto3.ProtobufInput.OneofZeroEnum.ProtobufOutput
-Recommended.Proto3.ProtobufInput.OneofZeroFloat.JsonOutput
-Recommended.Proto3.ProtobufInput.OneofZeroFloat.ProtobufOutput
-Recommended.Proto3.ProtobufInput.OneofZeroMessage.JsonOutput
-Recommended.Proto3.ProtobufInput.OneofZeroMessage.ProtobufOutput
-Recommended.Proto3.ProtobufInput.OneofZeroMessageSetTwice.JsonOutput
-Recommended.Proto3.ProtobufInput.OneofZeroMessageSetTwice.ProtobufOutput
-Recommended.Proto3.ProtobufInput.OneofZeroString.JsonOutput
-Recommended.Proto3.ProtobufInput.OneofZeroString.ProtobufOutput
-Recommended.Proto3.ProtobufInput.OneofZeroUint32.JsonOutput
-Recommended.Proto3.ProtobufInput.OneofZeroUint32.ProtobufOutput
-Recommended.Proto3.ProtobufInput.OneofZeroUint64.JsonOutput
-Recommended.Proto3.ProtobufInput.OneofZeroUint64.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BOOL.DefaultValue.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BOOL.MultipleValuesForDifferentField.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BOOL.MultipleValuesForSameField.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BOOL.NonDefaultValue.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BYTES.DefaultValue.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BYTES.MultipleValuesForDifferentField.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BYTES.MultipleValuesForSameField.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.BYTES.NonDefaultValue.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.DOUBLE.DefaultValue.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.DOUBLE.MultipleValuesForDifferentField.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.DOUBLE.MultipleValuesForSameField.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.DOUBLE.NonDefaultValue.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.ENUM.DefaultValue.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.ENUM.MultipleValuesForDifferentField.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.ENUM.MultipleValuesForSameField.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.ENUM.NonDefaultValue.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.FLOAT.DefaultValue.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.FLOAT.MultipleValuesForDifferentField.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.FLOAT.MultipleValuesForSameField.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.FLOAT.NonDefaultValue.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.DefaultValue.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.MultipleValuesForDifferentField.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.MultipleValuesForSameField.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.NonDefaultValue.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.STRING.DefaultValue.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.STRING.MultipleValuesForDifferentField.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.STRING.MultipleValuesForSameField.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.STRING.NonDefaultValue.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT32.DefaultValue.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT32.MultipleValuesForDifferentField.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT32.MultipleValuesForSameField.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT32.NonDefaultValue.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT64.DefaultValue.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT64.MultipleValuesForDifferentField.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT64.MultipleValuesForSameField.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.UINT64.NonDefaultValue.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BOOL[2].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BOOL[3].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BOOL[4].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BOOL[5].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BOOL[6].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.BYTES[3].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.DOUBLE[1].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.DOUBLE[2].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[0].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[1].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[2].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[3].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[4].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[5].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FIXED32[2].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FIXED64[2].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FLOAT[1].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FLOAT[2].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FLOAT[3].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FLOAT[4].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[1].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[2].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[3].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[4].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[5].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[6].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[7].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[8].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[9].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT64[1].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT64[2].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT64[3].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.MESSAGE[0].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.MESSAGE[1].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SFIXED32[2].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SFIXED32[3].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SFIXED64[2].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SFIXED64[3].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT32[1].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT32[2].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT32[3].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT32[4].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT64[1].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT64[2].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT64[3].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.STRING[3].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.STRING[4].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.STRING[5].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.STRING[6].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[1].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[2].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[3].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[4].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[5].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[6].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[7].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[8].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[9].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT64[1].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT64[2].ProtobufOutput
-Required.DurationProtoInputTooLarge.JsonOutput
-Required.DurationProtoInputTooSmall.JsonOutput
-Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator
-Required.Proto3.JsonInput.Any.JsonOutput
-Required.Proto3.JsonInput.Any.ProtobufOutput
-Required.Proto3.JsonInput.AnyNested.JsonOutput
-Required.Proto3.JsonInput.AnyNested.ProtobufOutput
-Required.Proto3.JsonInput.AnyUnorderedTypeTag.JsonOutput
-Required.Proto3.JsonInput.AnyUnorderedTypeTag.ProtobufOutput
-Required.Proto3.JsonInput.AnyWithDuration.JsonOutput
-Required.Proto3.JsonInput.AnyWithDuration.ProtobufOutput
-Required.Proto3.JsonInput.AnyWithFieldMask.JsonOutput
-Required.Proto3.JsonInput.AnyWithFieldMask.ProtobufOutput
-Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.JsonOutput
-Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput
-Required.Proto3.JsonInput.AnyWithStruct.JsonOutput
-Required.Proto3.JsonInput.AnyWithStruct.ProtobufOutput
-Required.Proto3.JsonInput.AnyWithTimestamp.JsonOutput
-Required.Proto3.JsonInput.AnyWithTimestamp.ProtobufOutput
-Required.Proto3.JsonInput.AnyWithValueForInteger.JsonOutput
-Required.Proto3.JsonInput.AnyWithValueForInteger.ProtobufOutput
-Required.Proto3.JsonInput.AnyWithValueForJsonObject.JsonOutput
-Required.Proto3.JsonInput.AnyWithValueForJsonObject.ProtobufOutput
-Required.Proto3.JsonInput.EnumFieldNotQuoted
-Required.Proto3.JsonInput.IgnoreUnknownJsonFalse.ProtobufOutput
-Required.Proto3.JsonInput.IgnoreUnknownJsonNull.ProtobufOutput
-Required.Proto3.JsonInput.IgnoreUnknownJsonNumber.ProtobufOutput
-Required.Proto3.JsonInput.IgnoreUnknownJsonObject.ProtobufOutput
-Required.Proto3.JsonInput.IgnoreUnknownJsonString.ProtobufOutput
-Required.Proto3.JsonInput.IgnoreUnknownJsonTrue.ProtobufOutput
-Required.Proto3.JsonInput.Int32FieldLeadingZero
-Required.Proto3.JsonInput.Int32FieldNegativeWithLeadingZero
-Required.Proto3.JsonInput.Int32FieldPlusSign
-Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool
-Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
-Required.Proto3.JsonInput.StringFieldNotAString
-Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
-Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
-Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
-Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
-Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.BOOL
-Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.INT32
-Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.INT64
-Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.SINT32
-Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.SINT64
-Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.UINT32
-Required.Proto3.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.UINT64
-Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.JsonOutput
-Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.ProtobufOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.BOOL.JsonOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.BOOL.ProtobufOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.BYTES.JsonOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.BYTES.ProtobufOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.ENUM.JsonOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.ENUM.ProtobufOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FIXED32.JsonOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FIXED32.ProtobufOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.JsonOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.ProtobufOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FLOAT.JsonOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FLOAT.ProtobufOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.INT32.JsonOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.INT32.ProtobufOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.INT64.JsonOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.INT64.ProtobufOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SFIXED32.JsonOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SFIXED32.ProtobufOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SFIXED64.JsonOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SFIXED64.ProtobufOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SINT32.JsonOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SINT32.ProtobufOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SINT64.JsonOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.SINT64.ProtobufOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.STRING.JsonOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.STRING.ProtobufOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.UINT32.JsonOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.UINT32.ProtobufOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.UINT64.JsonOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.UINT64.ProtobufOutput
-Required.Proto3.ProtobufInput.UnknownVarint.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.Default.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.Default.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateKey.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateKey.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateKeyInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateKeyInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateValueInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.DuplicateValueInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.MissingDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.MissingDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.NonDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.NonDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.Unordered.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.BOOL.BOOL.Unordered.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.Default.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.Default.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateKey.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateKey.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateKeyInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateKeyInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateValueInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.DuplicateValueInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.MissingDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.MissingDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.NonDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.NonDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.Unordered.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED32.FIXED32.Unordered.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.Default.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.Default.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateKey.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateKey.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateKeyInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateKeyInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateValueInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.DuplicateValueInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.MissingDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.MissingDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.NonDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.NonDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.Unordered.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.FIXED64.FIXED64.Unordered.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.Default.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.Default.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateKey.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateKey.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateKeyInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateKeyInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateValueInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.DuplicateValueInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.MissingDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.MissingDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.NonDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.NonDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.Unordered.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.DOUBLE.Unordered.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.Default.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.Default.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateKey.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateKey.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateKeyInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateKeyInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateValueInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.DuplicateValueInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.MissingDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.MissingDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.NonDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.NonDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.Unordered.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.FLOAT.Unordered.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.Default.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.Default.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateKey.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateKey.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateKeyInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateKeyInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateValueInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.DuplicateValueInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.MissingDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.MissingDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.NonDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.NonDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.Unordered.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT32.INT32.Unordered.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.Default.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.Default.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateKey.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateKey.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateKeyInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateKeyInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateValueInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.DuplicateValueInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.MissingDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.MissingDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.NonDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.NonDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.Unordered.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.INT64.INT64.Unordered.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.Default.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.Default.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateKey.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateKey.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateKeyInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateKeyInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateValueInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.DuplicateValueInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.MissingDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.MissingDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.NonDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.NonDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.Unordered.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED32.SFIXED32.Unordered.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.Default.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.Default.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateKey.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateKey.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateKeyInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateKeyInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateValueInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.DuplicateValueInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.MissingDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.MissingDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.NonDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.NonDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.Unordered.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SFIXED64.SFIXED64.Unordered.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.Default.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.Default.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateKey.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateKey.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateKeyInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateKeyInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateValueInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.DuplicateValueInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.MissingDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.MissingDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.NonDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.NonDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.Unordered.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT32.SINT32.Unordered.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.Default.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.Default.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateKey.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateKey.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateKeyInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateKeyInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateValueInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.DuplicateValueInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.MissingDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.MissingDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.NonDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.NonDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.Unordered.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.SINT64.SINT64.Unordered.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.Default.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.Default.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateKey.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateKey.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateKeyInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateKeyInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateValueInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.DuplicateValueInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.MissingDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.MissingDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.NonDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.NonDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.Unordered.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.BYTES.Unordered.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.Default.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.Default.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateKey.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateKey.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateKeyInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateKeyInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateValueInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.DuplicateValueInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.MissingDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.MissingDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.NonDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.NonDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.Unordered.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.ENUM.Unordered.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.Default.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.Default.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateKey.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateKey.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateKeyInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateKeyInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateValueInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.DuplicateValueInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.MergeValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.MergeValue.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.MissingDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.MissingDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.NonDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.NonDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.Unordered.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.Unordered.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.Default.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.Default.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateKey.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateKey.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateKeyInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateKeyInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateValueInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.DuplicateValueInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.MissingDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.MissingDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.NonDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.NonDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.Unordered.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.STRING.Unordered.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.Default.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.Default.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateKey.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateKey.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateKeyInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateKeyInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateValueInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.DuplicateValueInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.MissingDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.MissingDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.NonDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.NonDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.Unordered.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT32.UINT32.Unordered.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.Default.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.Default.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateKey.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateKey.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateKeyInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateKeyInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateValueInMapEntry.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.DuplicateValueInMapEntry.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.MissingDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.MissingDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.NonDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.NonDefault.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.Unordered.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.UINT64.UINT64.Unordered.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.DefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.DefaultValue.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.MultipleValuesForDifferentField.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.MultipleValuesForDifferentField.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.MultipleValuesForSameField.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.MultipleValuesForSameField.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.NonDefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.BOOL.NonDefaultValue.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.DefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.DefaultValue.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.MultipleValuesForDifferentField.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.MultipleValuesForDifferentField.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.MultipleValuesForSameField.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.MultipleValuesForSameField.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.NonDefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.BYTES.NonDefaultValue.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.DefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.DefaultValue.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.MultipleValuesForDifferentField.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.MultipleValuesForDifferentField.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.MultipleValuesForSameField.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.MultipleValuesForSameField.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.NonDefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.DOUBLE.NonDefaultValue.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.DefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.DefaultValue.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.MultipleValuesForDifferentField.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.MultipleValuesForDifferentField.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.MultipleValuesForSameField.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.MultipleValuesForSameField.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.NonDefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.ENUM.NonDefaultValue.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.DefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.DefaultValue.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.MultipleValuesForDifferentField.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.MultipleValuesForDifferentField.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.MultipleValuesForSameField.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.MultipleValuesForSameField.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.NonDefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.FLOAT.NonDefaultValue.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.DefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.DefaultValue.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.Merge.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.Merge.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.MultipleValuesForDifferentField.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.MultipleValuesForDifferentField.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.MultipleValuesForSameField.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.MultipleValuesForSameField.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.NonDefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.NonDefaultValue.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.STRING.DefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.STRING.DefaultValue.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.STRING.MultipleValuesForDifferentField.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.STRING.MultipleValuesForDifferentField.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.STRING.MultipleValuesForSameField.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.STRING.MultipleValuesForSameField.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.STRING.NonDefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.STRING.NonDefaultValue.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.DefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.DefaultValue.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.MultipleValuesForDifferentField.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.MultipleValuesForDifferentField.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.MultipleValuesForSameField.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.MultipleValuesForSameField.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.NonDefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.UINT32.NonDefaultValue.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.DefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.DefaultValue.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.MultipleValuesForDifferentField.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.MultipleValuesForDifferentField.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.MultipleValuesForSameField.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.MultipleValuesForSameField.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.NonDefaultValue.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataOneof.UINT64.NonDefaultValue.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.BYTES.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.MESSAGE.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.MESSAGE.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.STRING.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[2].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[2].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[3].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[3].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[4].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[4].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[5].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[5].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[6].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.BOOL[6].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.BYTES[3].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.BYTES[3].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.DOUBLE[1].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.DOUBLE[1].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.DOUBLE[2].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.DOUBLE[2].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[0].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[0].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[1].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[1].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[2].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[2].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[3].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[3].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[4].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[4].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[5].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[5].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.FIXED32[2].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.FIXED32[2].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.FIXED64[2].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.FIXED64[2].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[1].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[1].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[2].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[2].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[3].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[3].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[4].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[4].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT32[1].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT32[1].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT32[2].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT32[2].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT32[3].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT32[3].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT32[4].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT32[4].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT32[5].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT32[5].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT32[6].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT32[6].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT32[7].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT32[7].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT32[8].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT32[8].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT32[9].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT32[9].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT64[1].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT64[1].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT64[2].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT64[2].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT64[3].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT64[3].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.MESSAGE[0].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.MESSAGE[0].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.MESSAGE[1].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.MESSAGE[1].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED32[2].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED32[2].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED32[3].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED32[3].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED64[2].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED64[2].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED64[3].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED64[3].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[1].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[1].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[2].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[2].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[3].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[3].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[4].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SINT32[4].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[1].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[1].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[2].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[2].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[3].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[3].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.STRING[3].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.STRING[3].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.STRING[4].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.STRING[4].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.STRING[5].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.STRING[5].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.STRING[6].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.STRING[6].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[1].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[1].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[2].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[2].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[3].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[3].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[4].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[4].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[5].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[5].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[6].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[6].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[7].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[7].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[8].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[8].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[9].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[9].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT64[1].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT64[1].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT64[2].JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT64[2].ProtobufOutput
-Required.TimestampProtoInputTooLarge.JsonOutput
-Required.TimestampProtoInputTooSmall.JsonOutput
diff --git a/conformance/failure_list_ruby.txt b/conformance/failure_list_ruby.txt
index 1aea145..4938202 100644
--- a/conformance/failure_list_ruby.txt
+++ b/conformance/failure_list_ruby.txt
@@ -1,114 +1,58 @@
-Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
-Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
-Recommended.FieldMaskTooManyUnderscore.JsonOutput
 Recommended.Proto2.JsonInput.FieldNameExtension.Validator
-Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
-Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
-Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator
-Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator
-Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
-Recommended.Proto3.JsonInput.MapFieldValueIsNull
-Recommended.Proto3.JsonInput.NullValueInNormalMessage.Validator
-Recommended.Proto3.JsonInput.NullValueInOtherOneofNewFormat.Validator
-Recommended.Proto3.JsonInput.NullValueInOtherOneofOldFormat.Validator
-Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull
-Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull
-Recommended.Proto3.JsonInput.StringEndsWithEscapeChar
-Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder
-Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate
-Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
-Recommended.Proto3.JsonInput.TimestampHas3FractionalDigits.Validator
-Recommended.Proto3.JsonInput.TimestampHas6FractionalDigits.Validator
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT32.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT64.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.UnpackedInput.UnpackedOutput.ProtobufOutput
 Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
 Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[3].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[4].ProtobufOutput
-Required.DurationProtoInputTooLarge.JsonOutput
-Required.DurationProtoInputTooSmall.JsonOutput
-Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator
-Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
-Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
-Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.JsonOutput
-Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
-Required.Proto3.JsonInput.DoubleFieldNan.JsonOutput
-Required.Proto3.JsonInput.DurationMinValue.JsonOutput
-Required.Proto3.JsonInput.DurationRepeatedValue.JsonOutput
-Required.Proto3.JsonInput.FloatFieldInfinity.JsonOutput
-Required.Proto3.JsonInput.FloatFieldNan.JsonOutput
-Required.Proto3.JsonInput.FloatFieldNegativeInfinity.JsonOutput
-Required.Proto3.JsonInput.IgnoreUnknownJsonFalse.ProtobufOutput
-Required.Proto3.JsonInput.IgnoreUnknownJsonNull.ProtobufOutput
-Required.Proto3.JsonInput.IgnoreUnknownJsonNumber.ProtobufOutput
-Required.Proto3.JsonInput.IgnoreUnknownJsonObject.ProtobufOutput
-Required.Proto3.JsonInput.IgnoreUnknownJsonString.ProtobufOutput
-Required.Proto3.JsonInput.IgnoreUnknownJsonTrue.ProtobufOutput
-Required.Proto3.JsonInput.OneofFieldDuplicate
-Required.Proto3.JsonInput.RejectTopLevelNull
-Required.Proto3.JsonInput.StringFieldSurrogatePair.JsonOutput
-Required.Proto3.JsonInput.StringFieldSurrogatePair.ProtobufOutput
-Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
-Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
-Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
-Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataMap.STRING.MESSAGE.MissingDefault.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[2].JsonOutput
-Required.TimestampProtoInputTooLarge.JsonOutput
-Required.TimestampProtoInputTooSmall.JsonOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT32.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.UnpackedOutput.ProtobufOutput
+Recommended.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.UnpackedOutput.ProtobufOutput
diff --git a/conformance/text_format_failure_list_jruby.txt b/conformance/text_format_failure_list_jruby.txt
deleted file mode 100644
index 404b64a..0000000
--- a/conformance/text_format_failure_list_jruby.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-Recommended.Proto3.ProtobufInput.GroupUnknownFields_Drop.TextFormatOutput
-Recommended.Proto3.ProtobufInput.GroupUnknownFields_Print.TextFormatOutput
-Recommended.Proto3.ProtobufInput.MessageUnknownFields_Drop.TextFormatOutput
-Recommended.Proto3.ProtobufInput.MessageUnknownFields_Print.TextFormatOutput
-Recommended.Proto3.ProtobufInput.RepeatedUnknownFields_Drop.TextFormatOutput
-Recommended.Proto3.ProtobufInput.RepeatedUnknownFields_Print.TextFormatOutput
-Recommended.Proto3.ProtobufInput.ScalarUnknownFields_Drop.TextFormatOutput
-Recommended.Proto3.ProtobufInput.ScalarUnknownFields_Print.TextFormatOutput
diff --git a/java/core/src/main/java/com/google/protobuf/Descriptors.java b/java/core/src/main/java/com/google/protobuf/Descriptors.java
index c30b00d..51597fa 100644
--- a/java/core/src/main/java/com/google/protobuf/Descriptors.java
+++ b/java/core/src/main/java/com/google/protobuf/Descriptors.java
@@ -190,7 +190,7 @@
         name = packageName + '.' + name;
       }
       final GenericDescriptor result = pool.findSymbol(name);
-      if (result != null && result instanceof Descriptor && result.getFile() == this) {
+      if (result instanceof Descriptor && result.getFile() == this) {
         return (Descriptor) result;
       } else {
         return null;
@@ -214,7 +214,7 @@
         name = packageName + '.' + name;
       }
       final GenericDescriptor result = pool.findSymbol(name);
-      if (result != null && result instanceof EnumDescriptor && result.getFile() == this) {
+      if (result instanceof EnumDescriptor && result.getFile() == this) {
         return (EnumDescriptor) result;
       } else {
         return null;
@@ -238,7 +238,7 @@
         name = packageName + '.' + name;
       }
       final GenericDescriptor result = pool.findSymbol(name);
-      if (result != null && result instanceof ServiceDescriptor && result.getFile() == this) {
+      if (result instanceof ServiceDescriptor && result.getFile() == this) {
         return (ServiceDescriptor) result;
       } else {
         return null;
@@ -260,7 +260,7 @@
         name = packageName + '.' + name;
       }
       final GenericDescriptor result = pool.findSymbol(name);
-      if (result != null && result instanceof FieldDescriptor && result.getFile() == this) {
+      if (result instanceof FieldDescriptor && result.getFile() == this) {
         return (FieldDescriptor) result;
       } else {
         return null;
@@ -338,7 +338,7 @@
         final Class<?> descriptorOuterClass,
         final String[] dependencyClassNames,
         final String[] dependencyFileNames) {
-      List<FileDescriptor> descriptors = new ArrayList<FileDescriptor>();
+      List<FileDescriptor> descriptors = new ArrayList<>();
       for (int i = 0; i < dependencyClassNames.length; i++) {
         try {
           Class<?> clazz = descriptorOuterClass.getClassLoader().loadClass(dependencyClassNames[i]);
@@ -507,11 +507,11 @@
       this.pool = pool;
       this.proto = proto;
       this.dependencies = dependencies.clone();
-      HashMap<String, FileDescriptor> nameToFileMap = new HashMap<String, FileDescriptor>();
+      HashMap<String, FileDescriptor> nameToFileMap = new HashMap<>();
       for (FileDescriptor file : dependencies) {
         nameToFileMap.put(file.getName(), file);
       }
-      List<FileDescriptor> publicDependencies = new ArrayList<FileDescriptor>();
+      List<FileDescriptor> publicDependencies = new ArrayList<>();
       for (int i = 0; i < proto.getPublicDependencyCount(); i++) {
         int index = proto.getPublicDependency(i);
         if (index < 0 || index >= proto.getDependencyCount()) {
@@ -758,7 +758,7 @@
      * y" ranges declared on it.
      */
     public boolean isExtendable() {
-      return proto.getExtensionRangeList().size() != 0;
+      return !proto.getExtensionRangeList().isEmpty();
     }
 
     /**
@@ -772,7 +772,7 @@
      */
     public FieldDescriptor findFieldByName(final String name) {
       final GenericDescriptor result = file.pool.findSymbol(fullName + '.' + name);
-      if (result != null && result instanceof FieldDescriptor) {
+      if (result instanceof FieldDescriptor) {
         return (FieldDescriptor) result;
       } else {
         return null;
@@ -797,7 +797,7 @@
      */
     public Descriptor findNestedTypeByName(final String name) {
       final GenericDescriptor result = file.pool.findSymbol(fullName + '.' + name);
-      if (result != null && result instanceof Descriptor) {
+      if (result instanceof Descriptor) {
         return (Descriptor) result;
       } else {
         return null;
@@ -812,7 +812,7 @@
      */
     public EnumDescriptor findEnumTypeByName(final String name) {
       final GenericDescriptor result = file.pool.findSymbol(fullName + '.' + name);
-      if (result != null && result instanceof EnumDescriptor) {
+      if (result instanceof EnumDescriptor) {
         return (EnumDescriptor) result;
       } else {
         return null;
@@ -1701,7 +1701,7 @@
      */
     public EnumValueDescriptor findValueByName(final String name) {
       final GenericDescriptor result = file.pool.findSymbol(fullName + '.' + name);
-      if (result != null && result instanceof EnumValueDescriptor) {
+      if (result instanceof EnumValueDescriptor) {
         return (EnumValueDescriptor) result;
       } else {
         return null;
@@ -1785,7 +1785,7 @@
     private final Descriptor containingType;
     private EnumValueDescriptor[] values;
     private final WeakHashMap<Integer, WeakReference<EnumValueDescriptor>> unknownValues =
-        new WeakHashMap<Integer, WeakReference<EnumValueDescriptor>>();
+        new WeakHashMap<>();
 
     private EnumDescriptor(
         final EnumDescriptorProto proto,
@@ -1991,7 +1991,7 @@
      */
     public MethodDescriptor findMethodByName(final String name) {
       final GenericDescriptor result = file.pool.findSymbol(fullName + '.' + name);
-      if (result != null && result instanceof MethodDescriptor) {
+      if (result instanceof MethodDescriptor) {
         return (MethodDescriptor) result;
       } else {
         return null;
@@ -2265,12 +2265,12 @@
     }
 
     DescriptorPool(final FileDescriptor[] dependencies, boolean allowUnknownDependencies) {
-      this.dependencies = new HashSet<FileDescriptor>();
+      this.dependencies = new HashSet<>();
       this.allowUnknownDependencies = allowUnknownDependencies;
 
-      for (int i = 0; i < dependencies.length; i++) {
-        this.dependencies.add(dependencies[i]);
-        importPublicDependencies(dependencies[i]);
+      for (Descriptors.FileDescriptor dependency : dependencies) {
+        this.dependencies.add(dependency);
+        importPublicDependencies(dependency);
       }
 
       for (final FileDescriptor dependency : this.dependencies) {
@@ -2297,12 +2297,9 @@
     private final Set<FileDescriptor> dependencies;
     private boolean allowUnknownDependencies;
 
-    private final Map<String, GenericDescriptor> descriptorsByName =
-        new HashMap<String, GenericDescriptor>();
-    private final Map<DescriptorIntPair, FieldDescriptor> fieldsByNumber =
-        new HashMap<DescriptorIntPair, FieldDescriptor>();
-    private final Map<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber =
-        new HashMap<DescriptorIntPair, EnumValueDescriptor>();
+    private final Map<String, GenericDescriptor> descriptorsByName = new HashMap<>();
+    private final Map<DescriptorIntPair, FieldDescriptor> fieldsByNumber = new HashMap<>();
+    private final Map<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber = new HashMap<>();
 
     /** Find a generic descriptor by fully-qualified name. */
     GenericDescriptor findSymbol(final String fullName) {
diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
index 27f5210..5e3ee0f 100644
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -266,12 +266,14 @@
     memoizedSerializedSize = size;
   }
 
+  @Override
   public void writeTo(CodedOutputStream output) throws IOException {
     Protobuf.getInstance()
         .schemaFor(this)
         .writeTo(this, CodedOutputStreamWriter.forCodedOutput(output));
   }
 
+  @Override
   public int getSerializedSize() {
     if (memoizedSerializedSize == -1) {
       memoizedSerializedSize = Protobuf.getInstance().schemaFor(this).getSerializedSize(this);
diff --git a/java/core/src/main/java/com/google/protobuf/RawMessageInfo.java b/java/core/src/main/java/com/google/protobuf/RawMessageInfo.java
index 72f56ed..3fbfaa1 100644
--- a/java/core/src/main/java/com/google/protobuf/RawMessageInfo.java
+++ b/java/core/src/main/java/com/google/protobuf/RawMessageInfo.java
@@ -80,14 +80,15 @@
    *   <li>[1]: field type with extra bits:
    *       <ul>
    *         <li>v & 0xFF = field type as defined in the FieldType class
-   *         <li>v & 0x100 = is required?
-   *         <li>v & 0x200 = is checkUtf8?
-   *         <li>v & 0x400 = needs isInitialized check?
-   *         <li>v & 0x800 = is map field with proto2 enum value?
+   *         <li>v & 0x0100 = is required?
+   *         <li>v & 0x0200 = is checkUtf8?
+   *         <li>v & 0x0400 = needs isInitialized check?
+   *         <li>v & 0x0800 = is map field with proto2 enum value?
+   *         <li>v & 0x1000 = supports presence checking?
    *       </ul>
    * </ul>
    *
-   * If the file is proto2 and this is a singular field:
+   * If the (singular) field supports presence checking:
    *
    * <ul>
    *   <li>[2]: hasbits offset
@@ -180,8 +181,32 @@
     this.defaultInstance = defaultInstance;
     this.info = info;
     this.objects = objects;
-    int position = 0;
-    int value = (int) info.charAt(position++);
+    int value;
+    try {
+      value = (int) info.charAt(0);
+    } catch (ArrayIndexOutOfBoundsException e) {
+      // This is a fix for issues
+      // that error out on a subset of phones on charAt(0) with an index out of bounds exception.
+      char[] infoChars = info.toCharArray();
+      info = new String(infoChars);
+      try {
+        value = (int) info.charAt(0);
+      } catch (ArrayIndexOutOfBoundsException e2) {
+        try {
+          char[] infoChars2 = new char[info.length()];
+          info.getChars(0, info.length(), infoChars2, 0);
+          info = new String(infoChars2);
+          value = (int) info.charAt(0);
+        } catch (ArrayIndexOutOfBoundsException e3) {
+          throw new IllegalStateException(
+              String.format(
+                  "Failed parsing '%s' with charArray.length of %d", info, infoChars.length),
+              e3);
+        }
+      }
+    }
+    int position = 1;
+
     if (value < 0xD800) {
       flags = value;
     } else {
diff --git a/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java b/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
index b9b32af..0acf22e 100644
--- a/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
+++ b/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
@@ -332,83 +332,18 @@
     return new JvmMemoryAccessor(UNSAFE);
   }
 
-  /** Indicates whether or not unsafe array operations are supported on this platform. */
   private static boolean supportsUnsafeArrayOperations() {
-    if (UNSAFE == null) {
+    if (MEMORY_ACCESSOR == null) {
       return false;
     }
-    try {
-      Class<?> clazz = UNSAFE.getClass();
-      clazz.getMethod("objectFieldOffset", Field.class);
-      clazz.getMethod("arrayBaseOffset", Class.class);
-      clazz.getMethod("arrayIndexScale", Class.class);
-      clazz.getMethod("getInt", Object.class, long.class);
-      clazz.getMethod("putInt", Object.class, long.class, int.class);
-      clazz.getMethod("getLong", Object.class, long.class);
-      clazz.getMethod("putLong", Object.class, long.class, long.class);
-      clazz.getMethod("getObject", Object.class, long.class);
-      clazz.getMethod("putObject", Object.class, long.class, Object.class);
-      if (Android.isOnAndroidDevice()) {
-        return true;
-      }
-      clazz.getMethod("getByte", Object.class, long.class);
-      clazz.getMethod("putByte", Object.class, long.class, byte.class);
-      clazz.getMethod("getBoolean", Object.class, long.class);
-      clazz.getMethod("putBoolean", Object.class, long.class, boolean.class);
-      clazz.getMethod("getFloat", Object.class, long.class);
-      clazz.getMethod("putFloat", Object.class, long.class, float.class);
-      clazz.getMethod("getDouble", Object.class, long.class);
-      clazz.getMethod("putDouble", Object.class, long.class, double.class);
-
-      return true;
-    } catch (Throwable e) {
-      // Because log statements are fairly sparse in this class, this logger is initialized
-      // non-statically. Static initialization adds undue runtime costs to the first client to
-      // initialize this class.
-      Logger.getLogger(UnsafeUtil.class.getName())
-          .log(
-              Level.WARNING,
-              "platform method missing - proto runtime falling back to safer methods: " + e);
-    }
-    return false;
+    return MEMORY_ACCESSOR.supportsUnsafeArrayOperations();
   }
 
   private static boolean supportsUnsafeByteBufferOperations() {
-    if (UNSAFE == null) {
+    if (MEMORY_ACCESSOR == null) {
       return false;
     }
-    try {
-      Class<?> clazz = UNSAFE.getClass();
-      // Methods for getting direct buffer address.
-      clazz.getMethod("objectFieldOffset", Field.class);
-      clazz.getMethod("getLong", Object.class, long.class);
-
-      if (bufferAddressField() == null) {
-        return false;
-      }
-
-      if (Android.isOnAndroidDevice()) {
-        return false;
-      }
-      clazz.getMethod("getByte", long.class);
-      clazz.getMethod("putByte", long.class, byte.class);
-      clazz.getMethod("getInt", long.class);
-      clazz.getMethod("putInt", long.class, int.class);
-      clazz.getMethod("getLong", long.class);
-      clazz.getMethod("putLong", long.class, long.class);
-      clazz.getMethod("copyMemory", long.class, long.class, long.class);
-      clazz.getMethod("copyMemory", Object.class, long.class, Object.class, long.class, long.class);
-      return true;
-    } catch (Throwable e) {
-      // Because log statements are fairly sparse in this class, this logger is initialized
-      // non-statically. Static initialization adds undue runtime costs to the first client to
-      // initialize this class.
-      Logger.getLogger(UnsafeUtil.class.getName())
-          .log(
-              Level.WARNING,
-              "platform method missing - proto runtime falling back to safer methods: " + e);
-    }
-    return false;
+    return MEMORY_ACCESSOR.supportsUnsafeByteBufferOperations();
   }
 
   private static boolean determineAndroidSupportByAddressSize(Class<?> addressClass) {
@@ -553,6 +488,43 @@
       return unsafe.objectFieldOffset(field);
     }
 
+    public final int arrayBaseOffset(Class<?> clazz) {
+      return unsafe.arrayBaseOffset(clazz);
+    }
+
+    public final int arrayIndexScale(Class<?> clazz) {
+      return unsafe.arrayIndexScale(clazz);
+    }
+
+    public abstract Object getStaticObject(Field field);
+
+    // Relative Address Operations ---------------------------------------------
+
+    // Indicates whether the following relative address operations are supported
+    // by this memory accessor.
+    public boolean supportsUnsafeArrayOperations() {
+      if (unsafe == null) {
+        return false;
+      }
+      try {
+        Class<?> clazz = unsafe.getClass();
+        clazz.getMethod("objectFieldOffset", Field.class);
+        clazz.getMethod("arrayBaseOffset", Class.class);
+        clazz.getMethod("arrayIndexScale", Class.class);
+        clazz.getMethod("getInt", Object.class, long.class);
+        clazz.getMethod("putInt", Object.class, long.class, int.class);
+        clazz.getMethod("getLong", Object.class, long.class);
+        clazz.getMethod("putLong", Object.class, long.class, long.class);
+        clazz.getMethod("getObject", Object.class, long.class);
+        clazz.getMethod("putObject", Object.class, long.class, Object.class);
+
+        return true;
+      } catch (Throwable e) {
+        logMissingMethod(e);
+      }
+      return false;
+    }
+
     public abstract byte getByte(Object target, long offset);
 
     public abstract void putByte(Object target, long offset, byte value);
@@ -593,12 +565,29 @@
       unsafe.putObject(target, offset, value);
     }
 
-    public final int arrayBaseOffset(Class<?> clazz) {
-      return unsafe.arrayBaseOffset(clazz);
-    }
+    // Absolute Address Operations --------------------------------------------
 
-    public final int arrayIndexScale(Class<?> clazz) {
-      return unsafe.arrayIndexScale(clazz);
+    // Indicates whether the following absolute address operations are
+    // supported by this memory accessor.
+    public boolean supportsUnsafeByteBufferOperations() {
+      if (unsafe == null) {
+        return false;
+      }
+      try {
+        Class<?> clazz = unsafe.getClass();
+        // Methods for getting direct buffer address.
+        clazz.getMethod("objectFieldOffset", Field.class);
+        clazz.getMethod("getLong", Object.class, long.class);
+
+        if (bufferAddressField() == null) {
+          return false;
+        }
+
+        return true;
+      } catch (Throwable e) {
+        logMissingMethod(e);
+      }
+      return false;
     }
 
     public abstract byte getByte(long address);
@@ -613,8 +602,6 @@
 
     public abstract void putLong(long address, long value);
 
-    public abstract Object getStaticObject(Field field);
-
     public abstract void copyMemory(long srcOffset, byte[] target, long targetIndex, long length);
 
     public abstract void copyMemory(byte[] src, long srcIndex, long targetOffset, long length);
@@ -627,33 +614,32 @@
     }
 
     @Override
-    public byte getByte(long address) {
-      return unsafe.getByte(address);
+    public Object getStaticObject(Field field) {
+      return getObject(unsafe.staticFieldBase(field), unsafe.staticFieldOffset(field));
     }
 
     @Override
-    public void putByte(long address, byte value) {
-      unsafe.putByte(address, value);
-    }
+    public boolean supportsUnsafeArrayOperations() {
+      if (!super.supportsUnsafeArrayOperations()) {
+        return false;
+      }
 
-    @Override
-    public int getInt(long address) {
-      return unsafe.getInt(address);
-    }
+      try {
+        Class<?> clazz = unsafe.getClass();
+        clazz.getMethod("getByte", Object.class, long.class);
+        clazz.getMethod("putByte", Object.class, long.class, byte.class);
+        clazz.getMethod("getBoolean", Object.class, long.class);
+        clazz.getMethod("putBoolean", Object.class, long.class, boolean.class);
+        clazz.getMethod("getFloat", Object.class, long.class);
+        clazz.getMethod("putFloat", Object.class, long.class, float.class);
+        clazz.getMethod("getDouble", Object.class, long.class);
+        clazz.getMethod("putDouble", Object.class, long.class, double.class);
 
-    @Override
-    public void putInt(long address, int value) {
-      unsafe.putInt(address, value);
-    }
-
-    @Override
-    public long getLong(long address) {
-      return unsafe.getLong(address);
-    }
-
-    @Override
-    public void putLong(long address, long value) {
-      unsafe.putLong(address, value);
+        return true;
+      } catch (Throwable e) {
+        logMissingMethod(e);
+      }
+      return false;
     }
 
     @Override
@@ -697,6 +683,60 @@
     }
 
     @Override
+    public boolean supportsUnsafeByteBufferOperations() {
+      if (!super.supportsUnsafeByteBufferOperations()) {
+        return false;
+      }
+
+      try {
+        Class<?> clazz = unsafe.getClass();
+        clazz.getMethod("getByte", long.class);
+        clazz.getMethod("putByte", long.class, byte.class);
+        clazz.getMethod("getInt", long.class);
+        clazz.getMethod("putInt", long.class, int.class);
+        clazz.getMethod("getLong", long.class);
+        clazz.getMethod("putLong", long.class, long.class);
+        clazz.getMethod("copyMemory", long.class, long.class, long.class);
+        clazz.getMethod(
+            "copyMemory", Object.class, long.class, Object.class, long.class, long.class);
+        return true;
+      } catch (Throwable e) {
+        logMissingMethod(e);
+      }
+      return false;
+    }
+
+    @Override
+    public byte getByte(long address) {
+      return unsafe.getByte(address);
+    }
+
+    @Override
+    public void putByte(long address, byte value) {
+      unsafe.putByte(address, value);
+    }
+
+    @Override
+    public int getInt(long address) {
+      return unsafe.getInt(address);
+    }
+
+    @Override
+    public void putInt(long address, int value) {
+      unsafe.putInt(address, value);
+    }
+
+    @Override
+    public long getLong(long address) {
+      return unsafe.getLong(address);
+    }
+
+    @Override
+    public void putLong(long address, long value) {
+      unsafe.putLong(address, value);
+    }
+
+    @Override
     public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
       unsafe.copyMemory(null, srcOffset, target, BYTE_ARRAY_BASE_OFFSET + targetIndex, length);
     }
@@ -705,11 +745,6 @@
     public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
       unsafe.copyMemory(src, BYTE_ARRAY_BASE_OFFSET + srcIndex, null, targetOffset, length);
     }
-
-    @Override
-    public Object getStaticObject(Field field) {
-      return getObject(unsafe.staticFieldBase(field), unsafe.staticFieldOffset(field));
-    }
   }
 
   private static final class Android64MemoryAccessor extends MemoryAccessor {
@@ -719,33 +754,12 @@
     }
 
     @Override
-    public byte getByte(long address) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void putByte(long address, byte value) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public int getInt(long address) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void putInt(long address, int value) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public long getLong(long address) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void putLong(long address, long value) {
-      throw new UnsupportedOperationException();
+    public Object getStaticObject(Field field) {
+      try {
+        return field.get(null);
+      } catch (IllegalAccessException e) {
+        return null;
+      }
     }
 
     @Override
@@ -805,6 +819,41 @@
     }
 
     @Override
+    public boolean supportsUnsafeByteBufferOperations() {
+      return false;
+    }
+
+    @Override
+    public byte getByte(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putByte(long address, byte value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int getInt(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putInt(long address, int value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public long getLong(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putLong(long address, long value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
     public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
       throw new UnsupportedOperationException();
     }
@@ -813,15 +862,6 @@
     public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
       throw new UnsupportedOperationException();
     }
-
-    @Override
-    public Object getStaticObject(Field field) {
-      try {
-        return field.get(null);
-      } catch (IllegalAccessException e) {
-        return null;
-      }
-    }
   }
 
   private static final class Android32MemoryAccessor extends MemoryAccessor {
@@ -839,33 +879,12 @@
     }
 
     @Override
-    public byte getByte(long address) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void putByte(long address, byte value) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public int getInt(long address) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void putInt(long address, int value) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public long getLong(long address) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void putLong(long address, long value) {
-      throw new UnsupportedOperationException();
+    public Object getStaticObject(Field field) {
+      try {
+        return field.get(null);
+      } catch (IllegalAccessException e) {
+        return null;
+      }
     }
 
     @Override
@@ -925,6 +944,41 @@
     }
 
     @Override
+    public boolean supportsUnsafeByteBufferOperations() {
+      return false;
+    }
+
+    @Override
+    public byte getByte(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putByte(long address, byte value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int getInt(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putInt(long address, int value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public long getLong(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putLong(long address, long value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
     public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
       throw new UnsupportedOperationException();
     }
@@ -933,15 +987,6 @@
     public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
       throw new UnsupportedOperationException();
     }
-
-    @Override
-    public Object getStaticObject(Field field) {
-      try {
-        return field.get(null);
-      } catch (IllegalAccessException e) {
-        return null;
-      }
-    }
   }
 
   private static byte getByteBigEndian(Object target, long offset) {
@@ -981,4 +1026,11 @@
   private static void putBooleanLittleEndian(Object target, long offset, boolean value) {
     putByteLittleEndian(target, offset, (byte) (value ? 1 : 0));
   }
+
+  private static void logMissingMethod(Throwable e) {
+    Logger.getLogger(UnsafeUtil.class.getName())
+        .log(
+            Level.WARNING,
+            "platform method missing - proto runtime falling back to safer methods: " + e);
+  }
 }
diff --git a/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java b/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
index a1c98c0..7266729 100644
--- a/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
+++ b/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
@@ -66,6 +66,11 @@
     assertFalse(hasMethod(classWithoutFieldPresence, "has" + camelName));
   }
 
+  private static void assertHasMethodExisting(Class<?> clazz, String camelName) {
+    assertTrue(hasMethod(clazz, "get" + camelName));
+    assertTrue(hasMethod(clazz, "has" + camelName));
+  }
+
   public void testHasMethod() {
     // Optional non-message fields don't have a hasFoo() method generated.
     assertHasMethodRemoved(UnittestProto.TestAllTypes.class, TestAllTypes.class, "OptionalInt32");
@@ -87,19 +92,16 @@
     assertFalse(TestAllTypes.getDefaultInstance().hasOptionalNestedMessage());
     assertFalse(TestAllTypes.newBuilder().hasOptionalNestedMessage());
 
-    // oneof fields don't have hasFoo() methods for non-message types.
-    assertHasMethodRemoved(UnittestProto.TestAllTypes.class, TestAllTypes.class, "OneofUint32");
-    assertHasMethodRemoved(UnittestProto.TestAllTypes.class, TestAllTypes.class, "OneofString");
-    assertHasMethodRemoved(UnittestProto.TestAllTypes.class, TestAllTypes.class, "OneofBytes");
+    // oneof fields support hasFoo() methods for non-message types.
+    assertHasMethodExisting(TestAllTypes.class, "OneofUint32");
+    assertHasMethodExisting(TestAllTypes.class, "OneofString");
+    assertHasMethodExisting(TestAllTypes.class, "OneofBytes");
     assertFalse(TestAllTypes.getDefaultInstance().hasOneofNestedMessage());
     assertFalse(TestAllTypes.newBuilder().hasOneofNestedMessage());
 
-    assertHasMethodRemoved(
-        UnittestProto.TestAllTypes.Builder.class, TestAllTypes.Builder.class, "OneofUint32");
-    assertHasMethodRemoved(
-        UnittestProto.TestAllTypes.Builder.class, TestAllTypes.Builder.class, "OneofString");
-    assertHasMethodRemoved(
-        UnittestProto.TestAllTypes.Builder.class, TestAllTypes.Builder.class, "OneofBytes");
+    assertHasMethodExisting(TestAllTypes.Builder.class, "OneofUint32");
+    assertHasMethodExisting(TestAllTypes.Builder.class, "OneofString");
+    assertHasMethodExisting(TestAllTypes.Builder.class, "OneofBytes");
   }
 
   public void testHasMethodForProto3Optional() throws Exception {
diff --git a/java/core/src/test/java/com/google/protobuf/Proto3MessageLiteInfoFactory.java b/java/core/src/test/java/com/google/protobuf/Proto3MessageLiteInfoFactory.java
index 66e406a..3c0c629 100644
--- a/java/core/src/test/java/com/google/protobuf/Proto3MessageLiteInfoFactory.java
+++ b/java/core/src/test/java/com/google/protobuf/Proto3MessageLiteInfoFactory.java
@@ -139,12 +139,12 @@
     // the content of the generated buildMessageInfo() method here.
     java.lang.String info =
         "\u0000@\u0001\u0000\u0001D@\u0000\u001f\u0000\u0001\u0000\u0002\u0001\u0003\u0002"
-            + "\u0004\u0003\u0005\u0004\u0006\u0005\u0007\u0006\b\u0007\t\u0208\n\t\u000b\n\f\u000b"
-            + "\r\f\u000e\r\u000f\u000e\u0010\u000f\u0011\u0010\u0012\u0012\u0013\u0013\u0014\u0014"
-            + "\u0015\u0015\u0016\u0016\u0017\u0017\u0018\u0018\u0019\u0019\u001a\u021a\u001b\u001b"
-            + "\u001c\u001c\u001d\u001d\u001e\u001e\u001f\u001f  !!\"\"##$$%%&&\'\'(())**++,,--"
-            + "..//0053\u000064\u000075\u000086\u000097\u0000:8\u0000;9\u0000<:\u0000=\u023b\u0000"
-            + "><\u0000?=\u0000@>\u0000A@\u0000BA\u0000CB\u0000DC\u0000";
+        + "\u0004\u0003\u0005\u0004\u0006\u0005\u0007\u0006\b\u0007\t\u0208\n\t\u000b\n\f\u000b"
+        + "\r\f\u000e\r\u000f\u000e\u0010\u000f\u0011\u0010\u0012\u0012\u0013\u0013\u0014\u0014"
+        + "\u0015\u0015\u0016\u0016\u0017\u0017\u0018\u0018\u0019\u0019\u001a\u021a\u001b\u001b"
+        + "\u001c\u001c\u001d\u001d\u001e\u001e\u001f\u001f  !!\"\"##$$%%&&\'\'(())**++,,--"
+        + "..//0053\u000064\u000075\u000086\u000097\u0000:8\u0000;9\u0000<:\u0000=\u023b\u0000"
+        + "><\u0000?=\u0000@>\u0000A@\u0000BA\u0000CB\u0000DC\u0000";
     return new RawMessageInfo(Proto3MessageLite.getDefaultInstance(), info, objects);
   }
 
diff --git a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
index 915dddf..a919f3b 100644
--- a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
+++ b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -1507,9 +1507,9 @@
             + "  value: -1\n"
             + "}\n";
     TestMap msg = TextFormat.parse(input, TestMap.class);
-    int i1 = msg.getInt32ToInt32Field().get(1);
+    int i1 = msg.getInt32ToInt32FieldMap().get(1);
     TestMap msg2 = TextFormat.parse(msg.toString(), TestMap.class);
-    int i2 = msg2.getInt32ToInt32Field().get(1);
+    int i2 = msg2.getInt32ToInt32FieldMap().get(1);
     assertEquals(i1, i2);
   }
 
@@ -1521,10 +1521,10 @@
     TestMap.Builder dest = TestMap.newBuilder();
     parserWithOverwriteForbidden.merge(text, dest);
     TestMap message = dest.build();
-    assertEquals(2, message.getStringToInt32Field().size());
-    assertEquals(2, message.getInt32ToMessageField().size());
-    assertEquals(10, message.getStringToInt32Field().get("x").intValue());
-    assertEquals(200, message.getInt32ToMessageField().get(2).getValue());
+    assertEquals(2, message.getStringToInt32FieldMap().size());
+    assertEquals(2, message.getInt32ToMessageFieldMap().size());
+    assertEquals(10, message.getStringToInt32FieldMap().get("x").intValue());
+    assertEquals(200, message.getInt32ToMessageFieldMap().get(2).getValue());
   }
 
   public void testMapShortFormEmpty() throws Exception {
@@ -1532,8 +1532,8 @@
     TestMap.Builder dest = TestMap.newBuilder();
     parserWithOverwriteForbidden.merge(text, dest);
     TestMap message = dest.build();
-    assertEquals(0, message.getStringToInt32Field().size());
-    assertEquals(0, message.getInt32ToMessageField().size());
+    assertEquals(0, message.getStringToInt32FieldMap().size());
+    assertEquals(0, message.getInt32ToMessageFieldMap().size());
   }
 
   public void testMapShortFormTrailingComma() throws Exception {
@@ -1558,8 +1558,8 @@
       TestMap.Builder builder = TestMap.newBuilder();
       defaultParser.merge(text, builder);
       TestMap map = builder.build();
-      assertEquals(2, map.getInt32ToInt32Field().size());
-      assertEquals(30, map.getInt32ToInt32Field().get(1).intValue());
+      assertEquals(2, map.getInt32ToInt32FieldMap().size());
+      assertEquals(30, map.getInt32ToInt32FieldMap().get(1).intValue());
     }
 
     {
@@ -1568,8 +1568,8 @@
       TestMap.Builder builder = TestMap.newBuilder();
       parserWithOverwriteForbidden.merge(text, builder);
       TestMap map = builder.build();
-      assertEquals(2, map.getInt32ToInt32Field().size());
-      assertEquals(30, map.getInt32ToInt32Field().get(1).intValue());
+      assertEquals(2, map.getInt32ToInt32FieldMap().size());
+      assertEquals(30, map.getInt32ToInt32FieldMap().get(1).intValue());
     }
 
     {
@@ -1580,8 +1580,8 @@
       TestMap map =
           TestMap.parseFrom(
               builder.build().toByteString(), ExtensionRegistryLite.getEmptyRegistry());
-      assertEquals(2, map.getInt32ToInt32Field().size());
-      assertEquals(30, map.getInt32ToInt32Field().get(1).intValue());
+      assertEquals(2, map.getInt32ToInt32FieldMap().size());
+      assertEquals(30, map.getInt32ToInt32FieldMap().get(1).intValue());
     }
   }
 
diff --git a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
index 46d3cc4..6133bb4 100644
--- a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
+++ b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
@@ -1697,6 +1697,7 @@
   public void testJsonException() throws Exception {
     InputStream throwingInputStream =
         new InputStream() {
+          @Override
           public int read() throws IOException {
             throw new IOException("12345");
           }
diff --git a/js/binary/decoder_test.js b/js/binary/decoder_test.js
index 8fce993..0fddc4b 100644
--- a/js/binary/decoder_test.js
+++ b/js/binary/decoder_test.js
@@ -315,8 +315,8 @@
         // 64-bit extremes, not in dev guide.
         {original: '9223372036854775807', zigzag: '18446744073709551614'},
         {original: '-9223372036854775808', zigzag: '18446744073709551615'},
-        // None of the above catch: bitsLow < 0 && bitsHigh > 0 && bitsHigh < 0x1FFFFF.
-        // The following used to be broken.
+        // None of the above catch: bitsLow < 0 && bitsHigh > 0 && bitsHigh <
+        // 0x1FFFFF. The following used to be broken.
         {original: '72000000000', zigzag: '144000000000'},
       ];
       var encoder = new jspb.BinaryEncoder();
diff --git a/kokoro/linux/dockerfile/test/ruby/Dockerfile b/kokoro/linux/dockerfile/test/ruby/Dockerfile
index 9037da7..b73bf84 100644
--- a/kokoro/linux/dockerfile/test/ruby/Dockerfile
+++ b/kokoro/linux/dockerfile/test/ruby/Dockerfile
@@ -26,13 +26,14 @@
 RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys \
     409B6B1796C275462A1703113804BB82D39DC0E3 \
     7D2BAF1CF37B13E2069D6956105BD0E739499BDB
-RUN \curl -sSL https://get.rvm.io | bash -s stable
+RUN \curl -sSL https://get.rvm.io | bash -s master
 
 RUN /bin/bash -l -c "rvm install 2.3.8"
 RUN /bin/bash -l -c "rvm install 2.4.5"
 RUN /bin/bash -l -c "rvm install 2.5.1"
 RUN /bin/bash -l -c "rvm install 2.6.0"
 RUN /bin/bash -l -c "rvm install 2.7.0"
+RUN /bin/bash -l -c "rvm install 3.0.0"
 
 RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
 RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
diff --git a/kokoro/linux/ruby30/build.sh b/kokoro/linux/ruby30/build.sh
new file mode 100755
index 0000000..9e44575
--- /dev/null
+++ b/kokoro/linux/ruby30/build.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+# This is the top-level script we give to Kokoro as the entry point for
+# running the "pull request" project:
+#
+# This script selects a specific Dockerfile (for building a Docker image) and
+# a script to run inside that image.  Then we delegate to the general
+# build_and_run_docker.sh script.
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+export DOCKERHUB_ORGANIZATION=protobuftesting
+export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/ruby
+export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
+export OUTPUT_DIR=testoutput
+export TEST_SET="ruby30"
+./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/ruby30/continuous.cfg b/kokoro/linux/ruby30/continuous.cfg
new file mode 100644
index 0000000..b03a335
--- /dev/null
+++ b/kokoro/linux/ruby30/continuous.cfg
@@ -0,0 +1,11 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/ruby30/build.sh"
+timeout_mins: 120
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.xml"
+  }
+}
diff --git a/kokoro/linux/ruby30/presubmit.cfg b/kokoro/linux/ruby30/presubmit.cfg
new file mode 100644
index 0000000..b03a335
--- /dev/null
+++ b/kokoro/linux/ruby30/presubmit.cfg
@@ -0,0 +1,11 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/ruby30/build.sh"
+timeout_mins: 120
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.xml"
+  }
+}
diff --git a/kokoro/macos/prepare_build_macos_rc b/kokoro/macos/prepare_build_macos_rc
index d1154e3..d94dd54 100755
--- a/kokoro/macos/prepare_build_macos_rc
+++ b/kokoro/macos/prepare_build_macos_rc
@@ -80,5 +80,5 @@
   curl -sSL https://rvm.io/mpapis.asc | gpg --import -
   curl -sSL https://rvm.io/pkuczynski.asc | gpg --import -
 
-  curl -sSL https://get.rvm.io | bash -s stable --ruby
+  curl -sSL https://get.rvm.io | bash -s master --ruby
 fi
diff --git a/kokoro/macos/ruby30/build.sh b/kokoro/macos/ruby30/build.sh
new file mode 100755
index 0000000..6b9bfb3
--- /dev/null
+++ b/kokoro/macos/ruby30/build.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+#
+# Build file to set up and run tests
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Prepare worker environment to run tests
+KOKORO_INSTALL_RUBY=yes
+KOKORO_INSTALL_RVM=yes
+source kokoro/macos/prepare_build_macos_rc
+
+./tests.sh ruby30
diff --git a/kokoro/macos/ruby30/continuous.cfg b/kokoro/macos/ruby30/continuous.cfg
new file mode 100644
index 0000000..d505117
--- /dev/null
+++ b/kokoro/macos/ruby30/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/ruby30/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/ruby30/presubmit.cfg b/kokoro/macos/ruby30/presubmit.cfg
new file mode 100644
index 0000000..d505117
--- /dev/null
+++ b/kokoro/macos/ruby30/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/ruby30/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/release/ruby/macos/ruby/ruby_build_environment.sh b/kokoro/release/ruby/macos/ruby/ruby_build_environment.sh
index 880c233..046b604 100755
--- a/kokoro/release/ruby/macos/ruby/ruby_build_environment.sh
+++ b/kokoro/release/ruby/macos/ruby/ruby_build_environment.sh
@@ -21,13 +21,13 @@
 
 CROSS_RUBY=$(mktemp tmpfile.XXXXXXXX)
 
-curl https://raw.githubusercontent.com/rake-compiler/rake-compiler/v1.1.0/tasks/bin/cross-ruby.rake > "$CROSS_RUBY"
+curl https://raw.githubusercontent.com/rake-compiler/rake-compiler/72184e51779b6a3b9b8580b036a052fdc3181ced/tasks/bin/cross-ruby.rake > "$CROSS_RUBY"
 
 # See https://github.com/grpc/grpc/issues/12161 for verconf.h patch details
 patch "$CROSS_RUBY" << EOF
---- cross-ruby.rake	2018-04-10 11:32:16.000000000 -0700
-+++ patched	2018-04-10 11:40:25.000000000 -0700
-@@ -141,8 +141,10 @@
+--- cross-ruby.rake	2020-12-11 11:17:53.000000000 +0900
++++ patched	2020-12-11 11:18:52.000000000 +0900
+@@ -111,10 +111,12 @@
      "--host=#{MINGW_HOST}",
      "--target=#{MINGW_TARGET}",
      "--build=#{RUBY_BUILD}",
@@ -36,10 +36,13 @@
 +    '--disable-shared',
      '--disable-install-doc',
 +    '--without-gmp',
-     '--with-ext='
+     '--with-ext=',
+-    'LDFLAGS=-pipe -s',
++    'LDFLAGS=-pipe',
    ]
 
-@@ -159,6 +161,7 @@
+   # Force Winsock2 for Ruby 1.8, 1.9 defaults to it
+@@ -130,6 +132,7 @@
  # make
  file "#{build_dir}/ruby.exe" => ["#{build_dir}/Makefile"] do |t|
    chdir File.dirname(t.prerequisites.first) do
@@ -55,7 +58,7 @@
 rvm use 2.7.0
 set -x
 ruby --version | grep 'ruby 2.7.0'
-for v in 2.7.0 ; do
+for v in 3.0.0 2.7.0 ; do
   ccache -c
   rake -f "$CROSS_RUBY" cross-ruby VERSION="$v" HOST=x86_64-darwin11 MAKE="$MAKE"
 done
diff --git a/python/google/protobuf/descriptor.py b/python/google/protobuf/descriptor.py
index 7583ea3..190b895 100644
--- a/python/google/protobuf/descriptor.py
+++ b/python/google/protobuf/descriptor.py
@@ -287,12 +287,26 @@
   if _USE_C_DESCRIPTORS:
     _C_DESCRIPTOR_CLASS = _message.Descriptor
 
-    def __new__(cls, name, full_name, filename, containing_type, fields,
-                nested_types, enum_types, extensions, options=None,
-                serialized_options=None,
-                is_extendable=True, extension_ranges=None, oneofs=None,
-                file=None, serialized_start=None, serialized_end=None,  # pylint: disable=redefined-builtin
-                syntax=None, create_key=None):
+    def __new__(
+        cls,
+        name=None,
+        full_name=None,
+        filename=None,
+        containing_type=None,
+        fields=None,
+        nested_types=None,
+        enum_types=None,
+        extensions=None,
+        options=None,
+        serialized_options=None,
+        is_extendable=True,
+        extension_ranges=None,
+        oneofs=None,
+        file=None,  # pylint: disable=redefined-builtin
+        serialized_start=None,
+        serialized_end=None,
+        syntax=None,
+        create_key=None):
       _message.Message._CheckCalledFromGeneratedFile()
       return _message.default_pool.FindMessageTypeByName(full_name)
 
@@ -799,9 +813,18 @@
   if _USE_C_DESCRIPTORS:
     _C_DESCRIPTOR_CLASS = _message.ServiceDescriptor
 
-    def __new__(cls, name, full_name, index, methods, options=None,
-                serialized_options=None, file=None,  # pylint: disable=redefined-builtin
-                serialized_start=None, serialized_end=None, create_key=None):
+    def __new__(
+        cls,
+        name=None,
+        full_name=None,
+        index=None,
+        methods=None,
+        options=None,
+        serialized_options=None,
+        file=None,  # pylint: disable=redefined-builtin
+        serialized_start=None,
+        serialized_end=None,
+        create_key=None):
       _message.Message._CheckCalledFromGeneratedFile()  # pylint: disable=protected-access
       return _message.default_pool.FindServiceByName(full_name)
 
diff --git a/python/google/protobuf/internal/factory_test1.proto b/python/google/protobuf/internal/factory_test1.proto
index f5bd038..5e729f5 100644
--- a/python/google/protobuf/internal/factory_test1.proto
+++ b/python/google/protobuf/internal/factory_test1.proto
@@ -34,7 +34,6 @@
 
 package google.protobuf.python.internal;
 
-
 enum Factory1Enum {
   FACTORY_1_VALUE_0 = 0;
   FACTORY_1_VALUE_1 = 1;
@@ -67,6 +66,5 @@
 
 service Factory1Service {
   // Dummy method for this dummy service.
-  rpc Factory1Method(Factory1MethodRequest) returns (Factory1MethodResponse) {
-  }
+  rpc Factory1Method(Factory1MethodRequest) returns (Factory1MethodResponse) {}
 }
diff --git a/python/google/protobuf/internal/message_factory_test.py b/python/google/protobuf/internal/message_factory_test.py
index 24b79ec..42f91b2 100755
--- a/python/google/protobuf/internal/message_factory_test.py
+++ b/python/google/protobuf/internal/message_factory_test.py
@@ -106,6 +106,23 @@
         'google.protobuf.python.internal.Factory2Message'))
     self.assertTrue(cls is cls2)
 
+  def testCreatePrototypeOverride(self):
+    class MyMessageFactory(message_factory.MessageFactory):
+
+      def CreatePrototype(self, descriptor):
+        cls = super(MyMessageFactory, self).CreatePrototype(descriptor)
+        cls.additional_field = 'Some value'
+        return cls
+
+    db = descriptor_database.DescriptorDatabase()
+    pool = descriptor_pool.DescriptorPool(db)
+    db.Add(self.factory_test1_fd)
+    db.Add(self.factory_test2_fd)
+    factory = MyMessageFactory()
+    cls = factory.GetPrototype(pool.FindMessageTypeByName(
+        'google.protobuf.python.internal.Factory2Message'))
+    self.assertTrue(hasattr(cls, 'additional_field'))
+
   def testGetMessages(self):
     # performed twice because multiple calls with the same input must be allowed
     for _ in range(2):
diff --git a/python/google/protobuf/internal/unknown_fields_test.py b/python/google/protobuf/internal/unknown_fields_test.py
index a60b942..d0ac5d9 100755
--- a/python/google/protobuf/internal/unknown_fields_test.py
+++ b/python/google/protobuf/internal/unknown_fields_test.py
@@ -40,11 +40,6 @@
 except ImportError:
   import unittest
 import sys
-try:
-  import tracemalloc
-except ImportError:
-  # Requires python 3.4+
-  pass
 from google.protobuf import map_unittest_pb2
 from google.protobuf import unittest_mset_pb2
 from google.protobuf import unittest_pb2
@@ -59,6 +54,12 @@
 from google.protobuf.internal import wire_format
 from google.protobuf import descriptor
 
+try:
+  import tracemalloc  # pylint: disable=g-import-not-at-top
+except ImportError:
+  # Requires python 3.4+
+  pass
+
 
 @testing_refleaks.TestCase
 class UnknownFieldsTest(unittest.TestCase):
@@ -318,14 +319,16 @@
     self.assertIn('UnknownFields does not exist.',
                   str(context.exception))
 
-  @unittest.skipIf((sys.version_info.major, sys.version_info.minor) < (3, 4), 
+  @unittest.skipIf((sys.version_info.major, sys.version_info.minor) < (3, 4),
                    'tracemalloc requires python 3.4+')
   def testUnknownFieldsNoMemoryLeak(self):
     # Call to UnknownFields must not leak memory
     nb_leaks = 1234
+
     def leaking_function():
       for _ in range(nb_leaks):
         self.empty_message.UnknownFields()
+
     tracemalloc.start()
     snapshot1 = tracemalloc.take_snapshot()
     leaking_function()
diff --git a/python/google/protobuf/message_factory.py b/python/google/protobuf/message_factory.py
index 24a524a..7dfaec8 100644
--- a/python/google/protobuf/message_factory.py
+++ b/python/google/protobuf/message_factory.py
@@ -64,7 +64,7 @@
     self._classes = {}
 
   def GetPrototype(self, descriptor):
-    """Builds a proto2 message class based on the passed in descriptor.
+    """Obtains a proto2 message class based on the passed in descriptor.
 
     Passing a descriptor with a fully qualified name matching a previous
     invocation will cause the same class to be returned.
@@ -76,27 +76,52 @@
       A class describing the passed in descriptor.
     """
     if descriptor not in self._classes:
-      descriptor_name = descriptor.name
-      if str is bytes:  # PY2
-        descriptor_name = descriptor.name.encode('ascii', 'ignore')
-      result_class = _GENERATED_PROTOCOL_MESSAGE_TYPE(
-          descriptor_name,
-          (message.Message,),
-          {'DESCRIPTOR': descriptor, '__module__': None})
-      # pylint: disable=protected-access
-      result_class._FACTORY = self
-      # If module not set, it wrongly points to message_factory module.
+      result_class = self.CreatePrototype(descriptor)
+      # The assignment to _classes is redundant for the base implementation, but
+      # might avoid confusion in cases where CreatePrototype gets overridden and
+      # does not call the base implementation.
       self._classes[descriptor] = result_class
-      for field in descriptor.fields:
-        if field.message_type:
-          self.GetPrototype(field.message_type)
-      for extension in result_class.DESCRIPTOR.extensions:
-        if extension.containing_type not in self._classes:
-          self.GetPrototype(extension.containing_type)
-        extended_class = self._classes[extension.containing_type]
-        extended_class.RegisterExtension(extension)
+      return result_class
     return self._classes[descriptor]
 
+  def CreatePrototype(self, descriptor):
+    """Builds a proto2 message class based on the passed in descriptor.
+
+    Don't call this function directly, it always creates a new class. Call
+    GetPrototype() instead. This method is meant to be overridden in subblasses
+    to perform additional operations on the newly constructed class.
+
+    Args:
+      descriptor: The descriptor to build from.
+
+    Returns:
+      A class describing the passed in descriptor.
+    """
+    descriptor_name = descriptor.name
+    if str is bytes:  # PY2
+      descriptor_name = descriptor.name.encode('ascii', 'ignore')
+    result_class = _GENERATED_PROTOCOL_MESSAGE_TYPE(
+        descriptor_name,
+        (message.Message,),
+        {
+            'DESCRIPTOR': descriptor,
+            # If module not set, it wrongly points to message_factory module.
+            '__module__': None,
+        })
+    result_class._FACTORY = self  # pylint: disable=protected-access
+    # Assign in _classes before doing recursive calls to avoid infinite
+    # recursion.
+    self._classes[descriptor] = result_class
+    for field in descriptor.fields:
+      if field.message_type:
+        self.GetPrototype(field.message_type)
+    for extension in result_class.DESCRIPTOR.extensions:
+      if extension.containing_type not in self._classes:
+        self.GetPrototype(extension.containing_type)
+      extended_class = self._classes[extension.containing_type]
+      extended_class.RegisterExtension(extension)
+    return result_class
+
   def GetMessages(self, files):
     """Gets all the messages from a specified file.
 
diff --git a/python/google/protobuf/proto_api.h b/python/google/protobuf/proto_api.h
index 75ee979..c869bce 100644
--- a/python/google/protobuf/proto_api.h
+++ b/python/google/protobuf/proto_api.h
@@ -82,6 +82,32 @@
   // to create Python-compatible message.
   virtual const DescriptorPool* GetDefaultDescriptorPool() const = 0;
   virtual MessageFactory* GetDefaultMessageFactory() const = 0;
+
+  // Allocate a new protocol buffer as a python object for the provided
+  // descriptor. This function works even if no Python module has been imported
+  // for the corresponding protocol buffer class.
+  // The factory is usually null; when provided, it is the MessageFactory which
+  // owns the Python class, and will be used to find and create Extensions for
+  // this message.
+  // When null is returned, a python error has already been set.
+  virtual PyObject* NewMessage(const Descriptor* descriptor,
+                               PyObject* py_message_factory) const = 0;
+
+  // Allocate a new protocol buffer where the underlying object is owned by C++.
+  // The factory must currently be null.  This function works even if no Python
+  // module has been imported for the corresponding protocol buffer class.
+  // When null is returned, a python error has already been set.
+  //
+  // Since this call returns a python object owned by C++, some operations
+  // are risky, and it must be used carefully. In particular:
+  // * Avoid modifying the returned object from the C++ side while there are
+  // existing python references to it or it's subobjects.
+  // * Avoid using python references to this object or any subobjects after the
+  // C++ object has been freed.
+  // * Calling this with the same C++ pointer will result in multiple distinct
+  // python objects referencing the same C++ object.
+  virtual PyObject* NewMessageOwnedExternally(
+      Message* msg, PyObject* py_message_factory) const = 0;
 };
 
 inline const char* PyProtoAPICapsuleName() {
diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc
index 0301e96..4e74386 100644
--- a/python/google/protobuf/pyext/message.cc
+++ b/python/google/protobuf/pyext/message.cc
@@ -121,7 +121,7 @@
     if ('A' <= *i && *i <= 'Z') *i += 'a' - 'A';
   }
 }
-}
+}  // namespace
 
 // Finalize the creation of the Message class.
 static int AddDescriptors(PyObject* cls, const Descriptor* descriptor) {
@@ -145,7 +145,7 @@
         PyEnumDescriptor_FromDescriptor(enum_descriptor));
     if (enum_type == NULL) {
       return -1;
-     }
+    }
     // Add wrapped enum type to message class.
     ScopedPyObjectPtr wrapped(PyObject_CallFunctionObjArgs(
         EnumTypeWrapper_class, enum_type.get(), NULL));
@@ -195,8 +195,7 @@
   return 0;
 }
 
-static PyObject* New(PyTypeObject* type,
-                     PyObject* args, PyObject* kwargs) {
+static PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
   static char *kwlist[] = {"name", "bases", "dict", 0};
   PyObject *bases, *dict;
   const char* name;
@@ -219,41 +218,20 @@
   }
 
   // Check dict['DESCRIPTOR']
-  PyObject* descriptor_or_name = PyDict_GetItem(dict, kDESCRIPTOR);
-  if (descriptor_or_name == nullptr) {
+  PyObject* py_descriptor = PyDict_GetItem(dict, kDESCRIPTOR);
+  if (py_descriptor == nullptr) {
     PyErr_SetString(PyExc_TypeError, "Message class has no DESCRIPTOR");
-    return NULL;
+    return nullptr;
   }
-
-  Py_ssize_t name_size;
-  char* full_name;
-  const Descriptor* message_descriptor;
-  PyObject* py_descriptor;
-
-  if (PyObject_TypeCheck(descriptor_or_name, &PyMessageDescriptor_Type)) {
-    py_descriptor = descriptor_or_name;
-    message_descriptor = PyMessageDescriptor_AsDescriptor(py_descriptor);
-    if (message_descriptor == nullptr) {
-      return nullptr;
-    }
-  } else {
-    if (PyString_AsStringAndSize(descriptor_or_name, &full_name, &name_size) <
-        0) {
-      return nullptr;
-    }
-    message_descriptor =
-        GetDefaultDescriptorPool()->pool->FindMessageTypeByName(
-            StringParam(full_name, name_size));
-    if (message_descriptor == nullptr) {
-      PyErr_Format(PyExc_KeyError,
-                   "Can not find message descriptor %s "
-                   "from pool",
-                   full_name);
-      return nullptr;
-    }
-    py_descriptor = PyMessageDescriptor_FromDescriptor(message_descriptor);
-    // reset the dict['DESCRIPTOR'] to py_descriptor.
-    PyDict_SetItem(dict, kDESCRIPTOR, py_descriptor);
+  if (!PyObject_TypeCheck(py_descriptor, &PyMessageDescriptor_Type)) {
+    PyErr_Format(PyExc_TypeError, "Expected a message Descriptor, got %s",
+                 py_descriptor->ob_type->tp_name);
+    return nullptr;
+  }
+  const Descriptor* message_descriptor =
+      PyMessageDescriptor_AsDescriptor(py_descriptor);
+  if (message_descriptor == nullptr) {
+    return nullptr;
   }
 
   // Messages have no __dict__
@@ -603,15 +581,15 @@
       OutOfRangeError(arg);
     }  // Otherwise propagate existing error.
     return false;
-    }
-    if (PROTOBUF_PREDICT_FALSE(!IsValidNumericCast<RangeType>(value))) {
-      OutOfRangeError(arg);
-      return false;
-    }
+  }
+  if (PROTOBUF_PREDICT_FALSE(!IsValidNumericCast<RangeType>(value))) {
+    OutOfRangeError(arg);
+    return false;
+  }
   return true;
 }
 
-template<class T>
+template <class T>
 bool CheckAndGetInteger(PyObject* arg, T* value) {
   // The fast path.
 #if PY_MAJOR_VERSION < 3
@@ -631,10 +609,10 @@
   // an integer and can be used as an ordinal number".
   // This definition includes everything that implements numbers.Integral
   // and shouldn't cast the net too wide.
-    if (PROTOBUF_PREDICT_FALSE(!PyIndex_Check(arg))) {
-      FormatTypeError(arg, "int, long");
-      return false;
-    }
+  if (PROTOBUF_PREDICT_FALSE(!PyIndex_Check(arg))) {
+    FormatTypeError(arg, "int, long");
+    return false;
+  }
 
   // Now we have an integral number so we can safely use PyLong_ functions.
   // We need to treat the signed and unsigned cases differently in case arg is
@@ -651,7 +629,7 @@
       if (PROTOBUF_PREDICT_FALSE(casted == nullptr)) {
         // Propagate existing error.
         return false;
-        }
+      }
       ulong_result = PyLong_AsUnsignedLongLong(casted);
       Py_DECREF(casted);
     }
@@ -676,7 +654,7 @@
       if (PROTOBUF_PREDICT_FALSE(casted == nullptr)) {
         // Propagate existing error.
         return false;
-        }
+      }
       long_result = PyLong_AsLongLong(casted);
       Py_DECREF(casted);
     }
@@ -702,7 +680,7 @@
   if (PROTOBUF_PREDICT_FALSE(*value == -1 && PyErr_Occurred())) {
     FormatTypeError(arg, "int, long, float");
     return false;
-    }
+  }
   return true;
 }
 
@@ -928,9 +906,9 @@
   // Toplevel messages are always mutable.
   GOOGLE_DCHECK(self->parent);
 
-  if (AssureWritable(self->parent) == -1)
+  if (AssureWritable(self->parent) == -1) {
     return -1;
-
+  }
   // If this message is part of a oneof, there might be a field to release in
   // the parent.
   if (MaybeReleaseOverlappingOneofField(self->parent,
@@ -1279,32 +1257,41 @@
 
 // The __new__ method of Message classes.
 // Creates a new C++ message and takes ownership.
-static PyObject* New(PyTypeObject* cls,
-                     PyObject* unused_args, PyObject* unused_kwargs) {
-  CMessageClass* type = CheckMessageClass(cls);
-  if (type == NULL) {
-    return NULL;
-  }
+static CMessage* NewCMessage(CMessageClass* type) {
   // Retrieve the message descriptor and the default instance (=prototype).
   const Descriptor* message_descriptor = type->message_descriptor;
-  if (message_descriptor == NULL) {
-    return NULL;
+  if (message_descriptor == nullptr) {
+    // This would be very unexpected since the CMessageClass has already
+    // been checked.
+    PyErr_Format(PyExc_TypeError,
+                 "CMessageClass object '%s' has no descriptor.",
+                 Py_TYPE(type)->tp_name);
+    return nullptr;
   }
   const Message* prototype =
       type->py_message_factory->message_factory->GetPrototype(
           message_descriptor);
-  if (prototype == NULL) {
+  if (prototype == nullptr) {
     PyErr_SetString(PyExc_TypeError, message_descriptor->full_name().c_str());
-    return NULL;
+    return nullptr;
   }
 
   CMessage* self = NewEmptyMessage(type);
-  if (self == NULL) {
-    return NULL;
+  if (self == nullptr) {
+    return nullptr;
   }
   self->message = prototype->New();
   self->parent = nullptr;  // This message owns its data.
-  return reinterpret_cast<PyObject*>(self);
+  return self;
+}
+
+static PyObject* New(PyTypeObject* cls, PyObject* unused_args,
+                     PyObject* unused_kwargs) {
+  CMessageClass* type = CheckMessageClass(cls);
+  if (type == nullptr) {
+    return nullptr;
+  }
+  return reinterpret_cast<PyObject*>(NewCMessage(type));
 }
 
 // The __init__ method of Message classes.
@@ -2866,28 +2853,57 @@
   return cmsg->message;
 }
 
+PyObject* PyMessage_New(const Descriptor* descriptor,
+                        PyObject* py_message_factory) {
+  PyMessageFactory* factory = nullptr;
+  if (py_message_factory == nullptr) {
+    factory = GetDescriptorPool_FromPool(descriptor->file()->pool())
+                  ->py_message_factory;
+  } else if (PyObject_TypeCheck(py_message_factory, &PyMessageFactory_Type)) {
+    factory = reinterpret_cast<PyMessageFactory*>(py_message_factory);
+  } else {
+    PyErr_SetString(PyExc_TypeError, "Expected a MessageFactory");
+    return nullptr;
+  }
+  auto* message_class =
+      message_factory::GetOrCreateMessageClass(factory, descriptor);
+  if (message_class == nullptr) {
+    return nullptr;
+  }
+
+  CMessage* self = cmessage::NewCMessage(message_class);
+  Py_DECREF(message_class);
+  if (self == nullptr) {
+    return nullptr;
+  }
+  return self->AsPyObject();
+}
+
 PyObject* PyMessage_NewMessageOwnedExternally(Message* message,
-                                              PyObject* message_factory) {
-  if (message_factory) {
+                                              PyObject* py_message_factory) {
+  if (py_message_factory) {
     PyErr_SetString(PyExc_NotImplementedError,
                     "Default message_factory=NULL is the only supported value");
-    return NULL;
+    return nullptr;
   }
   if (message->GetReflection()->GetMessageFactory() !=
       MessageFactory::generated_factory()) {
     PyErr_SetString(PyExc_TypeError,
                     "Message pointer was not created from the default factory");
-    return NULL;
+    return nullptr;
   }
 
   CMessageClass* message_class = message_factory::GetOrCreateMessageClass(
       GetDefaultDescriptorPool()->py_message_factory, message->GetDescriptor());
+  if (message_class == nullptr) {
+    return nullptr;
+  }
 
   CMessage* self = cmessage::NewEmptyMessage(message_class);
-  if (self == NULL) {
-    return NULL;
-  }
   Py_DECREF(message_class);
+  if (self == nullptr) {
+    return nullptr;
+  }
   self->message = message;
   Py_INCREF(Py_None);
   self->parent = reinterpret_cast<CMessage*>(Py_None);
@@ -2954,9 +2970,9 @@
       return false;
     }
 
-    PyModule_AddObject(m, "RepeatedScalarContainer",
-                       reinterpret_cast<PyObject*>(
-                           &RepeatedScalarContainer_Type));
+    PyModule_AddObject(
+        m, "RepeatedScalarContainer",
+        reinterpret_cast<PyObject*>(&RepeatedScalarContainer_Type));
 
     if (PyType_Ready(&RepeatedCompositeContainer_Type) < 0) {
       return false;
@@ -2964,8 +2980,7 @@
 
     PyModule_AddObject(
         m, "RepeatedCompositeContainer",
-        reinterpret_cast<PyObject*>(
-            &RepeatedCompositeContainer_Type));
+        reinterpret_cast<PyObject*>(&RepeatedCompositeContainer_Type));
 
     // Register them as MutableSequence.
 #if PY_MAJOR_VERSION >= 3
@@ -2998,16 +3013,14 @@
   }
 
   PyModule_AddObject(m, "UnknownFieldSet",
-                     reinterpret_cast<PyObject*>(
-                         &PyUnknownFields_Type));
+                     reinterpret_cast<PyObject*>(&PyUnknownFields_Type));
 
   if (PyType_Ready(&PyUnknownFieldRef_Type) < 0) {
     return false;
   }
 
   PyModule_AddObject(m, "UnknownField",
-                     reinterpret_cast<PyObject*>(
-                         &PyUnknownFieldRef_Type));
+                     reinterpret_cast<PyObject*>(&PyUnknownFieldRef_Type));
 
   // Initialize Map container types.
   if (!InitMapContainers()) {
@@ -3023,9 +3036,8 @@
   if (PyType_Ready(&ExtensionDict_Type) < 0) {
     return false;
   }
-  PyModule_AddObject(
-      m, "ExtensionDict",
-      reinterpret_cast<PyObject*>(&ExtensionDict_Type));
+  PyModule_AddObject(m, "ExtensionDict",
+                     reinterpret_cast<PyObject*>(&ExtensionDict_Type));
   if (PyType_Ready(&ExtensionIterator_Type) < 0) {
     return false;
   }
@@ -3039,25 +3051,24 @@
   PyModule_AddObject(m, "default_pool",
                      reinterpret_cast<PyObject*>(GetDefaultDescriptorPool()));
 
-  PyModule_AddObject(m, "DescriptorPool", reinterpret_cast<PyObject*>(
-      &PyDescriptorPool_Type));
-
-  PyModule_AddObject(m, "Descriptor", reinterpret_cast<PyObject*>(
-      &PyMessageDescriptor_Type));
-  PyModule_AddObject(m, "FieldDescriptor", reinterpret_cast<PyObject*>(
-      &PyFieldDescriptor_Type));
-  PyModule_AddObject(m, "EnumDescriptor", reinterpret_cast<PyObject*>(
-      &PyEnumDescriptor_Type));
-  PyModule_AddObject(m, "EnumValueDescriptor", reinterpret_cast<PyObject*>(
-      &PyEnumValueDescriptor_Type));
-  PyModule_AddObject(m, "FileDescriptor", reinterpret_cast<PyObject*>(
-      &PyFileDescriptor_Type));
-  PyModule_AddObject(m, "OneofDescriptor", reinterpret_cast<PyObject*>(
-      &PyOneofDescriptor_Type));
-  PyModule_AddObject(m, "ServiceDescriptor", reinterpret_cast<PyObject*>(
-      &PyServiceDescriptor_Type));
-  PyModule_AddObject(m, "MethodDescriptor", reinterpret_cast<PyObject*>(
-      &PyMethodDescriptor_Type));
+  PyModule_AddObject(m, "DescriptorPool",
+                     reinterpret_cast<PyObject*>(&PyDescriptorPool_Type));
+  PyModule_AddObject(m, "Descriptor",
+                     reinterpret_cast<PyObject*>(&PyMessageDescriptor_Type));
+  PyModule_AddObject(m, "FieldDescriptor",
+                     reinterpret_cast<PyObject*>(&PyFieldDescriptor_Type));
+  PyModule_AddObject(m, "EnumDescriptor",
+                     reinterpret_cast<PyObject*>(&PyEnumDescriptor_Type));
+  PyModule_AddObject(m, "EnumValueDescriptor",
+                     reinterpret_cast<PyObject*>(&PyEnumValueDescriptor_Type));
+  PyModule_AddObject(m, "FileDescriptor",
+                     reinterpret_cast<PyObject*>(&PyFileDescriptor_Type));
+  PyModule_AddObject(m, "OneofDescriptor",
+                     reinterpret_cast<PyObject*>(&PyOneofDescriptor_Type));
+  PyModule_AddObject(m, "ServiceDescriptor",
+                     reinterpret_cast<PyObject*>(&PyServiceDescriptor_Type));
+  PyModule_AddObject(m, "MethodDescriptor",
+                     reinterpret_cast<PyObject*>(&PyMethodDescriptor_Type));
 
   PyObject* enum_type_wrapper = PyImport_ImportModule(
       "google.protobuf.internal.enum_type_wrapper");
diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h
index c5a635d..a1e8326 100644
--- a/python/google/protobuf/pyext/message.h
+++ b/python/google/protobuf/pyext/message.h
@@ -282,51 +282,50 @@
 /* Is 64bit */
 #define IS_64BIT (SIZEOF_LONG == 8)
 
-#define FIELD_IS_REPEATED(field_descriptor)                 \
-    ((field_descriptor)->label() == FieldDescriptor::LABEL_REPEATED)
+#define FIELD_IS_REPEATED(field_descriptor) \
+  ((field_descriptor)->label() == FieldDescriptor::LABEL_REPEATED)
 
-#define GOOGLE_CHECK_GET_INT32(arg, value, err)                        \
-    int32 value;                                            \
-    if (!CheckAndGetInteger(arg, &value)) { \
-      return err;                                          \
-    }
+#define GOOGLE_CHECK_GET_INT32(arg, value, err)  \
+  int32 value;                            \
+  if (!CheckAndGetInteger(arg, &value)) { \
+    return err;                           \
+  }
 
-#define GOOGLE_CHECK_GET_INT64(arg, value, err)                        \
-    int64 value;                                            \
-    if (!CheckAndGetInteger(arg, &value)) { \
-      return err;                                          \
-    }
+#define GOOGLE_CHECK_GET_INT64(arg, value, err)  \
+  int64 value;                            \
+  if (!CheckAndGetInteger(arg, &value)) { \
+    return err;                           \
+  }
 
-#define GOOGLE_CHECK_GET_UINT32(arg, value, err)                       \
-    uint32 value;                                           \
-    if (!CheckAndGetInteger(arg, &value)) { \
-      return err;                                          \
-    }
+#define GOOGLE_CHECK_GET_UINT32(arg, value, err) \
+  uint32 value;                           \
+  if (!CheckAndGetInteger(arg, &value)) { \
+    return err;                           \
+  }
 
-#define GOOGLE_CHECK_GET_UINT64(arg, value, err)                       \
-    uint64 value;                                           \
-    if (!CheckAndGetInteger(arg, &value)) { \
-      return err;                                          \
-    }
+#define GOOGLE_CHECK_GET_UINT64(arg, value, err) \
+  uint64 value;                           \
+  if (!CheckAndGetInteger(arg, &value)) { \
+    return err;                           \
+  }
 
-#define GOOGLE_CHECK_GET_FLOAT(arg, value, err)                        \
-    float value;                                            \
-    if (!CheckAndGetFloat(arg, &value)) {                   \
-      return err;                                          \
-    }                                                       \
+#define GOOGLE_CHECK_GET_FLOAT(arg, value, err) \
+  float value;                           \
+  if (!CheckAndGetFloat(arg, &value)) {  \
+    return err;                          \
+  }
 
-#define GOOGLE_CHECK_GET_DOUBLE(arg, value, err)                       \
-    double value;                                           \
-    if (!CheckAndGetDouble(arg, &value)) {                  \
-      return err;                                          \
-    }
+#define GOOGLE_CHECK_GET_DOUBLE(arg, value, err) \
+  double value;                           \
+  if (!CheckAndGetDouble(arg, &value)) {  \
+    return err;                           \
+  }
 
-#define GOOGLE_CHECK_GET_BOOL(arg, value, err)                         \
-    bool value;                                             \
-    if (!CheckAndGetBool(arg, &value)) {                    \
-      return err;                                          \
-    }
-
+#define GOOGLE_CHECK_GET_BOOL(arg, value, err) \
+  bool value;                           \
+  if (!CheckAndGetBool(arg, &value)) {  \
+    return err;                         \
+  }
 
 #define FULL_MODULE_NAME "google.protobuf.pyext._message"
 
@@ -353,10 +352,12 @@
 
 extern PyObject* PickleError_class;
 
+PyObject* PyMessage_New(const Descriptor* descriptor,
+                        PyObject* py_message_factory);
 const Message* PyMessage_GetMessagePointer(PyObject* msg);
 Message* PyMessage_GetMutableMessagePointer(PyObject* msg);
 PyObject* PyMessage_NewMessageOwnedExternally(Message* message,
-                                              PyObject* message_factory);
+                                              PyObject* py_message_factory);
 
 bool InitProto2MessageModule(PyObject *m);
 
diff --git a/python/google/protobuf/pyext/message_module.cc b/python/google/protobuf/pyext/message_module.cc
index 63d60b7..b5975f7 100644
--- a/python/google/protobuf/pyext/message_module.cc
+++ b/python/google/protobuf/pyext/message_module.cc
@@ -30,13 +30,12 @@
 
 #include <Python.h>
 
+#include <google/protobuf/message_lite.h>
 #include <google/protobuf/pyext/descriptor_pool.h>
 #include <google/protobuf/pyext/message.h>
 #include <google/protobuf/pyext/message_factory.h>
 #include <google/protobuf/proto_api.h>
 
-#include <google/protobuf/message_lite.h>
-
 namespace {
 
 // C++ API.  Clients get at this via proto_api.h
@@ -55,6 +54,15 @@
     return google::protobuf::python::GetDefaultDescriptorPool()
         ->py_message_factory->message_factory;
   }
+  PyObject* NewMessage(const google::protobuf::Descriptor* descriptor,
+                       PyObject* py_message_factory) const override {
+    return google::protobuf::python::PyMessage_New(descriptor, py_message_factory);
+  }
+  PyObject* NewMessageOwnedExternally(
+      google::protobuf::Message* msg, PyObject* py_message_factory) const override {
+    return google::protobuf::python::PyMessage_NewMessageOwnedExternally(
+        msg, py_message_factory);
+  }
 };
 
 }  // namespace
diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc
index 1b739ae..cbc0f9f 100644
--- a/python/google/protobuf/pyext/repeated_composite_container.cc
+++ b/python/google/protobuf/pyext/repeated_composite_container.cc
@@ -567,7 +567,11 @@
     sizeof(RepeatedCompositeContainer),         // tp_basicsize
     0,                                          //  tp_itemsize
     repeated_composite_container::Dealloc,      //  tp_dealloc
-    0,                                          //  tp_print, in Python >=3.8: Py_ssize_t tp_vectorcall_offset
+#if PY_VERSION_HEX >= 0x03080000
+    0,                                          //  tp_vectorcall_offset
+#else
+    nullptr,                                    //  tp_print
+#endif
     nullptr,                                    //  tp_getattr
     nullptr,                                    //  tp_setattr
     nullptr,                                    //  tp_compare
diff --git a/python/google/protobuf/pyext/repeated_scalar_container.cc b/python/google/protobuf/pyext/repeated_scalar_container.cc
index 6b15258..5a5c4db 100644
--- a/python/google/protobuf/pyext/repeated_scalar_container.cc
+++ b/python/google/protobuf/pyext/repeated_scalar_container.cc
@@ -753,7 +753,11 @@
     sizeof(RepeatedScalarContainer),         // tp_basicsize
     0,                                       //  tp_itemsize
     repeated_scalar_container::Dealloc,      //  tp_dealloc
-    0,                                       //  tp_print, in Python >=3.8: Py_ssize_t tp_vectorcall_offset
+#if PY_VERSION_HEX >= 0x03080000
+    0,                                       //  tp_vectorcall_offset
+#else
+    nullptr,                                 //  tp_print
+#endif
     nullptr,                                 //  tp_getattr
     nullptr,                                 //  tp_setattr
     nullptr,                                 //  tp_compare
diff --git a/python/google/protobuf/service_reflection.py b/python/google/protobuf/service_reflection.py
index 8590e46..75c51ff 100644
--- a/python/google/protobuf/service_reflection.py
+++ b/python/google/protobuf/service_reflection.py
@@ -38,12 +38,6 @@
 
 __author__ = '[email protected] (Petar Petrov)'
 
-from google.protobuf.internal import api_implementation
-
-if api_implementation.Type() == 'cpp':
-  # pylint: disable=g-import-not-at-top
-  from google.protobuf.pyext import _message
-
 
 class GeneratedServiceType(type):
 
@@ -84,10 +78,6 @@
       return
 
     descriptor = dictionary[GeneratedServiceType._DESCRIPTOR_KEY]
-    if isinstance(descriptor, str):
-      descriptor = _message.default_pool.FindServiceByName(descriptor)
-      dictionary[GeneratedServiceType._DESCRIPTOR_KEY] = descriptor
-
     service_builder = _ServiceBuilder(descriptor)
     service_builder.BuildService(cls)
     cls.DESCRIPTOR = descriptor
@@ -113,16 +103,13 @@
         dictionary[_DESCRIPTOR_KEY] must contain a ServiceDescriptor object
         describing this protocol service type.
     """
-    descriptor = dictionary.get(cls._DESCRIPTOR_KEY)
-    if isinstance(descriptor, str):
-      descriptor = _message.default_pool.FindServiceByName(descriptor)
-      dictionary[GeneratedServiceStubType._DESCRIPTOR_KEY] = descriptor
     super(GeneratedServiceStubType, cls).__init__(name, bases, dictionary)
     # Don't do anything if this class doesn't have a descriptor. This happens
     # when a service stub is subclassed.
     if GeneratedServiceStubType._DESCRIPTOR_KEY not in dictionary:
       return
 
+    descriptor = dictionary[GeneratedServiceStubType._DESCRIPTOR_KEY]
     service_stub_builder = _ServiceStubBuilder(descriptor)
     service_stub_builder.BuildServiceStub(cls)
 
diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py
index 9ebe8b4..c376c7b 100644
--- a/python/google/protobuf/text_format.py
+++ b/python/google/protobuf/text_format.py
@@ -541,7 +541,7 @@
         # For groups, use the capitalized name.
         out.write(field.message_type.name)
       else:
-        out.write(field.name)
+          out.write(field.name)
 
     if (self.force_colon or
         field.cpp_type != descriptor.FieldDescriptor.CPPTYPE_MESSAGE):
@@ -902,6 +902,8 @@
       # pylint: disable=protected-access
       field = message.Extensions._FindExtensionByName(name)
       # pylint: enable=protected-access
+
+
       if not field:
         if self.allow_unknown_extension:
           field = None
@@ -988,6 +990,7 @@
     if not tokenizer.TryConsume(','):
       tokenizer.TryConsume(';')
 
+
   def _ConsumeAnyTypeUrl(self, tokenizer):
     """Consumes a google.protobuf.Any type URL and returns the type name."""
     # Consume "type.googleapis.com/".
diff --git a/python/setup.py b/python/setup.py
index aab240a..39eb18d 100755
--- a/python/setup.py
+++ b/python/setup.py
@@ -207,7 +207,7 @@
     # C++ projects must now migrate to libc++ and are recommended to set a
     # deployment target of macOS 10.9 or later, or iOS 7 or later.
     if sys.platform == 'darwin':
-      mac_target = str(sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET'))
+      mac_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
       if mac_target and (pkg_resources.parse_version(mac_target) <
                        pkg_resources.parse_version('10.9.0')):
         os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.9'
@@ -254,7 +254,7 @@
     os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp'
 
   # Keep this list of dependencies in sync with tox.ini.
-  install_requires = ['six>=1.9']
+  install_requires = ['six>=1.9', 'setuptools']
   if sys.version_info <= (2,7):
     install_requires.append('ordereddict')
     install_requires.append('unittest2')
diff --git a/ruby/Rakefile b/ruby/Rakefile
index 2aa7743..3e3da05 100644
--- a/ruby/Rakefile
+++ b/ruby/Rakefile
@@ -51,6 +51,12 @@
     system("mvn --batch-mode package")
   end
 else
+  unless ENV['IN_DOCKER'] == 'true'
+    # We need wyhash in-tree.
+    FileUtils.mkdir_p("ext/google/protobuf_c/third_party/wyhash")
+    FileUtils.cp("../third_party/wyhash/wyhash.h", "ext/google/protobuf_c/third_party/wyhash/wyhash.h")
+  end
+
   Rake::ExtensionTask.new("protobuf_c", spec) do |ext|
     unless RUBY_PLATFORM =~ /darwin/
       # TODO: also set "no_native to true" for mac if possible. As is,
@@ -73,7 +79,7 @@
     ['x86-mingw32', 'x64-mingw32', 'x86_64-linux', 'x86-linux'].each do |plat|
       RakeCompilerDock.sh <<-"EOT", platform: plat
         bundle && \
-        IN_DOCKER=true rake native:#{plat} pkg/#{spec.full_name}-#{plat}.gem RUBY_CC_VERSION=2.7.0:2.6.0:2.5.0:2.4.0:2.3.0
+        IN_DOCKER=true rake native:#{plat} pkg/#{spec.full_name}-#{plat}.gem RUBY_CC_VERSION=3.0.0:2.7.0:2.6.0:2.5.0:2.4.0:2.3.0
       EOT
     end
   end
@@ -81,7 +87,7 @@
   if RUBY_PLATFORM =~ /darwin/
     task 'gem:native' do
       system "rake genproto"
-      system "rake cross native gem RUBY_CC_VERSION=2.7.0:2.6.0:2.5.1:2.4.0:2.3.0"
+      system "rake cross native gem RUBY_CC_VERSION=3.0.0:2.7.0:2.6.0:2.5.1:2.4.0:2.3.0"
     end
   else
     task 'gem:native' => [:genproto, 'gem:windows']
@@ -98,7 +104,9 @@
 genproto_output << "tests/test_ruby_package_proto2.rb"
 genproto_output << "tests/basic_test.rb"
 genproto_output << "tests/basic_test_proto2.rb"
+genproto_output << "tests/multi_level_nesting_test.rb"
 genproto_output << "tests/wrappers.rb"
+
 file "tests/generated_code.rb" => "tests/generated_code.proto" do |file_task|
   sh "../src/protoc --ruby_out=. tests/generated_code.proto"
 end
@@ -131,6 +139,10 @@
   sh "../src/protoc -I../src -I. --ruby_out=. tests/basic_test_proto2.proto"
 end
 
+file "tests/multi_level_nesting_test.rb" => "tests/multi_level_nesting_test.proto" do |file_task|
+  sh "../src/protoc -I../src -I. --ruby_out=. tests/multi_level_nesting_test.proto"
+end
+
 file "tests/wrappers.rb" => "../src/google/protobuf/wrappers.proto" do |file_task|
   sh "../src/protoc -I../src -I. --ruby_out=tests ../src/google/protobuf/wrappers.proto"
 end
diff --git a/ruby/compatibility_tests/v3.0.0/tests/basic.rb b/ruby/compatibility_tests/v3.0.0/tests/basic.rb
index bfe68ef..7228144 100755
--- a/ruby/compatibility_tests/v3.0.0/tests/basic.rb
+++ b/ruby/compatibility_tests/v3.0.0/tests/basic.rb
@@ -1264,10 +1264,10 @@
       m = MapMessage.new(:map_string_int32 => {"a" => 1})
       expected = '{"mapStringInt32":{"a":1},"mapStringMsg":{}}'
       expected_preserve = '{"map_string_int32":{"a":1},"map_string_msg":{}}'
-      assert MapMessage.encode_json(m) == expected
+      assert_equal expected, MapMessage.encode_json(m, :emit_defaults => true)
 
-      json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true)
-      assert json == expected_preserve
+      json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true, :emit_defaults => true)
+      assert_equal expected_preserve, json
 
       m2 = MapMessage.decode_json(MapMessage.encode_json(m))
       assert m == m2
diff --git a/ruby/ext/google/protobuf_c/convert.c b/ruby/ext/google/protobuf_c/convert.c
new file mode 100644
index 0000000..bc3e35a
--- /dev/null
+++ b/ruby/ext/google/protobuf_c/convert.c
@@ -0,0 +1,349 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// -----------------------------------------------------------------------------
+// Ruby <-> upb data conversion functions.
+//
+// This file Also contains a few other assorted algorithms on upb_msgval.
+//
+// None of the algorithms in this file require any access to the internal
+// representation of Ruby or upb objects.
+// -----------------------------------------------------------------------------
+
+#include "convert.h"
+
+#include "message.h"
+#include "protobuf.h"
+#include "third_party/wyhash/wyhash.h"
+
+static upb_strview Convert_StringData(VALUE str, upb_arena *arena) {
+  upb_strview ret;
+  if (arena) {
+    char *ptr = upb_arena_malloc(arena, RSTRING_LEN(str));
+    memcpy(ptr, RSTRING_PTR(str), RSTRING_LEN(str));
+    ret.data = ptr;
+  } else {
+    // Data is only needed temporarily (within map lookup).
+    ret.data = RSTRING_PTR(str);
+  }
+  ret.size = RSTRING_LEN(str);
+  return ret;
+}
+
+static bool is_ruby_num(VALUE value) {
+  return (TYPE(value) == T_FLOAT ||
+          TYPE(value) == T_FIXNUM ||
+          TYPE(value) == T_BIGNUM);
+}
+
+static void Convert_CheckInt(const char* name, upb_fieldtype_t type,
+                             VALUE val) {
+  if (!is_ruby_num(val)) {
+    rb_raise(cTypeError,
+             "Expected number type for integral field '%s' (given %s).", name,
+             rb_class2name(CLASS_OF(val)));
+  }
+
+  // NUM2{INT,UINT,LL,ULL} macros do the appropriate range checks on upper
+  // bound; we just need to do precision checks (i.e., disallow rounding) and
+  // check for < 0 on unsigned types.
+  if (TYPE(val) == T_FLOAT) {
+    double dbl_val = NUM2DBL(val);
+    if (floor(dbl_val) != dbl_val) {
+      rb_raise(rb_eRangeError,
+               "Non-integral floating point value assigned to integer field "
+               "'%s' (given %s).",
+               name, rb_class2name(CLASS_OF(val)));
+    }
+  }
+  if (type == UPB_TYPE_UINT32 || type == UPB_TYPE_UINT64) {
+    if (NUM2DBL(val) < 0) {
+      rb_raise(
+          rb_eRangeError,
+          "Assigning negative value to unsigned integer field '%s' (given %s).",
+          name, rb_class2name(CLASS_OF(val)));
+    }
+  }
+}
+
+static int32_t Convert_ToEnum(VALUE value, const char* name,
+                              const upb_enumdef* e) {
+  int32_t val;
+
+  switch (TYPE(value)) {
+    case T_FLOAT:
+    case T_FIXNUM:
+    case T_BIGNUM:
+      Convert_CheckInt(name, UPB_TYPE_INT32, value);
+      val = NUM2INT(value);
+      break;
+    case T_STRING:
+      if (!upb_enumdef_ntoi(e, RSTRING_PTR(value), RSTRING_LEN(value), &val)) {
+        goto unknownval;
+      }
+      break;
+    case T_SYMBOL:
+      if (!upb_enumdef_ntoiz(e, rb_id2name(SYM2ID(value)), &val)) {
+        goto unknownval;
+      }
+      break;
+    default:
+      rb_raise(cTypeError,
+               "Expected number or symbol type for enum field '%s'.", name);
+  }
+
+  return val;
+
+unknownval:
+  rb_raise(rb_eRangeError, "Unknown symbol value for enum field '%s'.", name);
+}
+
+upb_msgval Convert_RubyToUpb(VALUE value, const char* name, TypeInfo type_info,
+                             upb_arena* arena) {
+  upb_msgval ret;
+
+  switch (type_info.type) {
+    case UPB_TYPE_FLOAT:
+      if (!is_ruby_num(value)) {
+        rb_raise(cTypeError, "Expected number type for float field '%s' (given %s).",
+                 name, rb_class2name(CLASS_OF(value)));
+      }
+      ret.float_val = NUM2DBL(value);
+      break;
+    case UPB_TYPE_DOUBLE:
+      if (!is_ruby_num(value)) {
+        rb_raise(cTypeError, "Expected number type for double field '%s' (given %s).",
+                 name, rb_class2name(CLASS_OF(value)));
+      }
+      ret.double_val = NUM2DBL(value);
+      break;
+    case UPB_TYPE_BOOL: {
+      if (value == Qtrue) {
+        ret.bool_val = 1;
+      } else if (value == Qfalse) {
+        ret.bool_val = 0;
+      } else {
+        rb_raise(cTypeError, "Invalid argument for boolean field '%s' (given %s).",
+                 name, rb_class2name(CLASS_OF(value)));
+      }
+      break;
+    }
+    case UPB_TYPE_STRING: {
+      VALUE utf8 = rb_enc_from_encoding(rb_utf8_encoding());
+      if (CLASS_OF(value) == rb_cSymbol) {
+        value = rb_funcall(value, rb_intern("to_s"), 0);
+      } else if (CLASS_OF(value) != rb_cString) {
+        rb_raise(cTypeError, "Invalid argument for string field '%s' (given %s).",
+                 name, rb_class2name(CLASS_OF(value)));
+      }
+
+      if (rb_obj_encoding(value) != utf8) {
+        // Note: this will not duplicate underlying string data unless necessary.
+        value = rb_str_encode(value, utf8, 0, Qnil);
+
+        if (rb_enc_str_coderange(value) == ENC_CODERANGE_BROKEN) {
+          rb_raise(rb_eEncodingError, "String is invalid UTF-8");
+        }
+      }
+
+      ret.str_val = Convert_StringData(value, arena);
+      break;
+    }
+    case UPB_TYPE_BYTES: {
+      VALUE bytes = rb_enc_from_encoding(rb_ascii8bit_encoding());
+      if (CLASS_OF(value) != rb_cString) {
+        rb_raise(cTypeError, "Invalid argument for bytes field '%s' (given %s).",
+                 name, rb_class2name(CLASS_OF(value)));
+      }
+
+      if (rb_obj_encoding(value) != bytes) {
+        // Note: this will not duplicate underlying string data unless necessary.
+        // TODO(haberman): is this really necessary to get raw bytes?
+        value = rb_str_encode(value, bytes, 0, Qnil);
+      }
+
+      ret.str_val = Convert_StringData(value, arena);
+      break;
+    }
+    case UPB_TYPE_MESSAGE:
+      ret.msg_val =
+          Message_GetUpbMessage(value, type_info.def.msgdef, name, arena);
+      break;
+    case UPB_TYPE_ENUM:
+      ret.int32_val = Convert_ToEnum(value, name, type_info.def.enumdef);
+      break;
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_UINT64:
+      Convert_CheckInt(name, type_info.type, value);
+      switch (type_info.type) {
+      case UPB_TYPE_INT32:
+        ret.int32_val = NUM2INT(value);
+        break;
+      case UPB_TYPE_INT64:
+        ret.int64_val = NUM2LL(value);
+        break;
+      case UPB_TYPE_UINT32:
+        ret.uint32_val = NUM2UINT(value);
+        break;
+      case UPB_TYPE_UINT64:
+        ret.uint64_val = NUM2ULL(value);
+        break;
+      default:
+        break;
+      }
+      break;
+    default:
+      break;
+  }
+
+  return ret;
+}
+
+VALUE Convert_UpbToRuby(upb_msgval upb_val, TypeInfo type_info, VALUE arena) {
+  switch (type_info.type) {
+    case UPB_TYPE_FLOAT:
+      return DBL2NUM(upb_val.float_val);
+    case UPB_TYPE_DOUBLE:
+      return DBL2NUM(upb_val.double_val);
+    case UPB_TYPE_BOOL:
+      return upb_val.bool_val ? Qtrue : Qfalse;
+    case UPB_TYPE_INT32:
+      return INT2NUM(upb_val.int32_val);
+    case UPB_TYPE_INT64:
+      return LL2NUM(upb_val.int64_val);
+    case UPB_TYPE_UINT32:
+      return UINT2NUM(upb_val.uint32_val);
+    case UPB_TYPE_UINT64:
+      return ULL2NUM(upb_val.int64_val);
+    case UPB_TYPE_ENUM: {
+      const char* name =
+          upb_enumdef_iton(type_info.def.enumdef, upb_val.int32_val);
+      if (name) {
+        return ID2SYM(rb_intern(name));
+      } else {
+        return INT2NUM(upb_val.int32_val);
+      }
+    }
+    case UPB_TYPE_STRING: {
+      VALUE str_rb = rb_str_new(upb_val.str_val.data, upb_val.str_val.size);
+      rb_enc_associate(str_rb, rb_utf8_encoding());
+      rb_obj_freeze(str_rb);
+      return str_rb;
+    }
+    case UPB_TYPE_BYTES: {
+      VALUE str_rb = rb_str_new(upb_val.str_val.data, upb_val.str_val.size);
+      rb_enc_associate(str_rb, rb_ascii8bit_encoding());
+      rb_obj_freeze(str_rb);
+      return str_rb;
+    }
+    case UPB_TYPE_MESSAGE:
+      return Message_GetRubyWrapper((upb_msg*)upb_val.msg_val,
+                                    type_info.def.msgdef, arena);
+    default:
+      rb_raise(rb_eRuntimeError, "Convert_UpbToRuby(): Unexpected type %d",
+               (int)type_info.type);
+  }
+}
+
+upb_msgval Msgval_DeepCopy(upb_msgval msgval, TypeInfo type_info,
+                           upb_arena* arena) {
+  upb_msgval new_msgval;
+
+  switch (type_info.type) {
+    default:
+      memcpy(&new_msgval, &msgval, sizeof(msgval));
+      break;
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES: {
+      size_t n = msgval.str_val.size;
+      char *mem = upb_arena_malloc(arena, n);
+      new_msgval.str_val.data = mem;
+      new_msgval.str_val.size = n;
+      memcpy(mem, msgval.str_val.data, n);
+      break;
+    }
+    case UPB_TYPE_MESSAGE:
+      new_msgval.msg_val =
+          Message_deep_copy(msgval.msg_val, type_info.def.msgdef, arena);
+      break;
+  }
+
+  return new_msgval;
+}
+
+bool Msgval_IsEqual(upb_msgval val1, upb_msgval val2, TypeInfo type_info) {
+  switch (type_info.type) {
+    case UPB_TYPE_BOOL:
+      return memcmp(&val1, &val2, 1) == 0;
+    case UPB_TYPE_FLOAT:
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_ENUM:
+      return memcmp(&val1, &val2, 4) == 0;
+    case UPB_TYPE_DOUBLE:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT64:
+      return memcmp(&val1, &val2, 8) == 0;
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+      return val1.str_val.size != val2.str_val.size ||
+             memcmp(val1.str_val.data, val2.str_val.data,
+                    val1.str_val.size) == 0;
+    case UPB_TYPE_MESSAGE:
+      return Message_Equal(val1.msg_val, val2.msg_val, type_info.def.msgdef);
+    default:
+      rb_raise(rb_eRuntimeError, "Internal error, unexpected type");
+  }
+}
+
+uint64_t Msgval_GetHash(upb_msgval val, TypeInfo type_info, uint64_t seed) {
+  switch (type_info.type) {
+    case UPB_TYPE_BOOL:
+      return wyhash(&val, 1, seed, _wyp);
+    case UPB_TYPE_FLOAT:
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_ENUM:
+      return wyhash(&val, 4, seed, _wyp);
+    case UPB_TYPE_DOUBLE:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT64:
+      return wyhash(&val, 8, seed, _wyp);
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+      return wyhash(val.str_val.data, val.str_val.size, seed, _wyp);
+    case UPB_TYPE_MESSAGE:
+      return Message_Hash(val.msg_val, type_info.def.msgdef, seed);
+    default:
+      rb_raise(rb_eRuntimeError, "Internal error, unexpected type");
+  }
+}
diff --git a/ruby/ext/google/protobuf_c/convert.h b/ruby/ext/google/protobuf_c/convert.h
new file mode 100644
index 0000000..cda18a0
--- /dev/null
+++ b/ruby/ext/google/protobuf_c/convert.h
@@ -0,0 +1,72 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef RUBY_PROTOBUF_CONVERT_H_
+#define RUBY_PROTOBUF_CONVERT_H_
+
+#include <ruby/ruby.h>
+
+#include "protobuf.h"
+#include "ruby-upb.h"
+
+// Converts |ruby_val| to a upb_msgval according to |type_info|.
+//
+// The |arena| parameter indicates the lifetime of the container where this
+// value will be assigned. It is used as follows:
+// - If type is string or bytes, the string data will be copied into |arena|.
+// - If type is message, and we need to auto-construct a message due to implicit
+//   conversions (eg. Time -> Google::Protobuf::Timestamp), the new message
+//   will be created in |arena|.
+// - If type is message and the Ruby value is a message instance, we will fuse
+//   the message's arena into |arena|, to ensure that this message outlives the
+//   container.
+upb_msgval Convert_RubyToUpb(VALUE ruby_val, const char *name,
+                             TypeInfo type_info, upb_arena *arena);
+
+// Converts |upb_val| to a Ruby VALUE according to |type_info|. This may involve
+// creating a Ruby wrapper object.
+//
+// The |arena| parameter indicates the arena that owns the lifetime of
+// |upb_val|. Any Ruby wrapper object that is created will reference |arena|
+// and ensure it outlives the wrapper.
+VALUE Convert_UpbToRuby(upb_msgval upb_val, TypeInfo type_info, VALUE arena);
+
+// Creates a deep copy of |msgval| in |arena|.
+upb_msgval Msgval_DeepCopy(upb_msgval msgval, TypeInfo type_info,
+                           upb_arena *arena);
+
+// Returns true if |val1| and |val2| are equal. Their type is given by
+// |type_info|.
+bool Msgval_IsEqual(upb_msgval val1, upb_msgval val2, TypeInfo type_info);
+
+// Returns a hash value for the given upb_msgval.
+uint64_t Msgval_GetHash(upb_msgval val, TypeInfo type_info, uint64_t seed);
+
+#endif  // RUBY_PROTOBUF_CONVERT_H_
diff --git a/ruby/ext/google/protobuf_c/defs.c b/ruby/ext/google/protobuf_c/defs.c
index 1a09cc5..6cf8174 100644
--- a/ruby/ext/google/protobuf_c/defs.c
+++ b/ruby/ext/google/protobuf_c/defs.c
@@ -30,8 +30,35 @@
 
 #include <ctype.h>
 #include <errno.h>
+#include <ruby/version.h>
+
+#include "convert.h"
+#include "message.h"
 #include "protobuf.h"
 
+static VALUE Builder_build(VALUE _self);
+
+static VALUE cMessageBuilderContext;
+static VALUE cOneofBuilderContext;
+static VALUE cEnumBuilderContext;
+static VALUE cBuilder;
+
+// -----------------------------------------------------------------------------
+// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
+// instances.
+// -----------------------------------------------------------------------------
+
+static VALUE get_msgdef_obj(VALUE descriptor_pool, const upb_msgdef* def);
+static VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_enumdef* def);
+static VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_fielddef* def);
+static VALUE get_filedef_obj(VALUE descriptor_pool, const upb_filedef* def);
+static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_oneofdef* def);
+
+// A distinct object that is not accessible from Ruby.  We use this as a
+// constructor argument to enforce that certain objects cannot be created from
+// Ruby.
+VALUE c_only_cookie = Qnil;
+
 // -----------------------------------------------------------------------------
 // Common utilities.
 // -----------------------------------------------------------------------------
@@ -48,6 +75,10 @@
   return rb_str_new2(s);
 }
 
+// -----------------------------------------------------------------------------
+// Backward compatibility code.
+// -----------------------------------------------------------------------------
+
 static void rewrite_enum_default(const upb_symtab* symtab,
                                  google_protobuf_FileDescriptorProto* file,
                                  google_protobuf_FieldDescriptorProto* field) {
@@ -205,6 +236,1239 @@
   }
 }
 
+// -----------------------------------------------------------------------------
+// DescriptorPool.
+// -----------------------------------------------------------------------------
+
+typedef struct {
+  VALUE def_to_descriptor;  // Hash table of def* -> Ruby descriptor.
+  upb_symtab* symtab;
+} DescriptorPool;
+
+VALUE cDescriptorPool = Qnil;
+
+// Global singleton DescriptorPool. The user is free to create others, but this
+// is used by generated code.
+VALUE generated_pool = Qnil;
+
+static void DescriptorPool_mark(void* _self) {
+  DescriptorPool* self = _self;
+  rb_gc_mark(self->def_to_descriptor);
+}
+
+static void DescriptorPool_free(void* _self) {
+  DescriptorPool* self = _self;
+  upb_symtab_free(self->symtab);
+  xfree(self);
+}
+
+static const rb_data_type_t DescriptorPool_type = {
+  "Google::Protobuf::DescriptorPool",
+  {DescriptorPool_mark, DescriptorPool_free, NULL},
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static DescriptorPool* ruby_to_DescriptorPool(VALUE val) {
+  DescriptorPool* ret;
+  TypedData_Get_Struct(val, DescriptorPool, &DescriptorPool_type, ret);
+  return ret;
+}
+
+// Exposed to other modules in defs.h.
+const upb_symtab *DescriptorPool_GetSymtab(VALUE desc_pool_rb) {
+  DescriptorPool *pool = ruby_to_DescriptorPool(desc_pool_rb);
+  return pool->symtab;
+}
+
+/*
+ * call-seq:
+ *     DescriptorPool.new => pool
+ *
+ * Creates a new, empty, descriptor pool.
+ */
+static VALUE DescriptorPool_alloc(VALUE klass) {
+  DescriptorPool* self = ALLOC(DescriptorPool);
+  VALUE ret;
+
+  self->def_to_descriptor = Qnil;
+  ret = TypedData_Wrap_Struct(klass, &DescriptorPool_type, self);
+
+  self->def_to_descriptor = rb_hash_new();
+  self->symtab = upb_symtab_new();
+  ObjectCache_Add(self->symtab, ret, _upb_symtab_arena(self->symtab));
+
+  return ret;
+}
+
+/*
+ * call-seq:
+ *     DescriptorPool.build(&block)
+ *
+ * Invokes the block with a Builder instance as self. All message and enum types
+ * added within the block are committed to the pool atomically, and may refer
+ * (co)recursively to each other. The user should call Builder#add_message and
+ * Builder#add_enum within the block as appropriate.  This is the recommended,
+ * idiomatic way to define new message and enum types.
+ */
+static VALUE DescriptorPool_build(int argc, VALUE* argv, VALUE _self) {
+  VALUE ctx = rb_class_new_instance(1, &_self, cBuilder);
+  VALUE block = rb_block_proc();
+  rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
+  Builder_build(ctx);
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     DescriptorPool.lookup(name) => descriptor
+ *
+ * Finds a Descriptor or EnumDescriptor by name and returns it, or nil if none
+ * exists with the given name.
+ */
+static VALUE DescriptorPool_lookup(VALUE _self, VALUE name) {
+  DescriptorPool* self = ruby_to_DescriptorPool(_self);
+  const char* name_str = get_str(name);
+  const upb_msgdef* msgdef;
+  const upb_enumdef* enumdef;
+
+  msgdef = upb_symtab_lookupmsg(self->symtab, name_str);
+  if (msgdef) {
+    return get_msgdef_obj(_self, msgdef);
+  }
+
+  enumdef = upb_symtab_lookupenum(self->symtab, name_str);
+  if (enumdef) {
+    return get_enumdef_obj(_self, enumdef);
+  }
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     DescriptorPool.generated_pool => descriptor_pool
+ *
+ * Class method that returns the global DescriptorPool. This is a singleton into
+ * which generated-code message and enum types are registered. The user may also
+ * register types in this pool for convenience so that they do not have to hold
+ * a reference to a private pool instance.
+ */
+static VALUE DescriptorPool_generated_pool(VALUE _self) {
+  return generated_pool;
+}
+
+static void DescriptorPool_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "DescriptorPool", rb_cObject);
+  rb_define_alloc_func(klass, DescriptorPool_alloc);
+  rb_define_method(klass, "build", DescriptorPool_build, -1);
+  rb_define_method(klass, "lookup", DescriptorPool_lookup, 1);
+  rb_define_singleton_method(klass, "generated_pool",
+                             DescriptorPool_generated_pool, 0);
+  rb_gc_register_address(&cDescriptorPool);
+  cDescriptorPool = klass;
+
+  rb_gc_register_address(&generated_pool);
+  generated_pool = rb_class_new_instance(0, NULL, klass);
+}
+
+// -----------------------------------------------------------------------------
+// Descriptor.
+// -----------------------------------------------------------------------------
+
+typedef struct {
+  const upb_msgdef* msgdef;
+  VALUE klass;
+  VALUE descriptor_pool;
+} Descriptor;
+
+VALUE cDescriptor = Qnil;
+
+static void Descriptor_mark(void* _self) {
+  Descriptor* self = _self;
+  rb_gc_mark(self->klass);
+  rb_gc_mark(self->descriptor_pool);
+}
+
+static const rb_data_type_t Descriptor_type = {
+  "Google::Protobuf::Descriptor",
+  {Descriptor_mark, RUBY_DEFAULT_FREE, NULL},
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static Descriptor* ruby_to_Descriptor(VALUE val) {
+  Descriptor* ret;
+  TypedData_Get_Struct(val, Descriptor, &Descriptor_type, ret);
+  return ret;
+}
+
+/*
+ * call-seq:
+ *     Descriptor.new => descriptor
+ *
+ * Creates a new, empty, message type descriptor. At a minimum, its name must be
+ * set before it is added to a pool. It cannot be used to create messages until
+ * it is added to a pool, after which it becomes immutable (as part of a
+ * finalization process).
+ */
+static VALUE Descriptor_alloc(VALUE klass) {
+  Descriptor* self = ALLOC(Descriptor);
+  VALUE ret = TypedData_Wrap_Struct(klass, &Descriptor_type, self);
+  self->msgdef = NULL;
+  self->klass = Qnil;
+  self->descriptor_pool = Qnil;
+  return ret;
+}
+
+/*
+ * call-seq:
+ *    Descriptor.new(c_only_cookie, ptr) => Descriptor
+ *
+ * Creates a descriptor wrapper object.  May only be called from C.
+ */
+static VALUE Descriptor_initialize(VALUE _self, VALUE cookie,
+                                   VALUE descriptor_pool, VALUE ptr) {
+  Descriptor* self = ruby_to_Descriptor(_self);
+
+  if (cookie != c_only_cookie) {
+    rb_raise(rb_eRuntimeError,
+             "Descriptor objects may not be created from Ruby.");
+  }
+
+  self->descriptor_pool = descriptor_pool;
+  self->msgdef = (const upb_msgdef*)NUM2ULL(ptr);
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *    Descriptor.file_descriptor
+ *
+ * Returns the FileDescriptor object this message belongs to.
+ */
+static VALUE Descriptor_file_descriptor(VALUE _self) {
+  Descriptor* self = ruby_to_Descriptor(_self);
+  return get_filedef_obj(self->descriptor_pool, upb_msgdef_file(self->msgdef));
+}
+
+/*
+ * call-seq:
+ *     Descriptor.name => name
+ *
+ * Returns the name of this message type as a fully-qualified string (e.g.,
+ * My.Package.MessageType).
+ */
+static VALUE Descriptor_name(VALUE _self) {
+  Descriptor* self = ruby_to_Descriptor(_self);
+  return rb_str_maybe_null(upb_msgdef_fullname(self->msgdef));
+}
+
+/*
+ * call-seq:
+ *     Descriptor.each(&block)
+ *
+ * Iterates over fields in this message type, yielding to the block on each one.
+ */
+static VALUE Descriptor_each(VALUE _self) {
+  Descriptor* self = ruby_to_Descriptor(_self);
+
+  upb_msg_field_iter it;
+  for (upb_msg_field_begin(&it, self->msgdef);
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    const upb_fielddef* field = upb_msg_iter_field(&it);
+    VALUE obj = get_fielddef_obj(self->descriptor_pool, field);
+    rb_yield(obj);
+  }
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     Descriptor.lookup(name) => FieldDescriptor
+ *
+ * Returns the field descriptor for the field with the given name, if present,
+ * or nil if none.
+ */
+static VALUE Descriptor_lookup(VALUE _self, VALUE name) {
+  Descriptor* self = ruby_to_Descriptor(_self);
+  const char* s = get_str(name);
+  const upb_fielddef* field = upb_msgdef_ntofz(self->msgdef, s);
+  if (field == NULL) {
+    return Qnil;
+  }
+  return get_fielddef_obj(self->descriptor_pool, field);
+}
+
+/*
+ * call-seq:
+ *     Descriptor.each_oneof(&block) => nil
+ *
+ * Invokes the given block for each oneof in this message type, passing the
+ * corresponding OneofDescriptor.
+ */
+static VALUE Descriptor_each_oneof(VALUE _self) {
+  Descriptor* self = ruby_to_Descriptor(_self);
+
+  upb_msg_oneof_iter it;
+  for (upb_msg_oneof_begin(&it, self->msgdef);
+       !upb_msg_oneof_done(&it);
+       upb_msg_oneof_next(&it)) {
+    const upb_oneofdef* oneof = upb_msg_iter_oneof(&it);
+    VALUE obj = get_oneofdef_obj(self->descriptor_pool, oneof);
+    rb_yield(obj);
+  }
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     Descriptor.lookup_oneof(name) => OneofDescriptor
+ *
+ * Returns the oneof descriptor for the oneof with the given name, if present,
+ * or nil if none.
+ */
+static VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name) {
+  Descriptor* self = ruby_to_Descriptor(_self);
+  const char* s = get_str(name);
+  const upb_oneofdef* oneof = upb_msgdef_ntooz(self->msgdef, s);
+  if (oneof == NULL) {
+    return Qnil;
+  }
+  return get_oneofdef_obj(self->descriptor_pool, oneof);
+}
+
+/*
+ * call-seq:
+ *     Descriptor.msgclass => message_klass
+ *
+ * Returns the Ruby class created for this message type.
+ */
+static VALUE Descriptor_msgclass(VALUE _self) {
+  Descriptor* self = ruby_to_Descriptor(_self);
+  if (self->klass == Qnil) {
+    self->klass = build_class_from_descriptor(_self);
+  }
+  return self->klass;
+}
+
+static void Descriptor_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "Descriptor", rb_cObject);
+  rb_define_alloc_func(klass, Descriptor_alloc);
+  rb_define_method(klass, "initialize", Descriptor_initialize, 3);
+  rb_define_method(klass, "each", Descriptor_each, 0);
+  rb_define_method(klass, "lookup", Descriptor_lookup, 1);
+  rb_define_method(klass, "each_oneof", Descriptor_each_oneof, 0);
+  rb_define_method(klass, "lookup_oneof", Descriptor_lookup_oneof, 1);
+  rb_define_method(klass, "msgclass", Descriptor_msgclass, 0);
+  rb_define_method(klass, "name", Descriptor_name, 0);
+  rb_define_method(klass, "file_descriptor", Descriptor_file_descriptor, 0);
+  rb_include_module(klass, rb_mEnumerable);
+  rb_gc_register_address(&cDescriptor);
+  cDescriptor = klass;
+}
+
+// -----------------------------------------------------------------------------
+// FileDescriptor.
+// -----------------------------------------------------------------------------
+
+typedef struct {
+  const upb_filedef* filedef;
+  VALUE descriptor_pool;  // Owns the upb_filedef.
+} FileDescriptor;
+
+static VALUE cFileDescriptor = Qnil;
+
+static void FileDescriptor_mark(void* _self) {
+  FileDescriptor* self = _self;
+  rb_gc_mark(self->descriptor_pool);
+}
+
+static const rb_data_type_t FileDescriptor_type = {
+  "Google::Protobuf::FileDescriptor",
+  {FileDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static FileDescriptor* ruby_to_FileDescriptor(VALUE val) {
+  FileDescriptor* ret;
+  TypedData_Get_Struct(val, FileDescriptor, &FileDescriptor_type, ret);
+  return ret;
+}
+
+static VALUE FileDescriptor_alloc(VALUE klass) {
+  FileDescriptor* self = ALLOC(FileDescriptor);
+  VALUE ret = TypedData_Wrap_Struct(klass, &FileDescriptor_type, self);
+  self->descriptor_pool = Qnil;
+  self->filedef = NULL;
+  return ret;
+}
+
+/*
+ * call-seq:
+ *     FileDescriptor.new => file
+ *
+ * Returns a new file descriptor. The syntax must be set before it's passed
+ * to a builder.
+ */
+static VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie,
+                                VALUE descriptor_pool, VALUE ptr) {
+  FileDescriptor* self = ruby_to_FileDescriptor(_self);
+
+  if (cookie != c_only_cookie) {
+    rb_raise(rb_eRuntimeError,
+             "Descriptor objects may not be created from Ruby.");
+  }
+
+  self->descriptor_pool = descriptor_pool;
+  self->filedef = (const upb_filedef*)NUM2ULL(ptr);
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     FileDescriptor.name => name
+ *
+ * Returns the name of the file.
+ */
+static VALUE FileDescriptor_name(VALUE _self) {
+  FileDescriptor* self = ruby_to_FileDescriptor(_self);
+  const char* name = upb_filedef_name(self->filedef);
+  return name == NULL ? Qnil : rb_str_new2(name);
+}
+
+/*
+ * call-seq:
+ *     FileDescriptor.syntax => syntax
+ *
+ * Returns this file descriptors syntax.
+ *
+ * Valid syntax versions are:
+ *     :proto2 or :proto3.
+ */
+static VALUE FileDescriptor_syntax(VALUE _self) {
+  FileDescriptor* self = ruby_to_FileDescriptor(_self);
+
+  switch (upb_filedef_syntax(self->filedef)) {
+    case UPB_SYNTAX_PROTO3: return ID2SYM(rb_intern("proto3"));
+    case UPB_SYNTAX_PROTO2: return ID2SYM(rb_intern("proto2"));
+    default: return Qnil;
+  }
+}
+
+static void FileDescriptor_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "FileDescriptor", rb_cObject);
+  rb_define_alloc_func(klass, FileDescriptor_alloc);
+  rb_define_method(klass, "initialize", FileDescriptor_initialize, 3);
+  rb_define_method(klass, "name", FileDescriptor_name, 0);
+  rb_define_method(klass, "syntax", FileDescriptor_syntax, 0);
+  rb_gc_register_address(&cFileDescriptor);
+  cFileDescriptor = klass;
+}
+
+// -----------------------------------------------------------------------------
+// FieldDescriptor.
+// -----------------------------------------------------------------------------
+
+typedef struct {
+  const upb_fielddef* fielddef;
+  VALUE descriptor_pool;  // Owns the upb_fielddef.
+} FieldDescriptor;
+
+static VALUE cFieldDescriptor = Qnil;
+
+static void FieldDescriptor_mark(void* _self) {
+  FieldDescriptor* self = _self;
+  rb_gc_mark(self->descriptor_pool);
+}
+
+static const rb_data_type_t FieldDescriptor_type = {
+  "Google::Protobuf::FieldDescriptor",
+  {FieldDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static FieldDescriptor* ruby_to_FieldDescriptor(VALUE val) {
+  FieldDescriptor* ret;
+  TypedData_Get_Struct(val, FieldDescriptor, &FieldDescriptor_type, ret);
+  return ret;
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.new => field
+ *
+ * Returns a new field descriptor. Its name, type, etc. must be set before it is
+ * added to a message type.
+ */
+static VALUE FieldDescriptor_alloc(VALUE klass) {
+  FieldDescriptor* self = ALLOC(FieldDescriptor);
+  VALUE ret = TypedData_Wrap_Struct(klass, &FieldDescriptor_type, self);
+  self->fielddef = NULL;
+  return ret;
+}
+
+/*
+ * call-seq:
+ *    EnumDescriptor.new(c_only_cookie, pool, ptr) => EnumDescriptor
+ *
+ * Creates a descriptor wrapper object.  May only be called from C.
+ */
+static VALUE FieldDescriptor_initialize(VALUE _self, VALUE cookie,
+                                        VALUE descriptor_pool, VALUE ptr) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+
+  if (cookie != c_only_cookie) {
+    rb_raise(rb_eRuntimeError,
+             "Descriptor objects may not be created from Ruby.");
+  }
+
+  self->descriptor_pool = descriptor_pool;
+  self->fielddef = (const upb_fielddef*)NUM2ULL(ptr);
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.name => name
+ *
+ * Returns the name of this field.
+ */
+static VALUE FieldDescriptor_name(VALUE _self) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  return rb_str_maybe_null(upb_fielddef_name(self->fielddef));
+}
+
+// Non-static, exposed to other .c files.
+upb_fieldtype_t ruby_to_fieldtype(VALUE type) {
+  if (TYPE(type) != T_SYMBOL) {
+    rb_raise(rb_eArgError, "Expected symbol for field type.");
+  }
+
+#define CONVERT(upb, ruby)                                           \
+  if (SYM2ID(type) == rb_intern( # ruby )) {                         \
+    return UPB_TYPE_ ## upb;                                         \
+  }
+
+  CONVERT(FLOAT, float);
+  CONVERT(DOUBLE, double);
+  CONVERT(BOOL, bool);
+  CONVERT(STRING, string);
+  CONVERT(BYTES, bytes);
+  CONVERT(MESSAGE, message);
+  CONVERT(ENUM, enum);
+  CONVERT(INT32, int32);
+  CONVERT(INT64, int64);
+  CONVERT(UINT32, uint32);
+  CONVERT(UINT64, uint64);
+
+#undef CONVERT
+
+  rb_raise(rb_eArgError, "Unknown field type.");
+  return 0;
+}
+
+static upb_descriptortype_t ruby_to_descriptortype(VALUE type) {
+  if (TYPE(type) != T_SYMBOL) {
+    rb_raise(rb_eArgError, "Expected symbol for field type.");
+  }
+
+#define CONVERT(upb, ruby)                                           \
+  if (SYM2ID(type) == rb_intern( # ruby )) {                         \
+    return UPB_DESCRIPTOR_TYPE_ ## upb;                              \
+  }
+
+  CONVERT(FLOAT, float);
+  CONVERT(DOUBLE, double);
+  CONVERT(BOOL, bool);
+  CONVERT(STRING, string);
+  CONVERT(BYTES, bytes);
+  CONVERT(MESSAGE, message);
+  CONVERT(GROUP, group);
+  CONVERT(ENUM, enum);
+  CONVERT(INT32, int32);
+  CONVERT(INT64, int64);
+  CONVERT(UINT32, uint32);
+  CONVERT(UINT64, uint64);
+  CONVERT(SINT32, sint32);
+  CONVERT(SINT64, sint64);
+  CONVERT(FIXED32, fixed32);
+  CONVERT(FIXED64, fixed64);
+  CONVERT(SFIXED32, sfixed32);
+  CONVERT(SFIXED64, sfixed64);
+
+#undef CONVERT
+
+  rb_raise(rb_eArgError, "Unknown field type.");
+  return 0;
+}
+
+static VALUE descriptortype_to_ruby(upb_descriptortype_t type) {
+  switch (type) {
+#define CONVERT(upb, ruby)                                           \
+    case UPB_DESCRIPTOR_TYPE_ ## upb : return ID2SYM(rb_intern( # ruby ));
+    CONVERT(FLOAT, float);
+    CONVERT(DOUBLE, double);
+    CONVERT(BOOL, bool);
+    CONVERT(STRING, string);
+    CONVERT(BYTES, bytes);
+    CONVERT(MESSAGE, message);
+    CONVERT(GROUP, group);
+    CONVERT(ENUM, enum);
+    CONVERT(INT32, int32);
+    CONVERT(INT64, int64);
+    CONVERT(UINT32, uint32);
+    CONVERT(UINT64, uint64);
+    CONVERT(SINT32, sint32);
+    CONVERT(SINT64, sint64);
+    CONVERT(FIXED32, fixed32);
+    CONVERT(FIXED64, fixed64);
+    CONVERT(SFIXED32, sfixed32);
+    CONVERT(SFIXED64, sfixed64);
+#undef CONVERT
+  }
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.type => type
+ *
+ * Returns this field's type, as a Ruby symbol, or nil if not yet set.
+ *
+ * Valid field types are:
+ *     :int32, :int64, :uint32, :uint64, :float, :double, :bool, :string,
+ *     :bytes, :message.
+ */
+static VALUE FieldDescriptor__type(VALUE _self) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  return descriptortype_to_ruby(upb_fielddef_descriptortype(self->fielddef));
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.default => default
+ *
+ * Returns this field's default, as a Ruby object, or nil if not yet set.
+ */
+static VALUE FieldDescriptor_default(VALUE _self) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  const upb_fielddef *f = self->fielddef;
+  upb_msgval default_val = {0};
+  if (upb_fielddef_issubmsg(f)) {
+    return Qnil;
+  } else if (!upb_fielddef_isseq(f)) {
+    default_val = upb_fielddef_default(f);
+  }
+  return Convert_UpbToRuby(default_val, TypeInfo_get(self->fielddef), Qnil);
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.label => label
+ *
+ * Returns this field's label (i.e., plurality), as a Ruby symbol.
+ *
+ * Valid field labels are:
+ *     :optional, :repeated
+ */
+static VALUE FieldDescriptor_label(VALUE _self) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  switch (upb_fielddef_label(self->fielddef)) {
+#define CONVERT(upb, ruby)                                           \
+    case UPB_LABEL_ ## upb : return ID2SYM(rb_intern( # ruby ));
+
+    CONVERT(OPTIONAL, optional);
+    CONVERT(REQUIRED, required);
+    CONVERT(REPEATED, repeated);
+
+#undef CONVERT
+  }
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.number => number
+ *
+ * Returns the tag number for this field.
+ */
+static VALUE FieldDescriptor_number(VALUE _self) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  return INT2NUM(upb_fielddef_number(self->fielddef));
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.submsg_name => submsg_name
+ *
+ * Returns the name of the message or enum type corresponding to this field, if
+ * it is a message or enum field (respectively), or nil otherwise. This type
+ * name will be resolved within the context of the pool to which the containing
+ * message type is added.
+ */
+static VALUE FieldDescriptor_submsg_name(VALUE _self) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  switch (upb_fielddef_type(self->fielddef)) {
+    case UPB_TYPE_ENUM:
+      return rb_str_new2(
+          upb_enumdef_fullname(upb_fielddef_enumsubdef(self->fielddef)));
+    case UPB_TYPE_MESSAGE:
+      return rb_str_new2(
+          upb_msgdef_fullname(upb_fielddef_msgsubdef(self->fielddef)));
+    default:
+      return Qnil;
+  }
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.subtype => message_or_enum_descriptor
+ *
+ * Returns the message or enum descriptor corresponding to this field's type if
+ * it is a message or enum field, respectively, or nil otherwise. Cannot be
+ * called *until* the containing message type is added to a pool (and thus
+ * resolved).
+ */
+static VALUE FieldDescriptor_subtype(VALUE _self) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  switch (upb_fielddef_type(self->fielddef)) {
+    case UPB_TYPE_ENUM:
+      return get_enumdef_obj(self->descriptor_pool,
+                             upb_fielddef_enumsubdef(self->fielddef));
+    case UPB_TYPE_MESSAGE:
+      return get_msgdef_obj(self->descriptor_pool,
+                            upb_fielddef_msgsubdef(self->fielddef));
+    default:
+      return Qnil;
+  }
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.get(message) => value
+ *
+ * Returns the value set for this field on the given message. Raises an
+ * exception if message is of the wrong type.
+ */
+static VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  const upb_msgdef *m;
+  const upb_msgdef *msg = Message_Get(msg_rb, &m);
+  VALUE arena = Message_GetArena(msg_rb);
+  upb_msgval msgval;
+
+  if (m != upb_fielddef_containingtype(self->fielddef)) {
+    rb_raise(cTypeError, "get method called on wrong message type");
+  }
+
+  msgval = upb_msg_get(msg, self->fielddef);
+  return Convert_UpbToRuby(msgval, TypeInfo_get(self->fielddef), arena);
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.has?(message) => boolean
+ *
+ * Returns whether the value is set on the given message. Raises an
+ * exception when calling for fields that do not have presence.
+ */
+static VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  const upb_msgdef *m;
+  const upb_msgdef *msg = Message_Get(msg_rb, &m);
+
+  if (m != upb_fielddef_containingtype(self->fielddef)) {
+    rb_raise(cTypeError, "has method called on wrong message type");
+  } else if (!upb_fielddef_haspresence(self->fielddef)) {
+    rb_raise(rb_eArgError, "does not track presence");
+  }
+
+  return upb_msg_has(msg, self->fielddef) ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.clear(message)
+ *
+ * Clears the field from the message if it's set.
+ */
+static VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  const upb_msgdef *m;
+  upb_msgdef *msg = Message_GetMutable(msg_rb, &m);
+
+  if (m != upb_fielddef_containingtype(self->fielddef)) {
+    rb_raise(cTypeError, "has method called on wrong message type");
+  }
+
+  upb_msg_clearfield(msg, self->fielddef);
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     FieldDescriptor.set(message, value)
+ *
+ * Sets the value corresponding to this field to the given value on the given
+ * message. Raises an exception if message is of the wrong type. Performs the
+ * ordinary type-checks for field setting.
+ */
+static VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
+  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
+  const upb_msgdef *m;
+  upb_msgdef *msg = Message_GetMutable(msg_rb, &m);
+  upb_arena *arena = Arena_get(Message_GetArena(msg_rb));
+  upb_msgval msgval;
+
+  if (m != upb_fielddef_containingtype(self->fielddef)) {
+    rb_raise(cTypeError, "set method called on wrong message type");
+  }
+
+  msgval = Convert_RubyToUpb(value, upb_fielddef_name(self->fielddef),
+                             TypeInfo_get(self->fielddef), arena);
+  upb_msg_set(msg, self->fielddef, msgval, arena);
+  return Qnil;
+}
+
+static void FieldDescriptor_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "FieldDescriptor", rb_cObject);
+  rb_define_alloc_func(klass, FieldDescriptor_alloc);
+  rb_define_method(klass, "initialize", FieldDescriptor_initialize, 3);
+  rb_define_method(klass, "name", FieldDescriptor_name, 0);
+  rb_define_method(klass, "type", FieldDescriptor__type, 0);
+  rb_define_method(klass, "default", FieldDescriptor_default, 0);
+  rb_define_method(klass, "label", FieldDescriptor_label, 0);
+  rb_define_method(klass, "number", FieldDescriptor_number, 0);
+  rb_define_method(klass, "submsg_name", FieldDescriptor_submsg_name, 0);
+  rb_define_method(klass, "subtype", FieldDescriptor_subtype, 0);
+  rb_define_method(klass, "has?", FieldDescriptor_has, 1);
+  rb_define_method(klass, "clear", FieldDescriptor_clear, 1);
+  rb_define_method(klass, "get", FieldDescriptor_get, 1);
+  rb_define_method(klass, "set", FieldDescriptor_set, 2);
+  rb_gc_register_address(&cFieldDescriptor);
+  cFieldDescriptor = klass;
+}
+
+// -----------------------------------------------------------------------------
+// OneofDescriptor.
+// -----------------------------------------------------------------------------
+
+typedef struct {
+  const upb_oneofdef* oneofdef;
+  VALUE descriptor_pool;  // Owns the upb_oneofdef.
+} OneofDescriptor;
+
+static VALUE cOneofDescriptor = Qnil;
+
+static void OneofDescriptor_mark(void* _self) {
+  OneofDescriptor* self = _self;
+  rb_gc_mark(self->descriptor_pool);
+}
+
+static const rb_data_type_t OneofDescriptor_type = {
+    "Google::Protobuf::OneofDescriptor",
+    {OneofDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
+    .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static OneofDescriptor* ruby_to_OneofDescriptor(VALUE val) {
+  OneofDescriptor* ret;
+  TypedData_Get_Struct(val, OneofDescriptor, &OneofDescriptor_type, ret);
+  return ret;
+}
+
+/*
+ * call-seq:
+ *     OneofDescriptor.new => oneof_descriptor
+ *
+ * Creates a new, empty, oneof descriptor. The oneof may only be modified prior
+ * to being added to a message descriptor which is subsequently added to a pool.
+ */
+static VALUE OneofDescriptor_alloc(VALUE klass) {
+  OneofDescriptor* self = ALLOC(OneofDescriptor);
+  VALUE ret = TypedData_Wrap_Struct(klass, &OneofDescriptor_type, self);
+  self->oneofdef = NULL;
+  self->descriptor_pool = Qnil;
+  return ret;
+}
+
+/*
+ * call-seq:
+ *    OneofDescriptor.new(c_only_cookie, pool, ptr) => OneofDescriptor
+ *
+ * Creates a descriptor wrapper object.  May only be called from C.
+ */
+static VALUE OneofDescriptor_initialize(VALUE _self, VALUE cookie,
+                                 VALUE descriptor_pool, VALUE ptr) {
+  OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
+
+  if (cookie != c_only_cookie) {
+    rb_raise(rb_eRuntimeError,
+             "Descriptor objects may not be created from Ruby.");
+  }
+
+  self->descriptor_pool = descriptor_pool;
+  self->oneofdef = (const upb_oneofdef*)NUM2ULL(ptr);
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     OneofDescriptor.name => name
+ *
+ * Returns the name of this oneof.
+ */
+static VALUE OneofDescriptor_name(VALUE _self) {
+  OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
+  return rb_str_maybe_null(upb_oneofdef_name(self->oneofdef));
+}
+
+/*
+ * call-seq:
+ *     OneofDescriptor.each(&block) => nil
+ *
+ * Iterates through fields in this oneof, yielding to the block on each one.
+ */
+static VALUE OneofDescriptor_each(VALUE _self) {
+  OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
+  upb_oneof_iter it;
+  for (upb_oneof_begin(&it, self->oneofdef);
+       !upb_oneof_done(&it);
+       upb_oneof_next(&it)) {
+    const upb_fielddef* f = upb_oneof_iter_field(&it);
+    VALUE obj = get_fielddef_obj(self->descriptor_pool, f);
+    rb_yield(obj);
+  }
+  return Qnil;
+}
+
+static void OneofDescriptor_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "OneofDescriptor", rb_cObject);
+  rb_define_alloc_func(klass, OneofDescriptor_alloc);
+  rb_define_method(klass, "initialize", OneofDescriptor_initialize, 3);
+  rb_define_method(klass, "name", OneofDescriptor_name, 0);
+  rb_define_method(klass, "each", OneofDescriptor_each, 0);
+  rb_include_module(klass, rb_mEnumerable);
+  rb_gc_register_address(&cOneofDescriptor);
+  cOneofDescriptor = klass;
+}
+
+// -----------------------------------------------------------------------------
+// EnumDescriptor.
+// -----------------------------------------------------------------------------
+
+typedef struct {
+  const upb_enumdef* enumdef;
+  VALUE module;  // begins as nil
+  VALUE descriptor_pool;  // Owns the upb_enumdef.
+} EnumDescriptor;
+
+static VALUE cEnumDescriptor = Qnil;
+
+static void EnumDescriptor_mark(void* _self) {
+  EnumDescriptor* self = _self;
+  rb_gc_mark(self->module);
+  rb_gc_mark(self->descriptor_pool);
+}
+
+static const rb_data_type_t EnumDescriptor_type = {
+  "Google::Protobuf::EnumDescriptor",
+  {EnumDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static EnumDescriptor* ruby_to_EnumDescriptor(VALUE val) {
+  EnumDescriptor* ret;
+  TypedData_Get_Struct(val, EnumDescriptor, &EnumDescriptor_type, ret);
+  return ret;
+}
+
+static VALUE EnumDescriptor_alloc(VALUE klass) {
+  EnumDescriptor* self = ALLOC(EnumDescriptor);
+  VALUE ret = TypedData_Wrap_Struct(klass, &EnumDescriptor_type, self);
+  self->enumdef = NULL;
+  self->module = Qnil;
+  self->descriptor_pool = Qnil;
+  return ret;
+}
+
+// Exposed to other modules in defs.h.
+const upb_enumdef *EnumDescriptor_GetEnumDef(VALUE enum_desc_rb) {
+  EnumDescriptor *desc = ruby_to_EnumDescriptor(enum_desc_rb);
+  return desc->enumdef;
+}
+
+/*
+ * call-seq:
+ *    EnumDescriptor.new(c_only_cookie, ptr) => EnumDescriptor
+ *
+ * Creates a descriptor wrapper object.  May only be called from C.
+ */
+static VALUE EnumDescriptor_initialize(VALUE _self, VALUE cookie,
+                                       VALUE descriptor_pool, VALUE ptr) {
+  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
+
+  if (cookie != c_only_cookie) {
+    rb_raise(rb_eRuntimeError,
+             "Descriptor objects may not be created from Ruby.");
+  }
+
+  self->descriptor_pool = descriptor_pool;
+  self->enumdef = (const upb_enumdef*)NUM2ULL(ptr);
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *    EnumDescriptor.file_descriptor
+ *
+ * Returns the FileDescriptor object this enum belongs to.
+ */
+static VALUE EnumDescriptor_file_descriptor(VALUE _self) {
+  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
+  return get_filedef_obj(self->descriptor_pool,
+                         upb_enumdef_file(self->enumdef));
+}
+
+/*
+ * call-seq:
+ *     EnumDescriptor.name => name
+ *
+ * Returns the name of this enum type.
+ */
+static VALUE EnumDescriptor_name(VALUE _self) {
+  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
+  return rb_str_maybe_null(upb_enumdef_fullname(self->enumdef));
+}
+
+/*
+ * call-seq:
+ *     EnumDescriptor.lookup_name(name) => value
+ *
+ * Returns the numeric value corresponding to the given key name (as a Ruby
+ * symbol), or nil if none.
+ */
+static VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) {
+  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
+  const char* name_str= rb_id2name(SYM2ID(name));
+  int32_t val = 0;
+  if (upb_enumdef_ntoiz(self->enumdef, name_str, &val)) {
+    return INT2NUM(val);
+  } else {
+    return Qnil;
+  }
+}
+
+/*
+ * call-seq:
+ *     EnumDescriptor.lookup_value(name) => value
+ *
+ * Returns the key name (as a Ruby symbol) corresponding to the integer value,
+ * or nil if none.
+ */
+static VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number) {
+  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
+  int32_t val = NUM2INT(number);
+  const char* name = upb_enumdef_iton(self->enumdef, val);
+  if (name != NULL) {
+    return ID2SYM(rb_intern(name));
+  } else {
+    return Qnil;
+  }
+}
+
+/*
+ * call-seq:
+ *     EnumDescriptor.each(&block)
+ *
+ * Iterates over key => value mappings in this enum's definition, yielding to
+ * the block with (key, value) arguments for each one.
+ */
+static VALUE EnumDescriptor_each(VALUE _self) {
+  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
+
+  upb_enum_iter it;
+  for (upb_enum_begin(&it, self->enumdef);
+       !upb_enum_done(&it);
+       upb_enum_next(&it)) {
+    VALUE key = ID2SYM(rb_intern(upb_enum_iter_name(&it)));
+    VALUE number = INT2NUM(upb_enum_iter_number(&it));
+    rb_yield_values(2, key, number);
+  }
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     EnumDescriptor.enummodule => module
+ *
+ * Returns the Ruby module corresponding to this enum type.
+ */
+static VALUE EnumDescriptor_enummodule(VALUE _self) {
+  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
+  if (self->module == Qnil) {
+    self->module = build_module_from_enumdesc(_self);
+  }
+  return self->module;
+}
+
+static void EnumDescriptor_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "EnumDescriptor", rb_cObject);
+  rb_define_alloc_func(klass, EnumDescriptor_alloc);
+  rb_define_method(klass, "initialize", EnumDescriptor_initialize, 3);
+  rb_define_method(klass, "name", EnumDescriptor_name, 0);
+  rb_define_method(klass, "lookup_name", EnumDescriptor_lookup_name, 1);
+  rb_define_method(klass, "lookup_value", EnumDescriptor_lookup_value, 1);
+  rb_define_method(klass, "each", EnumDescriptor_each, 0);
+  rb_define_method(klass, "enummodule", EnumDescriptor_enummodule, 0);
+  rb_define_method(klass, "file_descriptor", EnumDescriptor_file_descriptor, 0);
+  rb_include_module(klass, rb_mEnumerable);
+  rb_gc_register_address(&cEnumDescriptor);
+  cEnumDescriptor = klass;
+}
+
+// -----------------------------------------------------------------------------
+// FileBuilderContext.
+// -----------------------------------------------------------------------------
+
+typedef struct {
+  upb_arena *arena;
+  google_protobuf_FileDescriptorProto* file_proto;
+  VALUE descriptor_pool;
+} FileBuilderContext;
+
+static VALUE cFileBuilderContext = Qnil;
+
+static void FileBuilderContext_mark(void* _self) {
+  FileBuilderContext* self = _self;
+  rb_gc_mark(self->descriptor_pool);
+}
+
+static void FileBuilderContext_free(void* _self) {
+  FileBuilderContext* self = _self;
+  upb_arena_free(self->arena);
+  xfree(self);
+}
+
+static const rb_data_type_t FileBuilderContext_type = {
+  "Google::Protobuf::Internal::FileBuilderContext",
+  {FileBuilderContext_mark, FileBuilderContext_free, NULL},
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static FileBuilderContext* ruby_to_FileBuilderContext(VALUE val) {
+  FileBuilderContext* ret;
+  TypedData_Get_Struct(val, FileBuilderContext, &FileBuilderContext_type, ret);
+  return ret;
+}
+
+static upb_strview FileBuilderContext_strdup2(VALUE _self, const char *str) {
+  FileBuilderContext* self = ruby_to_FileBuilderContext(_self);
+  upb_strview ret;
+  char *data;
+
+  ret.size = strlen(str);
+  data = upb_malloc(upb_arena_alloc(self->arena), ret.size + 1);
+  ret.data = data;
+  memcpy(data, str, ret.size);
+  /* Null-terminate required by rewrite_enum_defaults() above. */
+  data[ret.size] = '\0';
+  return ret;
+}
+
+static upb_strview FileBuilderContext_strdup(VALUE _self, VALUE rb_str) {
+  return FileBuilderContext_strdup2(_self, get_str(rb_str));
+}
+
+static upb_strview FileBuilderContext_strdup_sym(VALUE _self, VALUE rb_sym) {
+  Check_Type(rb_sym, T_SYMBOL);
+  return FileBuilderContext_strdup(_self, rb_id2str(SYM2ID(rb_sym)));
+}
+
+static VALUE FileBuilderContext_alloc(VALUE klass) {
+  FileBuilderContext* self = ALLOC(FileBuilderContext);
+  VALUE ret = TypedData_Wrap_Struct(klass, &FileBuilderContext_type, self);
+  self->arena = upb_arena_new();
+  self->file_proto = google_protobuf_FileDescriptorProto_new(self->arena);
+  self->descriptor_pool = Qnil;
+  return ret;
+}
+
+/*
+ * call-seq:
+ *     FileBuilderContext.new(descriptor_pool) => context
+ *
+ * Create a new file builder context for the given file descriptor and
+ * builder context. This class is intended to serve as a DSL context to be used
+ * with #instance_eval.
+ */
+static VALUE FileBuilderContext_initialize(VALUE _self, VALUE descriptor_pool,
+                                           VALUE name, VALUE options) {
+  FileBuilderContext* self = ruby_to_FileBuilderContext(_self);
+  self->descriptor_pool = descriptor_pool;
+
+  google_protobuf_FileDescriptorProto_set_name(
+      self->file_proto, FileBuilderContext_strdup(_self, name));
+
+  // Default syntax for Ruby is proto3.
+  google_protobuf_FileDescriptorProto_set_syntax(
+      self->file_proto,
+      FileBuilderContext_strdup(_self, rb_str_new2("proto3")));
+
+  if (options != Qnil) {
+    VALUE syntax;
+
+    Check_Type(options, T_HASH);
+    syntax = rb_hash_lookup2(options, ID2SYM(rb_intern("syntax")), Qnil);
+
+    if (syntax != Qnil) {
+      VALUE syntax_str;
+
+      Check_Type(syntax, T_SYMBOL);
+      syntax_str = rb_id2str(SYM2ID(syntax));
+      google_protobuf_FileDescriptorProto_set_syntax(
+          self->file_proto, FileBuilderContext_strdup(_self, syntax_str));
+    }
+  }
+
+  return Qnil;
+}
+
+static void MessageBuilderContext_add_synthetic_oneofs(VALUE _self);
+
+/*
+ * call-seq:
+ *     FileBuilderContext.add_message(name, &block)
+ *
+ * Creates a new, empty descriptor with the given name, and invokes the block in
+ * the context of a MessageBuilderContext on that descriptor. The block can then
+ * call, e.g., MessageBuilderContext#optional and MessageBuilderContext#repeated
+ * methods to define the message fields.
+ *
+ * This is the recommended, idiomatic way to build message definitions.
+ */
+static VALUE FileBuilderContext_add_message(VALUE _self, VALUE name) {
+  VALUE args[2] = { _self, name };
+  VALUE ctx = rb_class_new_instance(2, args, cMessageBuilderContext);
+  VALUE block = rb_block_proc();
+  rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
+  MessageBuilderContext_add_synthetic_oneofs(ctx);
+  return Qnil;
+}
+
 /* We have to do some relatively complicated logic here for backward
  * compatibility.
  *
@@ -334,1113 +1598,83 @@
       file_proto, RARRAY_LEN(enum_ents), arena);
 }
 
-// -----------------------------------------------------------------------------
-// DescriptorPool.
-// -----------------------------------------------------------------------------
-
-#define DEFINE_CLASS(name, string_name)                             \
-    VALUE c ## name = Qnil;                                         \
-    const rb_data_type_t _ ## name ## _type = {                     \
-      string_name,                                                  \
-      { name ## _mark, name ## _free, NULL },                       \
-    };                                                              \
-    name* ruby_to_ ## name(VALUE val) {                             \
-      name* ret;                                                    \
-      TypedData_Get_Struct(val, name, &_ ## name ## _type, ret);    \
-      return ret;                                                   \
-    }                                                               \
-
-#define DEFINE_SELF(type, var, rb_var)                              \
-    type* var = ruby_to_ ## type(rb_var)
-
-// Global singleton DescriptorPool. The user is free to create others, but this
-// is used by generated code.
-VALUE generated_pool = Qnil;
-
-DEFINE_CLASS(DescriptorPool, "Google::Protobuf::DescriptorPool");
-
-void DescriptorPool_mark(void* _self) {
-  DescriptorPool* self = _self;
-  rb_gc_mark(self->def_to_descriptor);
-}
-
-void DescriptorPool_free(void* _self) {
-  DescriptorPool* self = _self;
-
-  upb_symtab_free(self->symtab);
-  upb_handlercache_free(self->fill_handler_cache);
-  upb_handlercache_free(self->pb_serialize_handler_cache);
-  upb_handlercache_free(self->json_serialize_handler_cache);
-  upb_handlercache_free(self->json_serialize_handler_preserve_cache);
-  upb_pbcodecache_free(self->fill_method_cache);
-  upb_json_codecache_free(self->json_fill_method_cache);
-
-  xfree(self);
-}
-
 /*
  * call-seq:
- *     DescriptorPool.new => pool
+ *     FileBuilderContext.add_enum(name, &block)
  *
- * Creates a new, empty, descriptor pool.
- */
-VALUE DescriptorPool_alloc(VALUE klass) {
-  DescriptorPool* self = ALLOC(DescriptorPool);
-  VALUE ret;
-
-  self->def_to_descriptor = Qnil;
-  ret = TypedData_Wrap_Struct(klass, &_DescriptorPool_type, self);
-
-  self->def_to_descriptor = rb_hash_new();
-  self->symtab = upb_symtab_new();
-  self->fill_handler_cache =
-      upb_handlercache_new(add_handlers_for_message, (void*)ret);
-  self->pb_serialize_handler_cache = upb_pb_encoder_newcache();
-  self->json_serialize_handler_cache = upb_json_printer_newcache(false);
-  self->json_serialize_handler_preserve_cache =
-      upb_json_printer_newcache(true);
-  self->fill_method_cache = upb_pbcodecache_new(self->fill_handler_cache);
-  self->json_fill_method_cache = upb_json_codecache_new();
-
-  return ret;
-}
-
-void DescriptorPool_register(VALUE module) {
-  VALUE klass = rb_define_class_under(
-      module, "DescriptorPool", rb_cObject);
-  rb_define_alloc_func(klass, DescriptorPool_alloc);
-  rb_define_method(klass, "build", DescriptorPool_build, -1);
-  rb_define_method(klass, "lookup", DescriptorPool_lookup, 1);
-  rb_define_singleton_method(klass, "generated_pool",
-                             DescriptorPool_generated_pool, 0);
-  rb_gc_register_address(&cDescriptorPool);
-  cDescriptorPool = klass;
-
-  rb_gc_register_address(&generated_pool);
-  generated_pool = rb_class_new_instance(0, NULL, klass);
-}
-
-/*
- * call-seq:
- *     DescriptorPool.build(&block)
+ * Creates a new, empty enum descriptor with the given name, and invokes the
+ * block in the context of an EnumBuilderContext on that descriptor. The block
+ * can then call EnumBuilderContext#add_value to define the enum values.
  *
- * Invokes the block with a Builder instance as self. All message and enum types
- * added within the block are committed to the pool atomically, and may refer
- * (co)recursively to each other. The user should call Builder#add_message and
- * Builder#add_enum within the block as appropriate.  This is the recommended,
- * idiomatic way to define new message and enum types.
+ * This is the recommended, idiomatic way to build enum definitions.
  */
-VALUE DescriptorPool_build(int argc, VALUE* argv, VALUE _self) {
-  VALUE ctx = rb_class_new_instance(1, &_self, cBuilder);
+static VALUE FileBuilderContext_add_enum(VALUE _self, VALUE name) {
+  VALUE args[2] = { _self, name };
+  VALUE ctx = rb_class_new_instance(2, args, cEnumBuilderContext);
   VALUE block = rb_block_proc();
   rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
-  Builder_build(ctx);
   return Qnil;
 }
 
-/*
- * call-seq:
- *     DescriptorPool.lookup(name) => descriptor
- *
- * Finds a Descriptor or EnumDescriptor by name and returns it, or nil if none
- * exists with the given name.
- */
-VALUE DescriptorPool_lookup(VALUE _self, VALUE name) {
-  DEFINE_SELF(DescriptorPool, self, _self);
-  const char* name_str = get_str(name);
-  const upb_msgdef* msgdef;
-  const upb_enumdef* enumdef;
+static void FileBuilderContext_build(VALUE _self) {
+  FileBuilderContext* self = ruby_to_FileBuilderContext(_self);
+  DescriptorPool* pool = ruby_to_DescriptorPool(self->descriptor_pool);
+  upb_status status;
 
-  msgdef = upb_symtab_lookupmsg(self->symtab, name_str);
-  if (msgdef) {
-    return get_msgdef_obj(_self, msgdef);
-  }
+  rewrite_enum_defaults(pool->symtab, self->file_proto);
+  rewrite_names(_self, self->file_proto);
 
-  enumdef = upb_symtab_lookupenum(self->symtab, name_str);
-  if (enumdef) {
-    return get_enumdef_obj(_self, enumdef);
-  }
-
-  return Qnil;
-}
-
-/*
- * call-seq:
- *     DescriptorPool.generated_pool => descriptor_pool
- *
- * Class method that returns the global DescriptorPool. This is a singleton into
- * which generated-code message and enum types are registered. The user may also
- * register types in this pool for convenience so that they do not have to hold
- * a reference to a private pool instance.
- */
-VALUE DescriptorPool_generated_pool(VALUE _self) {
-  return generated_pool;
-}
-
-// -----------------------------------------------------------------------------
-// Descriptor.
-// -----------------------------------------------------------------------------
-
-DEFINE_CLASS(Descriptor, "Google::Protobuf::Descriptor");
-
-void Descriptor_mark(void* _self) {
-  Descriptor* self = _self;
-  rb_gc_mark(self->klass);
-  rb_gc_mark(self->descriptor_pool);
-  if (self->layout && self->layout->empty_template) {
-    layout_mark(self->layout, self->layout->empty_template);
+  upb_status_clear(&status);
+  if (!upb_symtab_addfile(pool->symtab, self->file_proto, &status)) {
+    rb_raise(cTypeError, "Unable to add defs to DescriptorPool: %s",
+             upb_status_errmsg(&status));
   }
 }
 
-void Descriptor_free(void* _self) {
-  Descriptor* self = _self;
-  if (self->layout) {
-    free_layout(self->layout);
-  }
-  xfree(self);
-}
-
-/*
- * call-seq:
- *     Descriptor.new => descriptor
- *
- * Creates a new, empty, message type descriptor. At a minimum, its name must be
- * set before it is added to a pool. It cannot be used to create messages until
- * it is added to a pool, after which it becomes immutable (as part of a
- * finalization process).
- */
-VALUE Descriptor_alloc(VALUE klass) {
-  Descriptor* self = ALLOC(Descriptor);
-  VALUE ret = TypedData_Wrap_Struct(klass, &_Descriptor_type, self);
-  self->msgdef = NULL;
-  self->klass = Qnil;
-  self->descriptor_pool = Qnil;
-  self->layout = NULL;
-  return ret;
-}
-
-void Descriptor_register(VALUE module) {
-  VALUE klass = rb_define_class_under(
-      module, "Descriptor", rb_cObject);
-  rb_define_alloc_func(klass, Descriptor_alloc);
-  rb_define_method(klass, "initialize", Descriptor_initialize, 3);
-  rb_define_method(klass, "each", Descriptor_each, 0);
-  rb_define_method(klass, "lookup", Descriptor_lookup, 1);
-  rb_define_method(klass, "each_oneof", Descriptor_each_oneof, 0);
-  rb_define_method(klass, "lookup_oneof", Descriptor_lookup_oneof, 1);
-  rb_define_method(klass, "msgclass", Descriptor_msgclass, 0);
-  rb_define_method(klass, "name", Descriptor_name, 0);
-  rb_define_method(klass, "file_descriptor", Descriptor_file_descriptor, 0);
-  rb_include_module(klass, rb_mEnumerable);
-  rb_gc_register_address(&cDescriptor);
-  cDescriptor = klass;
-}
-
-/*
- * call-seq:
- *    Descriptor.new(c_only_cookie, ptr) => Descriptor
- *
- * Creates a descriptor wrapper object.  May only be called from C.
- */
-VALUE Descriptor_initialize(VALUE _self, VALUE cookie,
-                            VALUE descriptor_pool, VALUE ptr) {
-  DEFINE_SELF(Descriptor, self, _self);
-
-  if (cookie != c_only_cookie) {
-    rb_raise(rb_eRuntimeError,
-             "Descriptor objects may not be created from Ruby.");
-  }
-
-  self->descriptor_pool = descriptor_pool;
-  self->msgdef = (const upb_msgdef*)NUM2ULL(ptr);
-
-  return Qnil;
-}
-
-/*
- * call-seq:
- *    Descriptor.file_descriptor
- *
- * Returns the FileDescriptor object this message belongs to.
- */
-VALUE Descriptor_file_descriptor(VALUE _self) {
-  DEFINE_SELF(Descriptor, self, _self);
-  return get_filedef_obj(self->descriptor_pool, upb_msgdef_file(self->msgdef));
-}
-
-/*
- * call-seq:
- *     Descriptor.name => name
- *
- * Returns the name of this message type as a fully-qualified string (e.g.,
- * My.Package.MessageType).
- */
-VALUE Descriptor_name(VALUE _self) {
-  DEFINE_SELF(Descriptor, self, _self);
-  return rb_str_maybe_null(upb_msgdef_fullname(self->msgdef));
-}
-
-/*
- * call-seq:
- *     Descriptor.each(&block)
- *
- * Iterates over fields in this message type, yielding to the block on each one.
- */
-VALUE Descriptor_each(VALUE _self) {
-  DEFINE_SELF(Descriptor, self, _self);
-
-  upb_msg_field_iter it;
-  for (upb_msg_field_begin(&it, self->msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    VALUE obj = get_fielddef_obj(self->descriptor_pool, field);
-    rb_yield(obj);
-  }
-  return Qnil;
-}
-
-/*
- * call-seq:
- *     Descriptor.lookup(name) => FieldDescriptor
- *
- * Returns the field descriptor for the field with the given name, if present,
- * or nil if none.
- */
-VALUE Descriptor_lookup(VALUE _self, VALUE name) {
-  DEFINE_SELF(Descriptor, self, _self);
-  const char* s = get_str(name);
-  const upb_fielddef* field = upb_msgdef_ntofz(self->msgdef, s);
-  if (field == NULL) {
-    return Qnil;
-  }
-  return get_fielddef_obj(self->descriptor_pool, field);
-}
-
-/*
- * call-seq:
- *     Descriptor.each_oneof(&block) => nil
- *
- * Invokes the given block for each oneof in this message type, passing the
- * corresponding OneofDescriptor.
- */
-VALUE Descriptor_each_oneof(VALUE _self) {
-  DEFINE_SELF(Descriptor, self, _self);
-
-  upb_msg_oneof_iter it;
-  for (upb_msg_oneof_begin(&it, self->msgdef);
-       !upb_msg_oneof_done(&it);
-       upb_msg_oneof_next(&it)) {
-    const upb_oneofdef* oneof = upb_msg_iter_oneof(&it);
-    VALUE obj = get_oneofdef_obj(self->descriptor_pool, oneof);
-    rb_yield(obj);
-  }
-  return Qnil;
-}
-
-/*
- * call-seq:
- *     Descriptor.lookup_oneof(name) => OneofDescriptor
- *
- * Returns the oneof descriptor for the oneof with the given name, if present,
- * or nil if none.
- */
-VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name) {
-  DEFINE_SELF(Descriptor, self, _self);
-  const char* s = get_str(name);
-  const upb_oneofdef* oneof = upb_msgdef_ntooz(self->msgdef, s);
-  if (oneof == NULL) {
-    return Qnil;
-  }
-  return get_oneofdef_obj(self->descriptor_pool, oneof);
-}
-
-/*
- * call-seq:
- *     Descriptor.msgclass => message_klass
- *
- * Returns the Ruby class created for this message type.
- */
-VALUE Descriptor_msgclass(VALUE _self) {
-  DEFINE_SELF(Descriptor, self, _self);
-  if (self->klass == Qnil) {
-    self->klass = build_class_from_descriptor(_self);
-  }
-  return self->klass;
-}
-
-// -----------------------------------------------------------------------------
-// FileDescriptor.
-// -----------------------------------------------------------------------------
-
-DEFINE_CLASS(FileDescriptor, "Google::Protobuf::FileDescriptor");
-
-void FileDescriptor_mark(void* _self) {
-  FileDescriptor* self = _self;
-  rb_gc_mark(self->descriptor_pool);
-}
-
-void FileDescriptor_free(void* _self) {
-  xfree(_self);
-}
-
-VALUE FileDescriptor_alloc(VALUE klass) {
-  FileDescriptor* self = ALLOC(FileDescriptor);
-  VALUE ret = TypedData_Wrap_Struct(klass, &_FileDescriptor_type, self);
-  self->descriptor_pool = Qnil;
-  self->filedef = NULL;
-  return ret;
-}
-
-/*
- * call-seq:
- *     FileDescriptor.new => file
- *
- * Returns a new file descriptor. The syntax must be set before it's passed
- * to a builder.
- */
-VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie,
-                                VALUE descriptor_pool, VALUE ptr) {
-  DEFINE_SELF(FileDescriptor, self, _self);
-
-  if (cookie != c_only_cookie) {
-    rb_raise(rb_eRuntimeError,
-             "Descriptor objects may not be created from Ruby.");
-  }
-
-  self->descriptor_pool = descriptor_pool;
-  self->filedef = (const upb_filedef*)NUM2ULL(ptr);
-
-  return Qnil;
-}
-
-void FileDescriptor_register(VALUE module) {
-  VALUE klass = rb_define_class_under(
-      module, "FileDescriptor", rb_cObject);
-  rb_define_alloc_func(klass, FileDescriptor_alloc);
-  rb_define_method(klass, "initialize", FileDescriptor_initialize, 3);
-  rb_define_method(klass, "name", FileDescriptor_name, 0);
-  rb_define_method(klass, "syntax", FileDescriptor_syntax, 0);
-  rb_gc_register_address(&cFileDescriptor);
-  cFileDescriptor = klass;
-}
-
-/*
- * call-seq:
- *     FileDescriptor.name => name
- *
- * Returns the name of the file.
- */
-VALUE FileDescriptor_name(VALUE _self) {
-  DEFINE_SELF(FileDescriptor, self, _self);
-  const char* name = upb_filedef_name(self->filedef);
-  return name == NULL ? Qnil : rb_str_new2(name);
-}
-
-/*
- * call-seq:
- *     FileDescriptor.syntax => syntax
- *
- * Returns this file descriptors syntax.
- *
- * Valid syntax versions are:
- *     :proto2 or :proto3.
- */
-VALUE FileDescriptor_syntax(VALUE _self) {
-  DEFINE_SELF(FileDescriptor, self, _self);
-
-  switch (upb_filedef_syntax(self->filedef)) {
-    case UPB_SYNTAX_PROTO3: return ID2SYM(rb_intern("proto3"));
-    case UPB_SYNTAX_PROTO2: return ID2SYM(rb_intern("proto2"));
-    default: return Qnil;
-  }
-}
-
-// -----------------------------------------------------------------------------
-// FieldDescriptor.
-// -----------------------------------------------------------------------------
-
-DEFINE_CLASS(FieldDescriptor, "Google::Protobuf::FieldDescriptor");
-
-void FieldDescriptor_mark(void* _self) {
-  FieldDescriptor* self = _self;
-  rb_gc_mark(self->descriptor_pool);
-}
-
-void FieldDescriptor_free(void* _self) {
-  xfree(_self);
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.new => field
- *
- * Returns a new field descriptor. Its name, type, etc. must be set before it is
- * added to a message type.
- */
-VALUE FieldDescriptor_alloc(VALUE klass) {
-  FieldDescriptor* self = ALLOC(FieldDescriptor);
-  VALUE ret = TypedData_Wrap_Struct(klass, &_FieldDescriptor_type, self);
-  self->fielddef = NULL;
-  return ret;
-}
-
-void FieldDescriptor_register(VALUE module) {
-  VALUE klass = rb_define_class_under(
-      module, "FieldDescriptor", rb_cObject);
-  rb_define_alloc_func(klass, FieldDescriptor_alloc);
-  rb_define_method(klass, "initialize", FieldDescriptor_initialize, 3);
-  rb_define_method(klass, "name", FieldDescriptor_name, 0);
-  rb_define_method(klass, "type", FieldDescriptor_type, 0);
-  rb_define_method(klass, "default", FieldDescriptor_default, 0);
-  rb_define_method(klass, "label", FieldDescriptor_label, 0);
-  rb_define_method(klass, "number", FieldDescriptor_number, 0);
-  rb_define_method(klass, "submsg_name", FieldDescriptor_submsg_name, 0);
-  rb_define_method(klass, "subtype", FieldDescriptor_subtype, 0);
-  rb_define_method(klass, "has?", FieldDescriptor_has, 1);
-  rb_define_method(klass, "clear", FieldDescriptor_clear, 1);
-  rb_define_method(klass, "get", FieldDescriptor_get, 1);
-  rb_define_method(klass, "set", FieldDescriptor_set, 2);
-  rb_gc_register_address(&cFieldDescriptor);
-  cFieldDescriptor = klass;
-}
-
-/*
- * call-seq:
- *    EnumDescriptor.new(c_only_cookie, pool, ptr) => EnumDescriptor
- *
- * Creates a descriptor wrapper object.  May only be called from C.
- */
-VALUE FieldDescriptor_initialize(VALUE _self, VALUE cookie,
-                                 VALUE descriptor_pool, VALUE ptr) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-
-  if (cookie != c_only_cookie) {
-    rb_raise(rb_eRuntimeError,
-             "Descriptor objects may not be created from Ruby.");
-  }
-
-  self->descriptor_pool = descriptor_pool;
-  self->fielddef = (const upb_fielddef*)NUM2ULL(ptr);
-
-  return Qnil;
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.name => name
- *
- * Returns the name of this field.
- */
-VALUE FieldDescriptor_name(VALUE _self) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  return rb_str_maybe_null(upb_fielddef_name(self->fielddef));
-}
-
-upb_fieldtype_t ruby_to_fieldtype(VALUE type) {
-  if (TYPE(type) != T_SYMBOL) {
-    rb_raise(rb_eArgError, "Expected symbol for field type.");
-  }
-
-#define CONVERT(upb, ruby)                                           \
-  if (SYM2ID(type) == rb_intern( # ruby )) {                         \
-    return UPB_TYPE_ ## upb;                                         \
-  }
-
-  CONVERT(FLOAT, float);
-  CONVERT(DOUBLE, double);
-  CONVERT(BOOL, bool);
-  CONVERT(STRING, string);
-  CONVERT(BYTES, bytes);
-  CONVERT(MESSAGE, message);
-  CONVERT(ENUM, enum);
-  CONVERT(INT32, int32);
-  CONVERT(INT64, int64);
-  CONVERT(UINT32, uint32);
-  CONVERT(UINT64, uint64);
-
-#undef CONVERT
-
-  rb_raise(rb_eArgError, "Unknown field type.");
-  return 0;
-}
-
-VALUE fieldtype_to_ruby(upb_fieldtype_t type) {
-  switch (type) {
-#define CONVERT(upb, ruby)                                           \
-    case UPB_TYPE_ ## upb : return ID2SYM(rb_intern( # ruby ));
-    CONVERT(FLOAT, float);
-    CONVERT(DOUBLE, double);
-    CONVERT(BOOL, bool);
-    CONVERT(STRING, string);
-    CONVERT(BYTES, bytes);
-    CONVERT(MESSAGE, message);
-    CONVERT(ENUM, enum);
-    CONVERT(INT32, int32);
-    CONVERT(INT64, int64);
-    CONVERT(UINT32, uint32);
-    CONVERT(UINT64, uint64);
-#undef CONVERT
-  }
-  return Qnil;
-}
-
-upb_descriptortype_t ruby_to_descriptortype(VALUE type) {
-  if (TYPE(type) != T_SYMBOL) {
-    rb_raise(rb_eArgError, "Expected symbol for field type.");
-  }
-
-#define CONVERT(upb, ruby)                                           \
-  if (SYM2ID(type) == rb_intern( # ruby )) {                         \
-    return UPB_DESCRIPTOR_TYPE_ ## upb;                              \
-  }
-
-  CONVERT(FLOAT, float);
-  CONVERT(DOUBLE, double);
-  CONVERT(BOOL, bool);
-  CONVERT(STRING, string);
-  CONVERT(BYTES, bytes);
-  CONVERT(MESSAGE, message);
-  CONVERT(GROUP, group);
-  CONVERT(ENUM, enum);
-  CONVERT(INT32, int32);
-  CONVERT(INT64, int64);
-  CONVERT(UINT32, uint32);
-  CONVERT(UINT64, uint64);
-  CONVERT(SINT32, sint32);
-  CONVERT(SINT64, sint64);
-  CONVERT(FIXED32, fixed32);
-  CONVERT(FIXED64, fixed64);
-  CONVERT(SFIXED32, sfixed32);
-  CONVERT(SFIXED64, sfixed64);
-
-#undef CONVERT
-
-  rb_raise(rb_eArgError, "Unknown field type.");
-  return 0;
-}
-
-VALUE descriptortype_to_ruby(upb_descriptortype_t type) {
-  switch (type) {
-#define CONVERT(upb, ruby)                                           \
-    case UPB_DESCRIPTOR_TYPE_ ## upb : return ID2SYM(rb_intern( # ruby ));
-    CONVERT(FLOAT, float);
-    CONVERT(DOUBLE, double);
-    CONVERT(BOOL, bool);
-    CONVERT(STRING, string);
-    CONVERT(BYTES, bytes);
-    CONVERT(MESSAGE, message);
-    CONVERT(GROUP, group);
-    CONVERT(ENUM, enum);
-    CONVERT(INT32, int32);
-    CONVERT(INT64, int64);
-    CONVERT(UINT32, uint32);
-    CONVERT(UINT64, uint64);
-    CONVERT(SINT32, sint32);
-    CONVERT(SINT64, sint64);
-    CONVERT(FIXED32, fixed32);
-    CONVERT(FIXED64, fixed64);
-    CONVERT(SFIXED32, sfixed32);
-    CONVERT(SFIXED64, sfixed64);
-#undef CONVERT
-  }
-  return Qnil;
-}
-
-VALUE ruby_to_label(VALUE label) {
-  upb_label_t upb_label;
-  bool converted = false;
-
-#define CONVERT(upb, ruby)                                           \
-  if (SYM2ID(label) == rb_intern( # ruby )) {                        \
-    upb_label = UPB_LABEL_ ## upb;                                   \
-    converted = true;                                                \
-  }
-
-  CONVERT(OPTIONAL, optional);
-  CONVERT(REQUIRED, required);
-  CONVERT(REPEATED, repeated);
-
-#undef CONVERT
-
-  if (!converted) {
-    rb_raise(rb_eArgError, "Unknown field label.");
-  }
-
-  return upb_label;
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.type => type
- *
- * Returns this field's type, as a Ruby symbol, or nil if not yet set.
- *
- * Valid field types are:
- *     :int32, :int64, :uint32, :uint64, :float, :double, :bool, :string,
- *     :bytes, :message.
- */
-VALUE FieldDescriptor_type(VALUE _self) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  return descriptortype_to_ruby(upb_fielddef_descriptortype(self->fielddef));
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.default => default
- *
- * Returns this field's default, as a Ruby object, or nil if not yet set.
- */
-VALUE FieldDescriptor_default(VALUE _self) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  return layout_get_default(self->fielddef);
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.label => label
- *
- * Returns this field's label (i.e., plurality), as a Ruby symbol.
- *
- * Valid field labels are:
- *     :optional, :repeated
- */
-VALUE FieldDescriptor_label(VALUE _self) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  switch (upb_fielddef_label(self->fielddef)) {
-#define CONVERT(upb, ruby)                                           \
-    case UPB_LABEL_ ## upb : return ID2SYM(rb_intern( # ruby ));
-
-    CONVERT(OPTIONAL, optional);
-    CONVERT(REQUIRED, required);
-    CONVERT(REPEATED, repeated);
-
-#undef CONVERT
-  }
-
-  return Qnil;
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.number => number
- *
- * Returns the tag number for this field.
- */
-VALUE FieldDescriptor_number(VALUE _self) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  return INT2NUM(upb_fielddef_number(self->fielddef));
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.submsg_name => submsg_name
- *
- * Returns the name of the message or enum type corresponding to this field, if
- * it is a message or enum field (respectively), or nil otherwise. This type
- * name will be resolved within the context of the pool to which the containing
- * message type is added.
- */
-VALUE FieldDescriptor_submsg_name(VALUE _self) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  switch (upb_fielddef_type(self->fielddef)) {
-    case UPB_TYPE_ENUM:
-      return rb_str_new2(
-          upb_enumdef_fullname(upb_fielddef_enumsubdef(self->fielddef)));
-    case UPB_TYPE_MESSAGE:
-      return rb_str_new2(
-          upb_msgdef_fullname(upb_fielddef_msgsubdef(self->fielddef)));
-    default:
-      return Qnil;
-  }
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.subtype => message_or_enum_descriptor
- *
- * Returns the message or enum descriptor corresponding to this field's type if
- * it is a message or enum field, respectively, or nil otherwise. Cannot be
- * called *until* the containing message type is added to a pool (and thus
- * resolved).
- */
-VALUE FieldDescriptor_subtype(VALUE _self) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  switch (upb_fielddef_type(self->fielddef)) {
-    case UPB_TYPE_ENUM:
-      return get_enumdef_obj(self->descriptor_pool,
-                             upb_fielddef_enumsubdef(self->fielddef));
-    case UPB_TYPE_MESSAGE:
-      return get_msgdef_obj(self->descriptor_pool,
-                            upb_fielddef_msgsubdef(self->fielddef));
-    default:
-      return Qnil;
-  }
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.get(message) => value
- *
- * Returns the value set for this field on the given message. Raises an
- * exception if message is of the wrong type.
- */
-VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  MessageHeader* msg;
-  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
-  if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) {
-    rb_raise(cTypeError, "get method called on wrong message type");
-  }
-  return layout_get(msg->descriptor->layout, Message_data(msg), self->fielddef);
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.has?(message) => boolean
- *
- * Returns whether the value is set on the given message. Raises an
- * exception when calling for fields that do not have presence.
- */
-VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  MessageHeader* msg;
-  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
-  if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) {
-    rb_raise(cTypeError, "has method called on wrong message type");
-  } else if (!upb_fielddef_haspresence(self->fielddef)) {
-    rb_raise(rb_eArgError, "does not track presence");
-  }
-
-  return layout_has(msg->descriptor->layout, Message_data(msg), self->fielddef);
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.clear(message)
- *
- * Clears the field from the message if it's set.
- */
-VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  MessageHeader* msg;
-  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
-  if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) {
-    rb_raise(cTypeError, "has method called on wrong message type");
-  }
-
-  layout_clear(msg->descriptor->layout, Message_data(msg), self->fielddef);
-  return Qnil;
-}
-
-/*
- * call-seq:
- *     FieldDescriptor.set(message, value)
- *
- * Sets the value corresponding to this field to the given value on the given
- * message. Raises an exception if message is of the wrong type. Performs the
- * ordinary type-checks for field setting.
- */
-VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
-  DEFINE_SELF(FieldDescriptor, self, _self);
-  MessageHeader* msg;
-  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
-  if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) {
-    rb_raise(cTypeError, "set method called on wrong message type");
-  }
-  layout_set(msg->descriptor->layout, Message_data(msg), self->fielddef, value);
-  return Qnil;
-}
-
-// -----------------------------------------------------------------------------
-// OneofDescriptor.
-// -----------------------------------------------------------------------------
-
-DEFINE_CLASS(OneofDescriptor, "Google::Protobuf::OneofDescriptor");
-
-void OneofDescriptor_mark(void* _self) {
-  OneofDescriptor* self = _self;
-  rb_gc_mark(self->descriptor_pool);
-}
-
-void OneofDescriptor_free(void* _self) {
-  xfree(_self);
-}
-
-/*
- * call-seq:
- *     OneofDescriptor.new => oneof_descriptor
- *
- * Creates a new, empty, oneof descriptor. The oneof may only be modified prior
- * to being added to a message descriptor which is subsequently added to a pool.
- */
-VALUE OneofDescriptor_alloc(VALUE klass) {
-  OneofDescriptor* self = ALLOC(OneofDescriptor);
-  VALUE ret = TypedData_Wrap_Struct(klass, &_OneofDescriptor_type, self);
-  self->oneofdef = NULL;
-  self->descriptor_pool = Qnil;
-  return ret;
-}
-
-void OneofDescriptor_register(VALUE module) {
-  VALUE klass = rb_define_class_under(
-      module, "OneofDescriptor", rb_cObject);
-  rb_define_alloc_func(klass, OneofDescriptor_alloc);
-  rb_define_method(klass, "initialize", OneofDescriptor_initialize, 3);
-  rb_define_method(klass, "name", OneofDescriptor_name, 0);
-  rb_define_method(klass, "each", OneofDescriptor_each, 0);
-  rb_include_module(klass, rb_mEnumerable);
-  rb_gc_register_address(&cOneofDescriptor);
-  cOneofDescriptor = klass;
-}
-
-/*
- * call-seq:
- *    OneofDescriptor.new(c_only_cookie, pool, ptr) => OneofDescriptor
- *
- * Creates a descriptor wrapper object.  May only be called from C.
- */
-VALUE OneofDescriptor_initialize(VALUE _self, VALUE cookie,
-                                 VALUE descriptor_pool, VALUE ptr) {
-  DEFINE_SELF(OneofDescriptor, self, _self);
-
-  if (cookie != c_only_cookie) {
-    rb_raise(rb_eRuntimeError,
-             "Descriptor objects may not be created from Ruby.");
-  }
-
-  self->descriptor_pool = descriptor_pool;
-  self->oneofdef = (const upb_oneofdef*)NUM2ULL(ptr);
-
-  return Qnil;
-}
-
-/*
- * call-seq:
- *     OneofDescriptor.name => name
- *
- * Returns the name of this oneof.
- */
-VALUE OneofDescriptor_name(VALUE _self) {
-  DEFINE_SELF(OneofDescriptor, self, _self);
-  return rb_str_maybe_null(upb_oneofdef_name(self->oneofdef));
-}
-
-/*
- * call-seq:
- *     OneofDescriptor.each(&block) => nil
- *
- * Iterates through fields in this oneof, yielding to the block on each one.
- */
-VALUE OneofDescriptor_each(VALUE _self) {
-  DEFINE_SELF(OneofDescriptor, self, _self);
-  upb_oneof_iter it;
-  for (upb_oneof_begin(&it, self->oneofdef);
-       !upb_oneof_done(&it);
-       upb_oneof_next(&it)) {
-    const upb_fielddef* f = upb_oneof_iter_field(&it);
-    VALUE obj = get_fielddef_obj(self->descriptor_pool, f);
-    rb_yield(obj);
-  }
-  return Qnil;
-}
-
-// -----------------------------------------------------------------------------
-// EnumDescriptor.
-// -----------------------------------------------------------------------------
-
-DEFINE_CLASS(EnumDescriptor, "Google::Protobuf::EnumDescriptor");
-
-void EnumDescriptor_mark(void* _self) {
-  EnumDescriptor* self = _self;
-  rb_gc_mark(self->module);
-  rb_gc_mark(self->descriptor_pool);
-}
-
-void EnumDescriptor_free(void* _self) {
-  xfree(_self);
-}
-
-VALUE EnumDescriptor_alloc(VALUE klass) {
-  EnumDescriptor* self = ALLOC(EnumDescriptor);
-  VALUE ret = TypedData_Wrap_Struct(klass, &_EnumDescriptor_type, self);
-  self->enumdef = NULL;
-  self->module = Qnil;
-  self->descriptor_pool = Qnil;
-  return ret;
-}
-
-/*
- * call-seq:
- *    EnumDescriptor.new(c_only_cookie, ptr) => EnumDescriptor
- *
- * Creates a descriptor wrapper object.  May only be called from C.
- */
-VALUE EnumDescriptor_initialize(VALUE _self, VALUE cookie,
-                                VALUE descriptor_pool, VALUE ptr) {
-  DEFINE_SELF(EnumDescriptor, self, _self);
-
-  if (cookie != c_only_cookie) {
-    rb_raise(rb_eRuntimeError,
-             "Descriptor objects may not be created from Ruby.");
-  }
-
-  self->descriptor_pool = descriptor_pool;
-  self->enumdef = (const upb_enumdef*)NUM2ULL(ptr);
-
-  return Qnil;
-}
-
-void EnumDescriptor_register(VALUE module) {
-  VALUE klass = rb_define_class_under(
-      module, "EnumDescriptor", rb_cObject);
-  rb_define_alloc_func(klass, EnumDescriptor_alloc);
-  rb_define_method(klass, "initialize", EnumDescriptor_initialize, 3);
-  rb_define_method(klass, "name", EnumDescriptor_name, 0);
-  rb_define_method(klass, "lookup_name", EnumDescriptor_lookup_name, 1);
-  rb_define_method(klass, "lookup_value", EnumDescriptor_lookup_value, 1);
-  rb_define_method(klass, "each", EnumDescriptor_each, 0);
-  rb_define_method(klass, "enummodule", EnumDescriptor_enummodule, 0);
-  rb_define_method(klass, "file_descriptor", EnumDescriptor_file_descriptor, 0);
-  rb_include_module(klass, rb_mEnumerable);
-  rb_gc_register_address(&cEnumDescriptor);
-  cEnumDescriptor = klass;
-}
-
-/*
- * call-seq:
- *    EnumDescriptor.file_descriptor
- *
- * Returns the FileDescriptor object this enum belongs to.
- */
-VALUE EnumDescriptor_file_descriptor(VALUE _self) {
-  DEFINE_SELF(EnumDescriptor, self, _self);
-  return get_filedef_obj(self->descriptor_pool,
-                         upb_enumdef_file(self->enumdef));
-}
-
-/*
- * call-seq:
- *     EnumDescriptor.name => name
- *
- * Returns the name of this enum type.
- */
-VALUE EnumDescriptor_name(VALUE _self) {
-  DEFINE_SELF(EnumDescriptor, self, _self);
-  return rb_str_maybe_null(upb_enumdef_fullname(self->enumdef));
-}
-
-/*
- * call-seq:
- *     EnumDescriptor.lookup_name(name) => value
- *
- * Returns the numeric value corresponding to the given key name (as a Ruby
- * symbol), or nil if none.
- */
-VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) {
-  DEFINE_SELF(EnumDescriptor, self, _self);
-  const char* name_str= rb_id2name(SYM2ID(name));
-  int32_t val = 0;
-  if (upb_enumdef_ntoiz(self->enumdef, name_str, &val)) {
-    return INT2NUM(val);
-  } else {
-    return Qnil;
-  }
-}
-
-/*
- * call-seq:
- *     EnumDescriptor.lookup_value(name) => value
- *
- * Returns the key name (as a Ruby symbol) corresponding to the integer value,
- * or nil if none.
- */
-VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number) {
-  DEFINE_SELF(EnumDescriptor, self, _self);
-  int32_t val = NUM2INT(number);
-  const char* name = upb_enumdef_iton(self->enumdef, val);
-  if (name != NULL) {
-    return ID2SYM(rb_intern(name));
-  } else {
-    return Qnil;
-  }
-}
-
-/*
- * call-seq:
- *     EnumDescriptor.each(&block)
- *
- * Iterates over key => value mappings in this enum's definition, yielding to
- * the block with (key, value) arguments for each one.
- */
-VALUE EnumDescriptor_each(VALUE _self) {
-  DEFINE_SELF(EnumDescriptor, self, _self);
-
-  upb_enum_iter it;
-  for (upb_enum_begin(&it, self->enumdef);
-       !upb_enum_done(&it);
-       upb_enum_next(&it)) {
-    VALUE key = ID2SYM(rb_intern(upb_enum_iter_name(&it)));
-    VALUE number = INT2NUM(upb_enum_iter_number(&it));
-    rb_yield_values(2, key, number);
-  }
-
-  return Qnil;
-}
-
-/*
- * call-seq:
- *     EnumDescriptor.enummodule => module
- *
- * Returns the Ruby module corresponding to this enum type.
- */
-VALUE EnumDescriptor_enummodule(VALUE _self) {
-  DEFINE_SELF(EnumDescriptor, self, _self);
-  if (self->module == Qnil) {
-    self->module = build_module_from_enumdesc(_self);
-  }
-  return self->module;
+static void FileBuilderContext_register(VALUE module) {
+  VALUE klass = rb_define_class_under(module, "FileBuilderContext", rb_cObject);
+  rb_define_alloc_func(klass, FileBuilderContext_alloc);
+  rb_define_method(klass, "initialize", FileBuilderContext_initialize, 3);
+  rb_define_method(klass, "add_message", FileBuilderContext_add_message, 1);
+  rb_define_method(klass, "add_enum", FileBuilderContext_add_enum, 1);
+  rb_gc_register_address(&cFileBuilderContext);
+  cFileBuilderContext = klass;
 }
 
 // -----------------------------------------------------------------------------
 // MessageBuilderContext.
 // -----------------------------------------------------------------------------
 
-DEFINE_CLASS(MessageBuilderContext,
-    "Google::Protobuf::Internal::MessageBuilderContext");
+typedef struct {
+  google_protobuf_DescriptorProto* msg_proto;
+  VALUE file_builder;
+} MessageBuilderContext;
 
-void MessageBuilderContext_mark(void* _self) {
+static VALUE cMessageBuilderContext = Qnil;
+
+static void MessageBuilderContext_mark(void* _self) {
   MessageBuilderContext* self = _self;
   rb_gc_mark(self->file_builder);
 }
 
-void MessageBuilderContext_free(void* _self) {
-  MessageBuilderContext* self = _self;
-  xfree(self);
-}
+static const rb_data_type_t MessageBuilderContext_type = {
+  "Google::Protobuf::Internal::MessageBuilderContext",
+  {MessageBuilderContext_mark, RUBY_DEFAULT_FREE, NULL},
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
 
-VALUE MessageBuilderContext_alloc(VALUE klass) {
-  MessageBuilderContext* self = ALLOC(MessageBuilderContext);
-  VALUE ret = TypedData_Wrap_Struct(
-      klass, &_MessageBuilderContext_type, self);
-  self->file_builder = Qnil;
+static MessageBuilderContext* ruby_to_MessageBuilderContext(VALUE val) {
+  MessageBuilderContext* ret;
+  TypedData_Get_Struct(val, MessageBuilderContext, &MessageBuilderContext_type,
+                       ret);
   return ret;
 }
 
-void MessageBuilderContext_register(VALUE module) {
-  VALUE klass = rb_define_class_under(
-      module, "MessageBuilderContext", rb_cObject);
-  rb_define_alloc_func(klass, MessageBuilderContext_alloc);
-  rb_define_method(klass, "initialize",
-                   MessageBuilderContext_initialize, 2);
-  rb_define_method(klass, "optional", MessageBuilderContext_optional, -1);
-  rb_define_method(klass, "proto3_optional", MessageBuilderContext_proto3_optional, -1);
-  rb_define_method(klass, "required", MessageBuilderContext_required, -1);
-  rb_define_method(klass, "repeated", MessageBuilderContext_repeated, -1);
-  rb_define_method(klass, "map", MessageBuilderContext_map, -1);
-  rb_define_method(klass, "oneof", MessageBuilderContext_oneof, 1);
-  rb_gc_register_address(&cMessageBuilderContext);
-  cMessageBuilderContext = klass;
+static VALUE MessageBuilderContext_alloc(VALUE klass) {
+  MessageBuilderContext* self = ALLOC(MessageBuilderContext);
+  VALUE ret = TypedData_Wrap_Struct(klass, &MessageBuilderContext_type, self);
+  self->file_builder = Qnil;
+  return ret;
 }
 
 /*
@@ -1451,10 +1685,9 @@
  * builder context. This class is intended to serve as a DSL context to be used
  * with #instance_eval.
  */
-VALUE MessageBuilderContext_initialize(VALUE _self,
-                                       VALUE _file_builder,
-                                       VALUE name) {
-  DEFINE_SELF(MessageBuilderContext, self, _self);
+static VALUE MessageBuilderContext_initialize(VALUE _self, VALUE _file_builder,
+                                              VALUE name) {
+  MessageBuilderContext* self = ruby_to_MessageBuilderContext(_self);
   FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder);
   google_protobuf_FileDescriptorProto* file_proto = file_builder->file_proto;
 
@@ -1472,7 +1705,7 @@
                              VALUE type, VALUE number, VALUE type_class,
                              VALUE options, int oneof_index,
                              bool proto3_optional) {
-  DEFINE_SELF(MessageBuilderContext, self, msgbuilder_rb);
+  MessageBuilderContext* self = ruby_to_MessageBuilderContext(msgbuilder_rb);
   FileBuilderContext* file_context =
       ruby_to_FileBuilderContext(self->file_builder);
   google_protobuf_FieldDescriptorProto* field_proto;
@@ -1527,9 +1760,16 @@
   }
 }
 
+#if RUBY_API_VERSION_CODE >= 20700
+static VALUE make_mapentry(VALUE _message_builder, VALUE types, int argc,
+                           const VALUE* argv, VALUE blockarg) {
+  (void)blockarg;
+#else
 static VALUE make_mapentry(VALUE _message_builder, VALUE types, int argc,
                            VALUE* argv) {
-  DEFINE_SELF(MessageBuilderContext, message_builder, _message_builder);
+#endif
+  MessageBuilderContext* message_builder =
+      ruby_to_MessageBuilderContext(_message_builder);
   VALUE type_class = rb_ary_entry(types, 2);
   FileBuilderContext* file_context =
       ruby_to_FileBuilderContext(message_builder->file_builder);
@@ -1596,8 +1836,8 @@
  * FieldDescriptor#type=) and the type_class must be a string, if present (as
  * accepted by FieldDescriptor#submsg_name=).
  */
-VALUE MessageBuilderContext_proto3_optional(int argc, VALUE* argv,
-                                            VALUE _self) {
+static VALUE MessageBuilderContext_proto3_optional(int argc, VALUE* argv,
+                                                   VALUE _self) {
   VALUE name, type, number;
   VALUE type_class, options = Qnil;
 
@@ -1630,7 +1870,8 @@
  * completeness. Any attempt to add a message type with required fields to a
  * pool will currently result in an error.
  */
-VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self) {
+static VALUE MessageBuilderContext_required(int argc, VALUE* argv,
+                                            VALUE _self) {
   VALUE name, type, number;
   VALUE type_class, options = Qnil;
 
@@ -1658,7 +1899,8 @@
  * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a
  * string, if present (as accepted by FieldDescriptor#submsg_name=).
  */
-VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self) {
+static VALUE MessageBuilderContext_repeated(int argc, VALUE* argv,
+                                            VALUE _self) {
   VALUE name, type, number, type_class;
 
   if (argc < 3) {
@@ -1687,8 +1929,8 @@
  * type_class must be a string, if present (as accepted by
  * FieldDescriptor#submsg_name=).
  */
-VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) {
-  DEFINE_SELF(MessageBuilderContext, self, _self);
+static VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) {
+  MessageBuilderContext* self = ruby_to_MessageBuilderContext(_self);
   VALUE name, key_type, value_type, number, type_class;
   VALUE mapentry_desc_name;
   FileBuilderContext* file_builder;
@@ -1717,14 +1959,6 @@
 
   file_builder = ruby_to_FileBuilderContext(self->file_builder);
 
-  // TODO(haberman): remove this restriction, maps are supported in proto2.
-  if (upb_strview_eql(
-          google_protobuf_FileDescriptorProto_syntax(file_builder->file_proto),
-          upb_strview_makez("proto2"))) {
-    rb_raise(rb_eArgError,
-             "Cannot add a native map field using proto2 syntax.");
-  }
-
   // Create a new message descriptor for the map entry message, and create a
   // repeated submessage field here with that type.
   msg_name = google_protobuf_DescriptorProto_name(self->msg_proto);
@@ -1768,8 +2002,8 @@
  *
  * This is the recommended, idiomatic way to build oneof definitions.
  */
-VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name) {
-  DEFINE_SELF(MessageBuilderContext, self, _self);
+static VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name) {
+  MessageBuilderContext* self = ruby_to_MessageBuilderContext(_self);
   size_t oneof_count;
   FileBuilderContext* file_context =
       ruby_to_FileBuilderContext(self->file_builder);
@@ -1795,8 +2029,8 @@
   return Qnil;
 }
 
-void MessageBuilderContext_add_synthetic_oneofs(VALUE _self) {
-  DEFINE_SELF(MessageBuilderContext, self, _self);
+static void MessageBuilderContext_add_synthetic_oneofs(VALUE _self) {
+  MessageBuilderContext* self = ruby_to_MessageBuilderContext(_self);
   FileBuilderContext* file_context =
       ruby_to_FileBuilderContext(self->file_builder);
   size_t field_count, oneof_count;
@@ -1845,40 +2079,57 @@
   }
 }
 
+static void MessageBuilderContext_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "MessageBuilderContext", rb_cObject);
+  rb_define_alloc_func(klass, MessageBuilderContext_alloc);
+  rb_define_method(klass, "initialize",
+                   MessageBuilderContext_initialize, 2);
+  rb_define_method(klass, "optional", MessageBuilderContext_optional, -1);
+  rb_define_method(klass, "proto3_optional", MessageBuilderContext_proto3_optional, -1);
+  rb_define_method(klass, "required", MessageBuilderContext_required, -1);
+  rb_define_method(klass, "repeated", MessageBuilderContext_repeated, -1);
+  rb_define_method(klass, "map", MessageBuilderContext_map, -1);
+  rb_define_method(klass, "oneof", MessageBuilderContext_oneof, 1);
+  rb_gc_register_address(&cMessageBuilderContext);
+  cMessageBuilderContext = klass;
+}
+
 // -----------------------------------------------------------------------------
 // OneofBuilderContext.
 // -----------------------------------------------------------------------------
 
-DEFINE_CLASS(OneofBuilderContext,
-    "Google::Protobuf::Internal::OneofBuilderContext");
+typedef struct {
+  int oneof_index;
+  VALUE message_builder;
+} OneofBuilderContext;
+
+static VALUE cOneofBuilderContext = Qnil;
 
 void OneofBuilderContext_mark(void* _self) {
   OneofBuilderContext* self = _self;
   rb_gc_mark(self->message_builder);
 }
 
-void OneofBuilderContext_free(void* _self) {
-  xfree(_self);
-}
+static const rb_data_type_t OneofBuilderContext_type = {
+  "Google::Protobuf::Internal::OneofBuilderContext",
+  {OneofBuilderContext_mark, RUBY_DEFAULT_FREE, NULL},
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
 
-VALUE OneofBuilderContext_alloc(VALUE klass) {
-  OneofBuilderContext* self = ALLOC(OneofBuilderContext);
-  VALUE ret = TypedData_Wrap_Struct(
-      klass, &_OneofBuilderContext_type, self);
-  self->oneof_index = 0;
-  self->message_builder = Qnil;
+static OneofBuilderContext* ruby_to_OneofBuilderContext(VALUE val) {
+  OneofBuilderContext* ret;
+  TypedData_Get_Struct(val, OneofBuilderContext, &OneofBuilderContext_type,
+                       ret);
   return ret;
 }
 
-void OneofBuilderContext_register(VALUE module) {
-  VALUE klass = rb_define_class_under(
-      module, "OneofBuilderContext", rb_cObject);
-  rb_define_alloc_func(klass, OneofBuilderContext_alloc);
-  rb_define_method(klass, "initialize",
-                   OneofBuilderContext_initialize, 2);
-  rb_define_method(klass, "optional", OneofBuilderContext_optional, -1);
-  rb_gc_register_address(&cOneofBuilderContext);
-  cOneofBuilderContext = klass;
+static VALUE OneofBuilderContext_alloc(VALUE klass) {
+  OneofBuilderContext* self = ALLOC(OneofBuilderContext);
+  VALUE ret = TypedData_Wrap_Struct(klass, &OneofBuilderContext_type, self);
+  self->oneof_index = 0;
+  self->message_builder = Qnil;
+  return ret;
 }
 
 /*
@@ -1889,10 +2140,9 @@
  * builder context. This class is intended to serve as a DSL context to be used
  * with #instance_eval.
  */
-VALUE OneofBuilderContext_initialize(VALUE _self,
-                                     VALUE oneof_index,
-                                     VALUE message_builder) {
-  DEFINE_SELF(OneofBuilderContext, self, _self);
+static VALUE OneofBuilderContext_initialize(VALUE _self, VALUE oneof_index,
+                                            VALUE message_builder) {
+  OneofBuilderContext* self = ruby_to_OneofBuilderContext(_self);
   self->oneof_index = NUM2INT(oneof_index);
   self->message_builder = message_builder;
   return Qnil;
@@ -1908,8 +2158,8 @@
  * (as accepted by FieldDescriptor#type=) and the type_class must be a string,
  * if present (as accepted by FieldDescriptor#submsg_name=).
  */
-VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
-  DEFINE_SELF(OneofBuilderContext, self, _self);
+static VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
+  OneofBuilderContext* self = ruby_to_OneofBuilderContext(_self);
   VALUE name, type, number;
   VALUE type_class, options = Qnil;
 
@@ -1921,39 +2171,51 @@
   return Qnil;
 }
 
+static void OneofBuilderContext_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "OneofBuilderContext", rb_cObject);
+  rb_define_alloc_func(klass, OneofBuilderContext_alloc);
+  rb_define_method(klass, "initialize",
+                   OneofBuilderContext_initialize, 2);
+  rb_define_method(klass, "optional", OneofBuilderContext_optional, -1);
+  rb_gc_register_address(&cOneofBuilderContext);
+  cOneofBuilderContext = klass;
+}
+
 // -----------------------------------------------------------------------------
 // EnumBuilderContext.
 // -----------------------------------------------------------------------------
 
-DEFINE_CLASS(EnumBuilderContext,
-    "Google::Protobuf::Internal::EnumBuilderContext");
+typedef struct {
+  google_protobuf_EnumDescriptorProto* enum_proto;
+  VALUE file_builder;
+} EnumBuilderContext;
+
+static VALUE cEnumBuilderContext = Qnil;
 
 void EnumBuilderContext_mark(void* _self) {
   EnumBuilderContext* self = _self;
   rb_gc_mark(self->file_builder);
 }
 
-void EnumBuilderContext_free(void* _self) {
-  xfree(_self);
-}
+static const rb_data_type_t EnumBuilderContext_type = {
+  "Google::Protobuf::Internal::EnumBuilderContext",
+  {EnumBuilderContext_mark, RUBY_DEFAULT_FREE, NULL},
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
 
-VALUE EnumBuilderContext_alloc(VALUE klass) {
-  EnumBuilderContext* self = ALLOC(EnumBuilderContext);
-  VALUE ret = TypedData_Wrap_Struct(
-      klass, &_EnumBuilderContext_type, self);
-  self->enum_proto = NULL;
-  self->file_builder = Qnil;
+static EnumBuilderContext* ruby_to_EnumBuilderContext(VALUE val) {
+  EnumBuilderContext* ret;
+  TypedData_Get_Struct(val, EnumBuilderContext, &EnumBuilderContext_type, ret);
   return ret;
 }
 
-void EnumBuilderContext_register(VALUE module) {
-  VALUE klass = rb_define_class_under(
-      module, "EnumBuilderContext", rb_cObject);
-  rb_define_alloc_func(klass, EnumBuilderContext_alloc);
-  rb_define_method(klass, "initialize", EnumBuilderContext_initialize, 2);
-  rb_define_method(klass, "value", EnumBuilderContext_value, 2);
-  rb_gc_register_address(&cEnumBuilderContext);
-  cEnumBuilderContext = klass;
+static VALUE EnumBuilderContext_alloc(VALUE klass) {
+  EnumBuilderContext* self = ALLOC(EnumBuilderContext);
+  VALUE ret = TypedData_Wrap_Struct(klass, &EnumBuilderContext_type, self);
+  self->enum_proto = NULL;
+  self->file_builder = Qnil;
+  return ret;
 }
 
 /*
@@ -1963,9 +2225,9 @@
  * Create a new builder context around the given enum descriptor. This class is
  * intended to serve as a DSL context to be used with #instance_eval.
  */
-VALUE EnumBuilderContext_initialize(VALUE _self, VALUE _file_builder,
-                                    VALUE name) {
-  DEFINE_SELF(EnumBuilderContext, self, _self);
+static VALUE EnumBuilderContext_initialize(VALUE _self, VALUE _file_builder,
+                                           VALUE name) {
+  EnumBuilderContext* self = ruby_to_EnumBuilderContext(_self);
   FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder);
   google_protobuf_FileDescriptorProto* file_proto = file_builder->file_proto;
 
@@ -1986,8 +2248,8 @@
  * Adds the given name => number mapping to the enum type. Name must be a Ruby
  * symbol.
  */
-VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number) {
-  DEFINE_SELF(EnumBuilderContext, self, _self);
+static VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number) {
+  EnumBuilderContext* self = ruby_to_EnumBuilderContext(_self);
   FileBuilderContext* file_builder =
       ruby_to_FileBuilderContext(self->file_builder);
   google_protobuf_EnumValueDescriptorProto* enum_value;
@@ -2003,194 +2265,51 @@
   return Qnil;
 }
 
-
-// -----------------------------------------------------------------------------
-// FileBuilderContext.
-// -----------------------------------------------------------------------------
-
-DEFINE_CLASS(FileBuilderContext,
-             "Google::Protobuf::Internal::FileBuilderContext");
-
-void FileBuilderContext_mark(void* _self) {
-  FileBuilderContext* self = _self;
-  rb_gc_mark(self->descriptor_pool);
-}
-
-void FileBuilderContext_free(void* _self) {
-  FileBuilderContext* self = _self;
-  upb_arena_free(self->arena);
-  xfree(self);
-}
-
-upb_strview FileBuilderContext_strdup2(VALUE _self, const char *str) {
-  DEFINE_SELF(FileBuilderContext, self, _self);
-  upb_strview ret;
-  char *data;
-
-  ret.size = strlen(str);
-  data = upb_malloc(upb_arena_alloc(self->arena), ret.size + 1);
-  ret.data = data;
-  memcpy(data, str, ret.size);
-  /* Null-terminate required by rewrite_enum_defaults() above. */
-  data[ret.size] = '\0';
-  return ret;
-}
-
-upb_strview FileBuilderContext_strdup(VALUE _self, VALUE rb_str) {
-  return FileBuilderContext_strdup2(_self, get_str(rb_str));
-}
-
-upb_strview FileBuilderContext_strdup_sym(VALUE _self, VALUE rb_sym) {
-  Check_Type(rb_sym, T_SYMBOL);
-  return FileBuilderContext_strdup(_self, rb_id2str(SYM2ID(rb_sym)));
-}
-
-VALUE FileBuilderContext_alloc(VALUE klass) {
-  FileBuilderContext* self = ALLOC(FileBuilderContext);
-  VALUE ret = TypedData_Wrap_Struct(klass, &_FileBuilderContext_type, self);
-  self->arena = upb_arena_new();
-  self->file_proto = google_protobuf_FileDescriptorProto_new(self->arena);
-  self->descriptor_pool = Qnil;
-  return ret;
-}
-
-void FileBuilderContext_register(VALUE module) {
-  VALUE klass = rb_define_class_under(module, "FileBuilderContext", rb_cObject);
-  rb_define_alloc_func(klass, FileBuilderContext_alloc);
-  rb_define_method(klass, "initialize", FileBuilderContext_initialize, 3);
-  rb_define_method(klass, "add_message", FileBuilderContext_add_message, 1);
-  rb_define_method(klass, "add_enum", FileBuilderContext_add_enum, 1);
-  rb_gc_register_address(&cFileBuilderContext);
-  cFileBuilderContext = klass;
-}
-
-/*
- * call-seq:
- *     FileBuilderContext.new(descriptor_pool) => context
- *
- * Create a new file builder context for the given file descriptor and
- * builder context. This class is intended to serve as a DSL context to be used
- * with #instance_eval.
- */
-VALUE FileBuilderContext_initialize(VALUE _self, VALUE descriptor_pool,
-                                    VALUE name, VALUE options) {
-  DEFINE_SELF(FileBuilderContext, self, _self);
-  self->descriptor_pool = descriptor_pool;
-
-  google_protobuf_FileDescriptorProto_set_name(
-      self->file_proto, FileBuilderContext_strdup(_self, name));
-
-  // Default syntax for Ruby is proto3.
-  google_protobuf_FileDescriptorProto_set_syntax(
-      self->file_proto,
-      FileBuilderContext_strdup(_self, rb_str_new2("proto3")));
-
-  if (options != Qnil) {
-    VALUE syntax;
-
-    Check_Type(options, T_HASH);
-    syntax = rb_hash_lookup2(options, ID2SYM(rb_intern("syntax")), Qnil);
-
-    if (syntax != Qnil) {
-      VALUE syntax_str;
-
-      Check_Type(syntax, T_SYMBOL);
-      syntax_str = rb_id2str(SYM2ID(syntax));
-      google_protobuf_FileDescriptorProto_set_syntax(
-          self->file_proto, FileBuilderContext_strdup(_self, syntax_str));
-    }
-  }
-
-  return Qnil;
-}
-
-/*
- * call-seq:
- *     FileBuilderContext.add_message(name, &block)
- *
- * Creates a new, empty descriptor with the given name, and invokes the block in
- * the context of a MessageBuilderContext on that descriptor. The block can then
- * call, e.g., MessageBuilderContext#optional and MessageBuilderContext#repeated
- * methods to define the message fields.
- *
- * This is the recommended, idiomatic way to build message definitions.
- */
-VALUE FileBuilderContext_add_message(VALUE _self, VALUE name) {
-  VALUE args[2] = { _self, name };
-  VALUE ctx = rb_class_new_instance(2, args, cMessageBuilderContext);
-  VALUE block = rb_block_proc();
-  rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
-  MessageBuilderContext_add_synthetic_oneofs(ctx);
-  return Qnil;
-}
-
-/*
- * call-seq:
- *     FileBuilderContext.add_enum(name, &block)
- *
- * Creates a new, empty enum descriptor with the given name, and invokes the
- * block in the context of an EnumBuilderContext on that descriptor. The block
- * can then call EnumBuilderContext#add_value to define the enum values.
- *
- * This is the recommended, idiomatic way to build enum definitions.
- */
-VALUE FileBuilderContext_add_enum(VALUE _self, VALUE name) {
-  VALUE args[2] = { _self, name };
-  VALUE ctx = rb_class_new_instance(2, args, cEnumBuilderContext);
-  VALUE block = rb_block_proc();
-  rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
-  return Qnil;
-}
-
-void FileBuilderContext_build(VALUE _self) {
-  DEFINE_SELF(FileBuilderContext, self, _self);
-  DescriptorPool* pool = ruby_to_DescriptorPool(self->descriptor_pool);
-  upb_status status;
-
-  rewrite_enum_defaults(pool->symtab, self->file_proto);
-  rewrite_names(_self, self->file_proto);
-
-  upb_status_clear(&status);
-  if (!upb_symtab_addfile(pool->symtab, self->file_proto, &status)) {
-    rb_raise(cTypeError, "Unable to add defs to DescriptorPool: %s",
-             upb_status_errmsg(&status));
-  }
+static void EnumBuilderContext_register(VALUE module) {
+  VALUE klass = rb_define_class_under(
+      module, "EnumBuilderContext", rb_cObject);
+  rb_define_alloc_func(klass, EnumBuilderContext_alloc);
+  rb_define_method(klass, "initialize", EnumBuilderContext_initialize, 2);
+  rb_define_method(klass, "value", EnumBuilderContext_value, 2);
+  rb_gc_register_address(&cEnumBuilderContext);
+  cEnumBuilderContext = klass;
 }
 
 // -----------------------------------------------------------------------------
 // Builder.
 // -----------------------------------------------------------------------------
 
-DEFINE_CLASS(Builder, "Google::Protobuf::Internal::Builder");
+typedef struct {
+  VALUE descriptor_pool;
+  VALUE default_file_builder;
+} Builder;
 
-void Builder_mark(void* _self) {
+static VALUE cBuilder = Qnil;
+
+static void Builder_mark(void* _self) {
   Builder* self = _self;
   rb_gc_mark(self->descriptor_pool);
   rb_gc_mark(self->default_file_builder);
 }
 
-void Builder_free(void* _self) {
-  xfree(_self);
-}
+static const rb_data_type_t Builder_type = {
+  "Google::Protobuf::Internal::Builder",
+  {Builder_mark, RUBY_DEFAULT_FREE, NULL},
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
 
-VALUE Builder_alloc(VALUE klass) {
-  Builder* self = ALLOC(Builder);
-  VALUE ret = TypedData_Wrap_Struct(
-      klass, &_Builder_type, self);
-  self->descriptor_pool = Qnil;
-  self->default_file_builder = Qnil;
+static Builder* ruby_to_Builder(VALUE val) {
+  Builder* ret;
+  TypedData_Get_Struct(val, Builder, &Builder_type, ret);
   return ret;
 }
 
-void Builder_register(VALUE module) {
-  VALUE klass = rb_define_class_under(module, "Builder", rb_cObject);
-  rb_define_alloc_func(klass, Builder_alloc); 
-  rb_define_method(klass, "initialize", Builder_initialize, 1);
-  rb_define_method(klass, "add_file", Builder_add_file, -1);
-  rb_define_method(klass, "add_message", Builder_add_message, 1);
-  rb_define_method(klass, "add_enum", Builder_add_enum, 1);
-  rb_gc_register_address(&cBuilder);
-  cBuilder = klass;
+static VALUE Builder_alloc(VALUE klass) {
+  Builder* self = ALLOC(Builder);
+  VALUE ret = TypedData_Wrap_Struct(klass, &Builder_type, self);
+  self->descriptor_pool = Qnil;
+  self->default_file_builder = Qnil;
+  return ret;
 }
 
 /*
@@ -2201,8 +2320,8 @@
  * descriptors and atomically register them into a pool in a way that allows for
  * (co)recursive type references.
  */
-VALUE Builder_initialize(VALUE _self, VALUE pool) {
-  DEFINE_SELF(Builder, self, _self);
+static VALUE Builder_initialize(VALUE _self, VALUE pool) {
+  Builder* self = ruby_to_Builder(_self);
   self->descriptor_pool = pool;
   self->default_file_builder = Qnil;  // Created lazily if needed.
   return Qnil;
@@ -2219,8 +2338,8 @@
  *
  * This is the recommended, idiomatic way to build file descriptors.
  */
-VALUE Builder_add_file(int argc, VALUE* argv, VALUE _self) {
-  DEFINE_SELF(Builder, self, _self);
+static VALUE Builder_add_file(int argc, VALUE* argv, VALUE _self) {
+  Builder* self = ruby_to_Builder(_self);
   VALUE name, options;
   VALUE ctx;
   VALUE block;
@@ -2240,7 +2359,7 @@
 }
 
 static VALUE Builder_get_default_file(VALUE _self) {
-  DEFINE_SELF(Builder, self, _self);
+  Builder* self = ruby_to_Builder(_self);
 
   /* Lazily create only if legacy builder-level methods are called. */
   if (self->default_file_builder == Qnil) {
@@ -2264,7 +2383,7 @@
  * files generated by protoc which don't add messages within "add_file" block.
  * Descriptors created this way get assigned to a default empty FileDescriptor.
  */
-VALUE Builder_add_message(VALUE _self, VALUE name) {
+static VALUE Builder_add_message(VALUE _self, VALUE name) {
   VALUE file_builder = Builder_get_default_file(_self);
   rb_funcall_with_block(file_builder, rb_intern("add_message"), 1, &name,
                         rb_block_proc());
@@ -2283,7 +2402,7 @@
  * Enum descriptors created this way get assigned to a default empty
  * FileDescriptor.
  */
-VALUE Builder_add_enum(VALUE _self, VALUE name) {
+static VALUE Builder_add_enum(VALUE _self, VALUE name) {
   VALUE file_builder = Builder_get_default_file(_self);
   rb_funcall_with_block(file_builder, rb_intern("add_enum"), 1, &name,
                         rb_block_proc());
@@ -2292,8 +2411,8 @@
 
 /* This method is hidden from Ruby, and only called directly from
  * DescriptorPool_build(). */
-VALUE Builder_build(VALUE _self) {
-  DEFINE_SELF(Builder, self, _self);
+static VALUE Builder_build(VALUE _self) {
+  Builder* self = ruby_to_Builder(_self);
 
   if (self->default_file_builder != Qnil) {
     FileBuilderContext_build(self->default_file_builder);
@@ -2303,8 +2422,19 @@
   return Qnil;
 }
 
+static void Builder_register(VALUE module) {
+  VALUE klass = rb_define_class_under(module, "Builder", rb_cObject);
+  rb_define_alloc_func(klass, Builder_alloc); 
+  rb_define_method(klass, "initialize", Builder_initialize, 1);
+  rb_define_method(klass, "add_file", Builder_add_file, -1);
+  rb_define_method(klass, "add_message", Builder_add_message, 1);
+  rb_define_method(klass, "add_enum", Builder_add_enum, 1);
+  rb_gc_register_address(&cBuilder);
+  cBuilder = klass;
+}
+
 static VALUE get_def_obj(VALUE _descriptor_pool, const void* ptr, VALUE klass) {
-  DEFINE_SELF(DescriptorPool, descriptor_pool, _descriptor_pool);
+  DescriptorPool* descriptor_pool = ruby_to_DescriptorPool(_descriptor_pool);
   VALUE key = ULL2NUM((intptr_t)ptr);
   VALUE def;
 
@@ -2319,48 +2449,111 @@
     VALUE args[3] = { c_only_cookie, _descriptor_pool, key };
     def = rb_class_new_instance(3, args, klass);
     rb_hash_aset(descriptor_pool->def_to_descriptor, key, def);
-
-    // For message defs, we now eagerly get/create descriptors for all
-    // submessages.  We will need these anyway to parse or serialize this
-    // message type.  But more importantly, we must do this now so that
-    // add_handlers_for_message() (which calls get_msgdef_obj()) does *not*
-    // need to create a Ruby object or insert into a Ruby Hash.  We need to
-    // avoid triggering GC, which can switch Ruby threads and re-enter our
-    // C extension from a different thread.  This wreaks havoc on our state
-    // if we were in the middle of building handlers.
-    if (klass == cDescriptor) {
-      const upb_msgdef *m = ptr;
-      upb_msg_field_iter it;
-      for (upb_msg_field_begin(&it, m);
-           !upb_msg_field_done(&it);
-           upb_msg_field_next(&it)) {
-        const upb_fielddef* f = upb_msg_iter_field(&it);
-        if (upb_fielddef_issubmsg(f)) {
-          get_msgdef_obj(_descriptor_pool, upb_fielddef_msgsubdef(f));
-        }
-      }
-    }
   }
 
   return def;
 }
 
-VALUE get_msgdef_obj(VALUE descriptor_pool, const upb_msgdef* def) {
+static VALUE get_msgdef_obj(VALUE descriptor_pool, const upb_msgdef* def) {
   return get_def_obj(descriptor_pool, def, cDescriptor);
 }
 
-VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_enumdef* def) {
+static VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_enumdef* def) {
   return get_def_obj(descriptor_pool, def, cEnumDescriptor);
 }
 
-VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_fielddef* def) {
+static VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_fielddef* def) {
   return get_def_obj(descriptor_pool, def, cFieldDescriptor);
 }
 
-VALUE get_filedef_obj(VALUE descriptor_pool, const upb_filedef* def) {
+static VALUE get_filedef_obj(VALUE descriptor_pool, const upb_filedef* def) {
   return get_def_obj(descriptor_pool, def, cFileDescriptor);
 }
 
-VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_oneofdef* def) {
+static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_oneofdef* def) {
   return get_def_obj(descriptor_pool, def, cOneofDescriptor);
 }
+
+// -----------------------------------------------------------------------------
+// Shared functions
+// -----------------------------------------------------------------------------
+
+// Functions exposed to other modules in defs.h.
+
+VALUE Descriptor_DefToClass(const upb_msgdef *m) {
+  const upb_symtab *symtab = upb_filedef_symtab(upb_msgdef_file(m));
+  VALUE pool = ObjectCache_Get(symtab);
+  PBRUBY_ASSERT(pool != Qnil);
+  VALUE desc_rb = get_msgdef_obj(pool, m);
+  const Descriptor* desc = ruby_to_Descriptor(desc_rb);
+  return desc->klass;
+}
+
+const upb_msgdef *Descriptor_GetMsgDef(VALUE desc_rb) {
+  const Descriptor* desc = ruby_to_Descriptor(desc_rb);
+  return desc->msgdef;
+}
+
+VALUE TypeInfo_InitArg(int argc, VALUE *argv, int skip_arg) {
+  if (argc > skip_arg) {
+    if (argc > 1 + skip_arg) {
+      rb_raise(rb_eArgError, "Expected a maximum of %d arguments.", skip_arg + 1);
+    }
+    return argv[skip_arg];
+  } else {
+    return Qnil;
+  }
+}
+
+TypeInfo TypeInfo_FromClass(int argc, VALUE* argv, int skip_arg,
+                            VALUE* type_class, VALUE* init_arg) {
+  TypeInfo ret = {ruby_to_fieldtype(argv[skip_arg])};
+
+  if (ret.type == UPB_TYPE_MESSAGE || ret.type == UPB_TYPE_ENUM) {
+    *init_arg = TypeInfo_InitArg(argc, argv, skip_arg + 2);
+
+    if (argc < 2 + skip_arg) {
+      rb_raise(rb_eArgError, "Expected at least %d arguments for message/enum.",
+               2 + skip_arg);
+    }
+
+    VALUE klass = argv[1 + skip_arg];
+    VALUE desc = MessageOrEnum_GetDescriptor(klass);
+    *type_class = klass;
+
+    if (desc == Qnil) {
+      rb_raise(rb_eArgError,
+               "Type class has no descriptor. Please pass a "
+               "class or enum as returned by the DescriptorPool.");
+    }
+
+    if (ret.type == UPB_TYPE_MESSAGE) {
+      ret.def.msgdef = ruby_to_Descriptor(desc)->msgdef;
+      Message_CheckClass(klass);
+    } else {
+      PBRUBY_ASSERT(ret.type == UPB_TYPE_ENUM);
+      ret.def.enumdef = ruby_to_EnumDescriptor(desc)->enumdef;
+    }
+  } else {
+    *init_arg = TypeInfo_InitArg(argc, argv, skip_arg + 1);
+  }
+
+  return ret;
+}
+
+void Defs_register(VALUE module) {
+  DescriptorPool_register(module);
+  Descriptor_register(module);
+  FileDescriptor_register(module);
+  FieldDescriptor_register(module);
+  OneofDescriptor_register(module);
+  EnumDescriptor_register(module);
+  FileBuilderContext_register(module);
+  MessageBuilderContext_register(module);
+  OneofBuilderContext_register(module);
+  EnumBuilderContext_register(module);
+  Builder_register(module);
+
+  rb_gc_register_address(&c_only_cookie);
+  c_only_cookie = rb_class_new_instance(0, NULL, rb_cObject);
+}
diff --git a/ruby/ext/google/protobuf_c/defs.h b/ruby/ext/google/protobuf_c/defs.h
new file mode 100644
index 0000000..97a94bb
--- /dev/null
+++ b/ruby/ext/google/protobuf_c/defs.h
@@ -0,0 +1,107 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef RUBY_PROTOBUF_DEFS_H_
+#define RUBY_PROTOBUF_DEFS_H_
+
+#include <ruby/ruby.h>
+
+#include "protobuf.h"
+#include "ruby-upb.h"
+
+// -----------------------------------------------------------------------------
+// TypeInfo
+// -----------------------------------------------------------------------------
+
+// This bundles a upb_fieldtype_t and msgdef/enumdef when appropriate. This is
+// convenient for functions that need type information but cannot necessarily
+// assume a upb_fielddef will be available.
+//
+// For example, Google::Protobuf::Map and Google::Protobuf::RepeatedField can
+// be constructed with type information alone:
+//
+//   # RepeatedField will internally store the type information in a TypeInfo.
+//   Google::Protobuf::RepeatedField.new(:message, FooMessage)
+
+typedef struct {
+  upb_fieldtype_t type;
+  union {
+    const upb_msgdef* msgdef;      // When type == UPB_TYPE_MESSAGE
+    const upb_enumdef* enumdef;    // When type == UPB_TYPE_ENUM
+  } def;
+} TypeInfo;
+
+static inline TypeInfo TypeInfo_get(const upb_fielddef *f) {
+  TypeInfo ret = {upb_fielddef_type(f), {NULL}};
+  switch (ret.type) {
+    case UPB_TYPE_MESSAGE:
+      ret.def.msgdef = upb_fielddef_msgsubdef(f);
+      break;
+    case UPB_TYPE_ENUM:
+      ret.def.enumdef = upb_fielddef_enumsubdef(f);
+      break;
+    default:
+      break;
+  }
+  return ret;
+}
+
+TypeInfo TypeInfo_FromClass(int argc, VALUE* argv, int skip_arg,
+                            VALUE* type_class, VALUE* init_arg);
+
+static inline TypeInfo TypeInfo_from_type(upb_fieldtype_t type) {
+  TypeInfo ret = {type};
+  assert(type != UPB_TYPE_MESSAGE && type != UPB_TYPE_ENUM);
+  return ret;
+}
+
+// -----------------------------------------------------------------------------
+// Other utilities
+// -----------------------------------------------------------------------------
+
+VALUE Descriptor_DefToClass(const upb_msgdef *m);
+
+// Returns the underlying msgdef, enumdef, or symtab (respectively) for the
+// given Descriptor, EnumDescriptor, or DescriptorPool Ruby object.
+const upb_enumdef *EnumDescriptor_GetEnumDef(VALUE enum_desc_rb);
+const upb_symtab *DescriptorPool_GetSymtab(VALUE desc_pool_rb);
+const upb_msgdef *Descriptor_GetMsgDef(VALUE desc_rb);
+
+// Returns a upb field type for the given Ruby symbol
+// (eg. :float => UPB_TYPE_FLOAT).
+upb_fieldtype_t ruby_to_fieldtype(VALUE type);
+
+// The singleton generated pool (a DescriptorPool object).
+extern VALUE generated_pool;
+
+// Call at startup to register all types in this module.
+void Defs_register(VALUE module);
+
+#endif  // RUBY_PROTOBUF_DEFS_H_
diff --git a/ruby/ext/google/protobuf_c/encode_decode.c b/ruby/ext/google/protobuf_c/encode_decode.c
deleted file mode 100644
index a58a5d2..0000000
--- a/ruby/ext/google/protobuf_c/encode_decode.c
+++ /dev/null
@@ -1,1795 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2014 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "protobuf.h"
-
-VALUE initialize_rb_class_with_no_args(VALUE klass) {
-  return rb_funcall(klass, rb_intern("new"), 0);
-}
-
-// This function is equivalent to rb_str_cat(), but unlike the real
-// rb_str_cat(), it doesn't leak memory in some versions of Ruby.
-// For more information, see:
-//   https://bugs.ruby-lang.org/issues/11328
-VALUE noleak_rb_str_cat(VALUE rb_str, const char *str, long len) {
-  char *p;
-  size_t oldlen = RSTRING_LEN(rb_str);
-  rb_str_modify_expand(rb_str, len);
-  p = RSTRING_PTR(rb_str);
-  memcpy(p + oldlen, str, len);
-  rb_str_set_len(rb_str, oldlen + len);
-  return rb_str;
-}
-
-bool is_wrapper(const upb_msgdef* m) {
-  switch (upb_msgdef_wellknowntype(m)) {
-    case UPB_WELLKNOWN_DOUBLEVALUE:
-    case UPB_WELLKNOWN_FLOATVALUE:
-    case UPB_WELLKNOWN_INT64VALUE:
-    case UPB_WELLKNOWN_UINT64VALUE:
-    case UPB_WELLKNOWN_INT32VALUE:
-    case UPB_WELLKNOWN_UINT32VALUE:
-    case UPB_WELLKNOWN_STRINGVALUE:
-    case UPB_WELLKNOWN_BYTESVALUE:
-    case UPB_WELLKNOWN_BOOLVALUE:
-      return true;
-    default:
-      return false;
-  }
-}
-
-// The code below also comes from upb's prototype Ruby binding, developed by
-// haberman@.
-
-/* stringsink *****************************************************************/
-
-static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) {
-  stringsink *sink = _sink;
-  sink->len = 0;
-  return sink;
-}
-
-static size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
-                                size_t len, const upb_bufhandle *handle) {
-  stringsink *sink = _sink;
-  size_t new_size = sink->size;
-
-  UPB_UNUSED(hd);
-  UPB_UNUSED(handle);
-
-  while (sink->len + len > new_size) {
-    new_size *= 2;
-  }
-
-  if (new_size != sink->size) {
-    sink->ptr = realloc(sink->ptr, new_size);
-    sink->size = new_size;
-  }
-
-  memcpy(sink->ptr + sink->len, ptr, len);
-  sink->len += len;
-
-  return len;
-}
-
-void stringsink_init(stringsink *sink) {
-  upb_byteshandler_init(&sink->handler);
-  upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL);
-  upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL);
-
-  upb_bytessink_reset(&sink->sink, &sink->handler, sink);
-
-  sink->size = 32;
-  sink->ptr = malloc(sink->size);
-  sink->len = 0;
-}
-
-void stringsink_uninit(stringsink *sink) {
-  free(sink->ptr);
-}
-
-// -----------------------------------------------------------------------------
-// Parsing.
-// -----------------------------------------------------------------------------
-
-#define DEREF(msg, ofs, type) *(type*)(((uint8_t *)msg) + ofs)
-
-typedef struct {
-  size_t ofs;
-  int32_t hasbit;
-} field_handlerdata_t;
-
-// Creates a handlerdata that contains the offset and the hasbit for the field
-static const void* newhandlerdata(upb_handlers* h, uint32_t ofs, int32_t hasbit) {
-  field_handlerdata_t *hd = ALLOC(field_handlerdata_t);
-  hd->ofs = ofs;
-  hd->hasbit = hasbit;
-  upb_handlers_addcleanup(h, hd, xfree);
-  return hd;
-}
-
-typedef struct {
-  size_t ofs;
-  int32_t hasbit;
-  upb_fieldtype_t wrapped_type;  // Only for wrappers.
-  VALUE subklass;
-} submsg_handlerdata_t;
-
-// Creates a handlerdata that contains offset and submessage type information.
-static const void *newsubmsghandlerdata(upb_handlers* h,
-                                        const upb_fielddef *f,
-                                        uint32_t ofs,
-                                        int32_t hasbit,
-                                        VALUE subklass) {
-  submsg_handlerdata_t *hd = ALLOC(submsg_handlerdata_t);
-  const upb_msgdef *subm = upb_fielddef_msgsubdef(f);
-  hd->ofs = ofs;
-  hd->hasbit = hasbit;
-  hd->subklass = subklass;
-  upb_handlers_addcleanup(h, hd, xfree);
-  if (is_wrapper(subm)) {
-    const upb_fielddef *value_f = upb_msgdef_itof(subm, 1);
-    hd->wrapped_type = upb_fielddef_type(value_f);
-  }
-  return hd;
-}
-
-typedef struct {
-  size_t ofs;              // union data slot
-  size_t case_ofs;         // oneof_case field
-  uint32_t oneof_case_num; // oneof-case number to place in oneof_case field
-  VALUE subklass;
-} oneof_handlerdata_t;
-
-static const void *newoneofhandlerdata(upb_handlers *h,
-                                       uint32_t ofs,
-                                       uint32_t case_ofs,
-                                       const upb_fielddef *f,
-                                       const Descriptor* desc) {
-  oneof_handlerdata_t *hd = ALLOC(oneof_handlerdata_t);
-  hd->ofs = ofs;
-  hd->case_ofs = case_ofs;
-  // We reuse the field tag number as a oneof union discriminant tag. Note that
-  // we don't expose these numbers to the user, so the only requirement is that
-  // we have some unique ID for each union case/possibility. The field tag
-  // numbers are already present and are easy to use so there's no reason to
-  // create a separate ID space. In addition, using the field tag number here
-  // lets us easily look up the field in the oneof accessor.
-  hd->oneof_case_num = upb_fielddef_number(f);
-  if (is_value_field(f)) {
-    hd->oneof_case_num |= ONEOF_CASE_MASK;
-  }
-  hd->subklass = field_type_class(desc->layout, f);
-  upb_handlers_addcleanup(h, hd, xfree);
-  return hd;
-}
-
-// A handler that starts a repeated field.  Gets the Repeated*Field instance for
-// this field (such an instance always exists even in an empty message).
-static void *startseq_handler(void* closure, const void* hd) {
-  MessageHeader* msg = closure;
-  const size_t *ofs = hd;
-  return (void*)DEREF(msg, *ofs, VALUE);
-}
-
-// Handlers that append primitive values to a repeated field.
-#define DEFINE_APPEND_HANDLER(type, ctype)                 \
-  static bool append##type##_handler(void *closure, const void *hd, \
-                                     ctype val) {                   \
-    VALUE ary = (VALUE)closure;                                     \
-    RepeatedField_push_native(ary, &val);                           \
-    return true;                                                    \
-  }
-
-DEFINE_APPEND_HANDLER(bool,   bool)
-DEFINE_APPEND_HANDLER(int32,  int32_t)
-DEFINE_APPEND_HANDLER(uint32, uint32_t)
-DEFINE_APPEND_HANDLER(float,  float)
-DEFINE_APPEND_HANDLER(int64,  int64_t)
-DEFINE_APPEND_HANDLER(uint64, uint64_t)
-DEFINE_APPEND_HANDLER(double, double)
-
-// Appends a string to a repeated field.
-static void* appendstr_handler(void *closure,
-                               const void *hd,
-                               size_t size_hint) {
-  VALUE ary = (VALUE)closure;
-  VALUE str = rb_str_new2("");
-  rb_enc_associate(str, kRubyStringUtf8Encoding);
-  RepeatedField_push_native(ary, &str);
-  return (void*)str;
-}
-
-static void set_hasbit(void *closure, int32_t hasbit) {
-  if (hasbit > 0) {
-    uint8_t* storage = closure;
-    storage[hasbit/8] |= 1 << (hasbit % 8);
-  }
-}
-
-// Appends a 'bytes' string to a repeated field.
-static void* appendbytes_handler(void *closure,
-                                 const void *hd,
-                                 size_t size_hint) {
-  VALUE ary = (VALUE)closure;
-  VALUE str = rb_str_new2("");
-  rb_enc_associate(str, kRubyString8bitEncoding);
-  RepeatedField_push_native(ary, &str);
-  return (void*)str;
-}
-
-// Sets a non-repeated string field in a message.
-static void* str_handler(void *closure,
-                         const void *hd,
-                         size_t size_hint) {
-  MessageHeader* msg = closure;
-  const field_handlerdata_t *fieldhandler = hd;
-
-  VALUE str = rb_str_new2("");
-  rb_enc_associate(str, kRubyStringUtf8Encoding);
-  DEREF(msg, fieldhandler->ofs, VALUE) = str;
-  set_hasbit(closure, fieldhandler->hasbit);
-  return (void*)str;
-}
-
-// Sets a non-repeated 'bytes' field in a message.
-static void* bytes_handler(void *closure,
-                           const void *hd,
-                           size_t size_hint) {
-  MessageHeader* msg = closure;
-  const field_handlerdata_t *fieldhandler = hd;
-
-  VALUE str = rb_str_new2("");
-  rb_enc_associate(str, kRubyString8bitEncoding);
-  DEREF(msg, fieldhandler->ofs, VALUE) = str;
-  set_hasbit(closure, fieldhandler->hasbit);
-  return (void*)str;
-}
-
-static size_t stringdata_handler(void* closure, const void* hd,
-                                 const char* str, size_t len,
-                                 const upb_bufhandle* handle) {
-  VALUE rb_str = (VALUE)closure;
-  noleak_rb_str_cat(rb_str, str, len);
-  return len;
-}
-
-static bool stringdata_end_handler(void* closure, const void* hd) {
-  VALUE rb_str = (VALUE)closure;
-  rb_obj_freeze(rb_str);
-  return true;
-}
-
-static bool appendstring_end_handler(void* closure, const void* hd) {
-  VALUE rb_str = (VALUE)closure;
-  rb_obj_freeze(rb_str);
-  return true;
-}
-
-// Appends a submessage to a repeated field (a regular Ruby array for now).
-static void *appendsubmsg_handler(void *closure, const void *hd) {
-  VALUE ary = (VALUE)closure;
-  const submsg_handlerdata_t *submsgdata = hd;
-  MessageHeader* submsg;
-
-  VALUE submsg_rb = initialize_rb_class_with_no_args(submsgdata->subklass);
-  RepeatedField_push(ary, submsg_rb);
-
-  TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
-  return submsg;
-}
-
-// Appends a wrapper to a repeated field (a regular Ruby array for now).
-static void *appendwrapper_handler(void *closure, const void *hd) {
-  VALUE ary = (VALUE)closure;
-  int size = RepeatedField_size(ary);
-  (void)hd;
-
-  RepeatedField_push(ary, Qnil);
-
-  return RepeatedField_index_native(ary, size);
-}
-
-// Sets a non-repeated submessage field in a message.
-static void *submsg_handler(void *closure, const void *hd) {
-  MessageHeader* msg = closure;
-  const submsg_handlerdata_t* submsgdata = hd;
-  VALUE submsg_rb;
-  MessageHeader* submsg;
-
-  if (DEREF(msg, submsgdata->ofs, VALUE) == Qnil) {
-    DEREF(msg, submsgdata->ofs, VALUE) =
-        initialize_rb_class_with_no_args(submsgdata->subklass);
-  }
-
-  set_hasbit(closure, submsgdata->hasbit);
-
-  submsg_rb = DEREF(msg, submsgdata->ofs, VALUE);
-  TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
-
-  return submsg;
-}
-
-static void* startwrapper(void* closure, const void* hd) {
-  const submsg_handlerdata_t* submsgdata = hd;
-  char* msg = closure;
-  VALUE* field = (VALUE*)(msg + submsgdata->ofs);
-
-  set_hasbit(closure, submsgdata->hasbit);
-
-  switch (submsgdata->wrapped_type) {
-    case UPB_TYPE_FLOAT:
-    case UPB_TYPE_DOUBLE:
-      *field = DBL2NUM(0);
-      break;
-    case UPB_TYPE_BOOL:
-      *field = Qfalse;
-      break;
-    case UPB_TYPE_STRING:
-      *field = get_frozen_string(NULL, 0, false);
-      break;
-    case UPB_TYPE_BYTES:
-      *field = get_frozen_string(NULL, 0, true);
-      break;
-    case UPB_TYPE_ENUM:
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_UINT64:
-      *field = INT2NUM(0);
-      break;
-    case UPB_TYPE_MESSAGE:
-      rb_raise(rb_eRuntimeError,
-               "Internal logic error with well-known types.");
-  }
-
-  return field;
-}
-
-// Handler data for startmap/endmap handlers.
-typedef struct {
-  size_t ofs;
-  upb_fieldtype_t key_field_type;
-  upb_fieldtype_t value_field_type;
-  VALUE subklass;
-} map_handlerdata_t;
-
-// Temporary frame for map parsing: at the beginning of a map entry message, a
-// submsg handler allocates a frame to hold (i) a reference to the Map object
-// into which this message will be inserted and (ii) storage slots to
-// temporarily hold the key and value for this map entry until the end of the
-// submessage. When the submessage ends, another handler is called to insert the
-// value into the map.
-typedef struct {
-  VALUE map;
-  const map_handlerdata_t* handlerdata;
-  char key_storage[NATIVE_SLOT_MAX_SIZE];
-  char value_storage[NATIVE_SLOT_MAX_SIZE];
-} map_parse_frame_t;
-
-static void MapParseFrame_mark(void* _self) {
-  map_parse_frame_t* frame = _self;
-
-  // This shouldn't strictly be necessary since this should be rooted by the
-  // message itself, but it can't hurt.
-  rb_gc_mark(frame->map);
-
-  native_slot_mark(frame->handlerdata->key_field_type, &frame->key_storage);
-  native_slot_mark(frame->handlerdata->value_field_type, &frame->value_storage);
-}
-
-void MapParseFrame_free(void* self) {
-  xfree(self);
-}
-
-rb_data_type_t MapParseFrame_type = {
-  "MapParseFrame",
-  { MapParseFrame_mark, MapParseFrame_free, NULL },
-};
-
-// Handler to begin a map entry: allocates a temporary frame. This is the
-// 'startsubmsg' handler on the msgdef that contains the map field.
-static void *startmap_handler(void *closure, const void *hd) {
-  MessageHeader* msg = closure;
-  const map_handlerdata_t* mapdata = hd;
-  map_parse_frame_t* frame = ALLOC(map_parse_frame_t);
-  VALUE map_rb = DEREF(msg, mapdata->ofs, VALUE);
-
-  frame->handlerdata = mapdata;
-  frame->map = map_rb;
-  native_slot_init(mapdata->key_field_type, &frame->key_storage);
-  native_slot_init(mapdata->value_field_type, &frame->value_storage);
-
-  Map_set_frame(map_rb,
-                TypedData_Wrap_Struct(rb_cObject, &MapParseFrame_type, frame));
-
-  return frame;
-}
-
-static bool endmap_handler(void *closure, const void *hd) {
-  map_parse_frame_t* frame = closure;
-  Map_set_frame(frame->map, Qnil);
-  return true;
-}
-
-// Handler to end a map entry: inserts the value defined during the message into
-// the map. This is the 'endmsg' handler on the map entry msgdef.
-static bool endmapentry_handler(void* closure, const void* hd, upb_status* s) {
-  map_parse_frame_t* frame = closure;
-  const map_handlerdata_t* mapdata = hd;
-
-  VALUE key = native_slot_get(
-      mapdata->key_field_type, Qnil,
-      &frame->key_storage);
-
-  VALUE value = native_slot_get(
-      mapdata->value_field_type, mapdata->subklass,
-      &frame->value_storage);
-
-  Map_index_set(frame->map, key, value);
-
-  return true;
-}
-
-// Allocates a new map_handlerdata_t given the map entry message definition. If
-// the offset of the field within the parent message is also given, that is
-// added to the handler data as well. Note that this is called *twice* per map
-// field: once in the parent message handler setup when setting the startsubmsg
-// handler and once in the map entry message handler setup when setting the
-// key/value and endmsg handlers. The reason is that there is no easy way to
-// pass the handlerdata down to the sub-message handler setup.
-static map_handlerdata_t* new_map_handlerdata(
-    size_t ofs,
-    const upb_msgdef* mapentry_def,
-    const Descriptor* desc) {
-  const upb_fielddef* key_field;
-  const upb_fielddef* value_field;
-  map_handlerdata_t* hd = ALLOC(map_handlerdata_t);
-  hd->ofs = ofs;
-  key_field = upb_msgdef_itof(mapentry_def, MAP_KEY_FIELD);
-  assert(key_field != NULL);
-  hd->key_field_type = upb_fielddef_type(key_field);
-  value_field = upb_msgdef_itof(mapentry_def, MAP_VALUE_FIELD);
-  assert(value_field != NULL);
-  hd->value_field_type = upb_fielddef_type(value_field);
-  hd->subklass = field_type_class(desc->layout, value_field);
-
-  return hd;
-}
-
-// Handlers that set primitive values in oneofs.
-#define DEFINE_ONEOF_HANDLER(type, ctype)                           \
-  static bool oneof##type##_handler(void *closure, const void *hd,  \
-                                     ctype val) {                   \
-    const oneof_handlerdata_t *oneofdata = hd;                      \
-    DEREF(closure, oneofdata->case_ofs, uint32_t) =                 \
-        oneofdata->oneof_case_num;                                  \
-    DEREF(closure, oneofdata->ofs, ctype) = val;                    \
-    return true;                                                    \
-  }
-
-DEFINE_ONEOF_HANDLER(bool,   bool)
-DEFINE_ONEOF_HANDLER(int32,  int32_t)
-DEFINE_ONEOF_HANDLER(uint32, uint32_t)
-DEFINE_ONEOF_HANDLER(float,  float)
-DEFINE_ONEOF_HANDLER(int64,  int64_t)
-DEFINE_ONEOF_HANDLER(uint64, uint64_t)
-DEFINE_ONEOF_HANDLER(double, double)
-
-#undef DEFINE_ONEOF_HANDLER
-
-// Handlers for strings in a oneof.
-static void *oneofstr_handler(void *closure,
-                              const void *hd,
-                              size_t size_hint) {
-  MessageHeader* msg = closure;
-  const oneof_handlerdata_t *oneofdata = hd;
-  VALUE str = rb_str_new2("");
-  rb_enc_associate(str, kRubyStringUtf8Encoding);
-  DEREF(msg, oneofdata->case_ofs, uint32_t) =
-      oneofdata->oneof_case_num;
-  DEREF(msg, oneofdata->ofs, VALUE) = str;
-  return (void*)str;
-}
-
-static void *oneofbytes_handler(void *closure,
-                                const void *hd,
-                                size_t size_hint) {
-  MessageHeader* msg = closure;
-  const oneof_handlerdata_t *oneofdata = hd;
-  VALUE str = rb_str_new2("");
-  rb_enc_associate(str, kRubyString8bitEncoding);
-  DEREF(msg, oneofdata->case_ofs, uint32_t) =
-      oneofdata->oneof_case_num;
-  DEREF(msg, oneofdata->ofs, VALUE) = str;
-  return (void*)str;
-}
-
-static bool oneofstring_end_handler(void* closure, const void* hd) {
-  VALUE rb_str = rb_str_new2("");
-  rb_obj_freeze(rb_str);
-  return true;
-}
-
-// Handler for a submessage field in a oneof.
-static void *oneofsubmsg_handler(void *closure,
-                                 const void *hd) {
-  MessageHeader* msg = closure;
-  const oneof_handlerdata_t *oneofdata = hd;
-  uint32_t oldcase = DEREF(msg, oneofdata->case_ofs, uint32_t);
-
-  VALUE submsg_rb;
-  MessageHeader* submsg;
-
-  if (oldcase != oneofdata->oneof_case_num ||
-      DEREF(msg, oneofdata->ofs, VALUE) == Qnil) {
-    DEREF(msg, oneofdata->ofs, VALUE) =
-        initialize_rb_class_with_no_args(oneofdata->subklass);
-  }
-  // Set the oneof case *after* allocating the new class instance -- otherwise,
-  // if the Ruby GC is invoked as part of a call into the VM, it might invoke
-  // our mark routines, and our mark routines might see the case value
-  // indicating a VALUE is present and expect a valid VALUE. See comment in
-  // layout_set() for more detail: basically, the change to the value and the
-  // case must be atomic w.r.t. the Ruby VM.
-  DEREF(msg, oneofdata->case_ofs, uint32_t) = oneofdata->oneof_case_num;
-
-  submsg_rb = DEREF(msg, oneofdata->ofs, VALUE);
-  TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
-  return submsg;
-}
-
-static void* oneof_startwrapper(void* closure, const void* hd) {
-  char* msg = closure;
-  const oneof_handlerdata_t *oneofdata = hd;
-
-  DEREF(msg, oneofdata->case_ofs, uint32_t) = oneofdata->oneof_case_num;
-
-  return msg + oneofdata->ofs;
-}
-
-// Set up handlers for a repeated field.
-static void add_handlers_for_repeated_field(upb_handlers *h,
-                                            const Descriptor* desc,
-                                            const upb_fielddef *f,
-                                            size_t offset) {
-  upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-  attr.handler_data = newhandlerdata(h, offset, -1);
-  upb_handlers_setstartseq(h, f, startseq_handler, &attr);
-
-  switch (upb_fielddef_type(f)) {
-
-#define SET_HANDLER(utype, ltype)                                 \
-  case utype:                                                     \
-    upb_handlers_set##ltype(h, f, append##ltype##_handler, NULL); \
-    break;
-
-    SET_HANDLER(UPB_TYPE_BOOL,   bool);
-    SET_HANDLER(UPB_TYPE_INT32,  int32);
-    SET_HANDLER(UPB_TYPE_UINT32, uint32);
-    SET_HANDLER(UPB_TYPE_ENUM,   int32);
-    SET_HANDLER(UPB_TYPE_FLOAT,  float);
-    SET_HANDLER(UPB_TYPE_INT64,  int64);
-    SET_HANDLER(UPB_TYPE_UINT64, uint64);
-    SET_HANDLER(UPB_TYPE_DOUBLE, double);
-
-#undef SET_HANDLER
-
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
-      upb_handlers_setstartstr(h, f, is_bytes ?
-                               appendbytes_handler : appendstr_handler,
-                               NULL);
-      upb_handlers_setstring(h, f, stringdata_handler, NULL);
-      upb_handlers_setendstr(h, f, appendstring_end_handler, NULL);
-      break;
-    }
-    case UPB_TYPE_MESSAGE: {
-      VALUE subklass = field_type_class(desc->layout, f);
-      upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-      attr.handler_data = newsubmsghandlerdata(h, f, 0, -1, subklass);
-      if (is_wrapper(upb_fielddef_msgsubdef(f))) {
-        upb_handlers_setstartsubmsg(h, f, appendwrapper_handler, &attr);
-      } else {
-        upb_handlers_setstartsubmsg(h, f, appendsubmsg_handler, &attr);
-      }
-      break;
-    }
-  }
-}
-
-static bool doublewrapper_handler(void* closure, const void* hd, double val) {
-  VALUE* rbval = closure;
-  *rbval = DBL2NUM(val);
-  return true;
-}
-
-static bool floatwrapper_handler(void* closure, const void* hd, float val) {
-  VALUE* rbval = closure;
-  *rbval = DBL2NUM(val);
-  return true;
-}
-
-static bool int64wrapper_handler(void* closure, const void* hd, int64_t val) {
-  VALUE* rbval = closure;
-  *rbval = LL2NUM(val);
-  return true;
-}
-
-static bool uint64wrapper_handler(void* closure, const void* hd, uint64_t val) {
-  VALUE* rbval = closure;
-  *rbval = ULL2NUM(val);
-  return true;
-}
-
-static bool int32wrapper_handler(void* closure, const void* hd, int32_t val) {
-  VALUE* rbval = closure;
-  *rbval = INT2NUM(val);
-  return true;
-}
-
-static bool uint32wrapper_handler(void* closure, const void* hd, uint32_t val) {
-  VALUE* rbval = closure;
-  *rbval = UINT2NUM(val);
-  return true;
-}
-
-static void* startstringwrapper_handler(void* closure, const void* hd,
-                                        size_t size_hint) {
-  VALUE* rbval = closure;
-  (void)size_hint;
-  *rbval = rb_str_new(NULL, 0);
-  rb_enc_associate(*rbval, kRubyStringUtf8Encoding);
-  return closure;
-}
-
-static size_t stringwrapper_handler(void* closure, const void* hd,
-                                    const char* ptr, size_t len,
-                                    const upb_bufhandle* handle) {
-  VALUE* rbval = closure;
-  *rbval = noleak_rb_str_cat(*rbval, ptr, len);
-  return len;
-}
-
-static void* startbyteswrapper_handler(void* closure, const void* hd,
-                                       size_t size_hint) {
-  VALUE* rbval = closure;
-  (void)size_hint;
-  *rbval = rb_str_new(NULL, 0);
-  rb_enc_associate(*rbval, kRubyString8bitEncoding);
-  return closure;
-}
-
-static size_t byteswrapper_handler(void* closure, const void* hd,
-                                   const char* ptr, size_t len,
-                                   const upb_bufhandle* handle) {
-  VALUE* rbval = closure;
-  *rbval = noleak_rb_str_cat(*rbval, ptr, len);
-  return len;
-}
-
-static bool boolwrapper_handler(void* closure, const void* hd, bool val) {
-  VALUE* rbval = closure;
-  if (val) {
-    *rbval = Qtrue;
-  } else {
-    *rbval = Qfalse;
-  }
-  return true;
-}
-
-// Set up handlers for a singular field.
-static void add_handlers_for_singular_field(const Descriptor* desc,
-                                            upb_handlers* h,
-                                            const upb_fielddef* f,
-                                            size_t offset, size_t hasbit_off) {
-  // The offset we pass to UPB points to the start of the Message,
-  // rather than the start of where our data is stored.
-  int32_t hasbit = -1;
-  if (hasbit_off != MESSAGE_FIELD_NO_HASBIT) {
-    hasbit = hasbit_off + sizeof(MessageHeader) * 8;
-  }
-
-  switch (upb_fielddef_type(f)) {
-    case UPB_TYPE_BOOL:
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_ENUM:
-    case UPB_TYPE_FLOAT:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT64:
-    case UPB_TYPE_DOUBLE:
-      upb_msg_setscalarhandler(h, f, offset, hasbit);
-      break;
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
-      upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-      attr.handler_data = newhandlerdata(h, offset, hasbit);
-      upb_handlers_setstartstr(h, f,
-                               is_bytes ? bytes_handler : str_handler,
-                               &attr);
-      upb_handlers_setstring(h, f, stringdata_handler, &attr);
-      upb_handlers_setendstr(h, f, stringdata_end_handler, &attr);
-      break;
-    }
-    case UPB_TYPE_MESSAGE: {
-      upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-      attr.handler_data = newsubmsghandlerdata(
-          h, f, offset, hasbit, field_type_class(desc->layout, f));
-      if (is_wrapper(upb_fielddef_msgsubdef(f))) {
-        upb_handlers_setstartsubmsg(h, f, startwrapper, &attr);
-      } else {
-        upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr);
-      }
-    }
-  }
-}
-
-// Adds handlers to a map field.
-static void add_handlers_for_mapfield(upb_handlers* h,
-                                      const upb_fielddef* fielddef,
-                                      size_t offset,
-                                      const Descriptor* desc) {
-  const upb_msgdef* map_msgdef = upb_fielddef_msgsubdef(fielddef);
-  map_handlerdata_t* hd = new_map_handlerdata(offset, map_msgdef, desc);
-  upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_addcleanup(h, hd, xfree);
-  attr.handler_data = hd;
-  upb_handlers_setstartsubmsg(h, fielddef, startmap_handler, &attr);
-  upb_handlers_setendsubmsg(h, fielddef, endmap_handler, &attr);
-}
-
-// Adds handlers to a map-entry msgdef.
-static void add_handlers_for_mapentry(const upb_msgdef* msgdef, upb_handlers* h,
-                                      const Descriptor* desc) {
-  const upb_fielddef* key_field = map_entry_key(msgdef);
-  const upb_fielddef* value_field = map_entry_value(msgdef);
-  map_handlerdata_t* hd = new_map_handlerdata(0, msgdef, desc);
-  upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_addcleanup(h, hd, xfree);
-  attr.handler_data = hd;
-  upb_handlers_setendmsg(h, endmapentry_handler, &attr);
-
-  add_handlers_for_singular_field(
-      desc, h, key_field,
-      offsetof(map_parse_frame_t, key_storage),
-      MESSAGE_FIELD_NO_HASBIT);
-  add_handlers_for_singular_field(
-      desc, h, value_field,
-      offsetof(map_parse_frame_t, value_storage),
-      MESSAGE_FIELD_NO_HASBIT);
-}
-
-static void add_handlers_for_wrapper(const upb_msgdef* msgdef,
-                                     upb_handlers* h) {
-  const upb_fielddef* f = upb_msgdef_itof(msgdef, 1);
-  switch (upb_msgdef_wellknowntype(msgdef)) {
-    case UPB_WELLKNOWN_DOUBLEVALUE:
-      upb_handlers_setdouble(h, f, doublewrapper_handler, NULL);
-      break;
-    case UPB_WELLKNOWN_FLOATVALUE:
-      upb_handlers_setfloat(h, f, floatwrapper_handler, NULL);
-      break;
-    case UPB_WELLKNOWN_INT64VALUE:
-      upb_handlers_setint64(h, f, int64wrapper_handler, NULL);
-      break;
-    case UPB_WELLKNOWN_UINT64VALUE:
-      upb_handlers_setuint64(h, f, uint64wrapper_handler, NULL);
-      break;
-    case UPB_WELLKNOWN_INT32VALUE:
-      upb_handlers_setint32(h, f, int32wrapper_handler, NULL);
-      break;
-    case UPB_WELLKNOWN_UINT32VALUE:
-      upb_handlers_setuint32(h, f, uint32wrapper_handler, NULL);
-      break;
-    case UPB_WELLKNOWN_STRINGVALUE:
-      upb_handlers_setstartstr(h, f, startstringwrapper_handler, NULL);
-      upb_handlers_setstring(h, f, stringwrapper_handler, NULL);
-      break;
-    case UPB_WELLKNOWN_BYTESVALUE:
-      upb_handlers_setstartstr(h, f, startbyteswrapper_handler, NULL);
-      upb_handlers_setstring(h, f, byteswrapper_handler, NULL);
-      break;
-    case UPB_WELLKNOWN_BOOLVALUE:
-      upb_handlers_setbool(h, f, boolwrapper_handler, NULL);
-      return;
-    default:
-      rb_raise(rb_eRuntimeError,
-               "Internal logic error with well-known types.");
-  }
-}
-
-// Set up handlers for a oneof field.
-static void add_handlers_for_oneof_field(upb_handlers *h,
-                                         const upb_fielddef *f,
-                                         size_t offset,
-                                         size_t oneof_case_offset,
-                                         const Descriptor* desc) {
-  upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-  attr.handler_data =
-      newoneofhandlerdata(h, offset, oneof_case_offset, f, desc);
-
-  switch (upb_fielddef_type(f)) {
-
-#define SET_HANDLER(utype, ltype)                                 \
-  case utype:                                                     \
-    upb_handlers_set##ltype(h, f, oneof##ltype##_handler, &attr); \
-    break;
-
-    SET_HANDLER(UPB_TYPE_BOOL,   bool);
-    SET_HANDLER(UPB_TYPE_INT32,  int32);
-    SET_HANDLER(UPB_TYPE_UINT32, uint32);
-    SET_HANDLER(UPB_TYPE_ENUM,   int32);
-    SET_HANDLER(UPB_TYPE_FLOAT,  float);
-    SET_HANDLER(UPB_TYPE_INT64,  int64);
-    SET_HANDLER(UPB_TYPE_UINT64, uint64);
-    SET_HANDLER(UPB_TYPE_DOUBLE, double);
-
-#undef SET_HANDLER
-
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
-      upb_handlers_setstartstr(h, f, is_bytes ?
-                               oneofbytes_handler : oneofstr_handler,
-                               &attr);
-      upb_handlers_setstring(h, f, stringdata_handler, NULL);
-      upb_handlers_setendstr(h, f, oneofstring_end_handler, &attr);
-      break;
-    }
-    case UPB_TYPE_MESSAGE: {
-      if (is_wrapper(upb_fielddef_msgsubdef(f))) {
-        upb_handlers_setstartsubmsg(h, f, oneof_startwrapper, &attr);
-      } else {
-        upb_handlers_setstartsubmsg(h, f, oneofsubmsg_handler, &attr);
-      }
-      break;
-    }
-  }
-}
-
-static bool unknown_field_handler(void* closure, const void* hd,
-                                  const char* buf, size_t size) {
-  MessageHeader* msg = (MessageHeader*)closure;
-  UPB_UNUSED(hd);
-
-  if (msg->unknown_fields == NULL) {
-    msg->unknown_fields = malloc(sizeof(stringsink));
-    stringsink_init(msg->unknown_fields);
-  }
-
-  stringsink_string(msg->unknown_fields, NULL, buf, size, NULL);
-
-  return true;
-}
-
-size_t get_field_offset(MessageLayout* layout, const upb_fielddef* f) {
-  return layout->fields[upb_fielddef_index(f)].offset + sizeof(MessageHeader);
-}
-
-void add_handlers_for_message(const void *closure, upb_handlers *h) {
-  const VALUE descriptor_pool = (VALUE)closure;
-  const upb_msgdef* msgdef = upb_handlers_msgdef(h);
-  Descriptor* desc =
-      ruby_to_Descriptor(get_msgdef_obj(descriptor_pool, msgdef));
-  upb_msg_field_iter i;
-  upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-
-  // Ensure layout exists. We may be invoked to create handlers for a given
-  // message if we are included as a submsg of another message type before our
-  // class is actually built, so to work around this, we just create the layout
-  // (and handlers, in the class-building function) on-demand.
-  if (desc->layout == NULL) {
-    create_layout(desc);
-  }
-
-  // If this is a mapentry message type, set up a special set of handlers and
-  // bail out of the normal (user-defined) message type handling.
-  if (upb_msgdef_mapentry(msgdef)) {
-    add_handlers_for_mapentry(msgdef, h, desc);
-    return;
-  }
-
-  // If this is a wrapper type, use special handlers and bail.
-  if (is_wrapper(msgdef)) {
-    add_handlers_for_wrapper(msgdef, h);
-    return;
-  }
-
-  upb_handlers_setunknown(h, unknown_field_handler, &attr);
-
-  for (upb_msg_field_begin(&i, desc->msgdef);
-       !upb_msg_field_done(&i);
-       upb_msg_field_next(&i)) {
-    const upb_fielddef *f = upb_msg_iter_field(&i);
-    const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(f);
-    size_t offset = get_field_offset(desc->layout, f);
-
-    if (oneof) {
-      size_t oneof_case_offset =
-          desc->layout->oneofs[upb_oneofdef_index(oneof)].case_offset +
-          sizeof(MessageHeader);
-      add_handlers_for_oneof_field(h, f, offset, oneof_case_offset, desc);
-    } else if (is_map_field(f)) {
-      add_handlers_for_mapfield(h, f, offset, desc);
-    } else if (upb_fielddef_isseq(f)) {
-      add_handlers_for_repeated_field(h, desc, f, offset);
-    } else {
-      add_handlers_for_singular_field(
-          desc, h, f, offset,
-          desc->layout->fields[upb_fielddef_index(f)].hasbit);
-    }
-  }
-}
-
-// Constructs the handlers for filling a message's data into an in-memory
-// object.
-const upb_handlers* get_fill_handlers(Descriptor* desc) {
-  DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
-  return upb_handlercache_get(pool->fill_handler_cache, desc->msgdef);
-}
-
-static const upb_pbdecodermethod *msgdef_decodermethod(Descriptor* desc) {
-  DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
-  return upb_pbcodecache_get(pool->fill_method_cache, desc->msgdef);
-}
-
-static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) {
-  DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
-  return upb_json_codecache_get(pool->json_fill_method_cache, desc->msgdef);
-}
-
-static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) {
-  DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
-  return upb_handlercache_get(pool->pb_serialize_handler_cache, desc->msgdef);
-}
-
-static const upb_handlers* msgdef_json_serialize_handlers(
-    Descriptor* desc, bool preserve_proto_fieldnames) {
-  DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
-  if (preserve_proto_fieldnames) {
-    return upb_handlercache_get(pool->json_serialize_handler_preserve_cache,
-                                desc->msgdef);
-  } else {
-    return upb_handlercache_get(pool->json_serialize_handler_cache,
-                                desc->msgdef);
-  }
-}
-
-
-// Stack-allocated context during an encode/decode operation. Contains the upb
-// environment and its stack-based allocator, an initial buffer for allocations
-// to avoid malloc() when possible, and a template for Ruby exception messages
-// if any error occurs.
-#define STACK_ENV_STACKBYTES 4096
-typedef struct {
-  upb_arena *arena;
-  upb_status status;
-  const char* ruby_error_template;
-  char allocbuf[STACK_ENV_STACKBYTES];
-} stackenv;
-
-static void stackenv_init(stackenv* se, const char* errmsg);
-static void stackenv_uninit(stackenv* se);
-
-static void stackenv_init(stackenv* se, const char* errmsg) {
-  se->ruby_error_template = errmsg;
-  se->arena =
-      upb_arena_init(se->allocbuf, sizeof(se->allocbuf), &upb_alloc_global);
-  upb_status_clear(&se->status);
-}
-
-static void stackenv_uninit(stackenv* se) {
-  upb_arena_free(se->arena);
-
-  if (!upb_ok(&se->status)) {
-    // TODO(haberman): have a way to verify that this is actually a parse error,
-    // instead of just throwing "parse error" unconditionally.
-    VALUE errmsg = rb_str_new2(upb_status_errmsg(&se->status));
-    rb_raise(cParseError, se->ruby_error_template, errmsg);
-  }
-}
-
-/*
- * call-seq:
- *     MessageClass.decode(data) => message
- *
- * Decodes the given data (as a string containing bytes in protocol buffers wire
- * format) under the interpretration given by this message class's definition
- * and returns a message object with the corresponding field values.
- */
-VALUE Message_decode(VALUE klass, VALUE data) {
-  VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
-  Descriptor* desc = ruby_to_Descriptor(descriptor);
-  VALUE msgklass = Descriptor_msgclass(descriptor);
-  VALUE msg_rb;
-  MessageHeader* msg;
-
-  if (TYPE(data) != T_STRING) {
-    rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
-  }
-
-  msg_rb = initialize_rb_class_with_no_args(msgklass);
-  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
-
-  {
-    const upb_pbdecodermethod* method = msgdef_decodermethod(desc);
-    const upb_handlers* h = upb_pbdecodermethod_desthandlers(method);
-    const upb_msgdef* m = upb_handlers_msgdef(h);
-    VALUE wrapper = Qnil;
-    void* ptr = msg;
-    stackenv se;
-    upb_sink sink;
-    upb_pbdecoder* decoder;
-    stackenv_init(&se, "Error occurred during parsing: %" PRIsVALUE);
-
-    if (is_wrapper(m)) {
-      ptr = &wrapper;
-    }
-
-    upb_sink_reset(&sink, h, ptr);
-    decoder = upb_pbdecoder_create(se.arena, method, sink, &se.status);
-    upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data),
-                      upb_pbdecoder_input(decoder));
-
-    stackenv_uninit(&se);
-
-    if (is_wrapper(m)) {
-      msg_rb = ruby_wrapper_type(msgklass, wrapper);
-    }
-  }
-
-  return msg_rb;
-}
-
-/*
- * call-seq:
- *     MessageClass.decode_json(data, options = {}) => message
- *
- * Decodes the given data (as a string containing bytes in protocol buffers wire
- * format) under the interpretration given by this message class's definition
- * and returns a message object with the corresponding field values.
- *
- *  @param options [Hash] options for the decoder
- *   ignore_unknown_fields: set true to ignore unknown fields (default is to
- *   raise an error)
- */
-VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
-  VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
-  Descriptor* desc = ruby_to_Descriptor(descriptor);
-  VALUE msgklass = Descriptor_msgclass(descriptor);
-  VALUE msg_rb;
-  VALUE data = argv[0];
-  VALUE ignore_unknown_fields = Qfalse;
-  MessageHeader* msg;
-
-  if (argc < 1 || argc > 2) {
-    rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
-  }
-
-  if (argc == 2) {
-    VALUE hash_args = argv[1];
-    if (TYPE(hash_args) != T_HASH) {
-      rb_raise(rb_eArgError, "Expected hash arguments.");
-    }
-
-    ignore_unknown_fields = rb_hash_lookup2(
-        hash_args, ID2SYM(rb_intern("ignore_unknown_fields")), Qfalse);
-  }
-
-  if (TYPE(data) != T_STRING) {
-    rb_raise(rb_eArgError, "Expected string for JSON data.");
-  }
-
-  // TODO(cfallin): Check and respect string encoding. If not UTF-8, we need to
-  // convert, because string handlers pass data directly to message string
-  // fields.
-
-  msg_rb = initialize_rb_class_with_no_args(msgklass);
-  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
-
-  {
-    const upb_json_parsermethod* method = msgdef_jsonparsermethod(desc);
-    const upb_handlers* h = get_fill_handlers(desc);
-    const upb_msgdef* m = upb_handlers_msgdef(h);
-    stackenv se;
-    upb_sink sink;
-    upb_json_parser* parser;
-    DescriptorPool* pool = ruby_to_DescriptorPool(generated_pool);
-    stackenv_init(&se, "Error occurred during parsing: %" PRIsVALUE);
-
-    if (is_wrapper(m)) {
-      rb_raise(
-          rb_eRuntimeError,
-          "Parsing a wrapper type from JSON at the top level does not work.");
-    }
-
-    upb_sink_reset(&sink, h, msg);
-    parser = upb_json_parser_create(se.arena, method, pool->symtab, sink,
-                                    &se.status, RTEST(ignore_unknown_fields));
-    upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data),
-                      upb_json_parser_input(parser));
-
-    stackenv_uninit(&se);
-  }
-
-  return msg_rb;
-}
-
-// -----------------------------------------------------------------------------
-// Serializing.
-// -----------------------------------------------------------------------------
-
-/* msgvisitor *****************************************************************/
-
-static void putmsg(VALUE msg, const Descriptor* desc, upb_sink sink, int depth,
-                   bool emit_defaults, bool is_json, bool open_msg);
-
-static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
-  upb_selector_t ret;
-  bool ok = upb_handlers_getselector(f, type, &ret);
-  UPB_ASSERT(ok);
-  return ret;
-}
-
-static void putstr(VALUE str, const upb_fielddef *f, upb_sink sink) {
-  upb_sink subsink;
-
-  if (str == Qnil) return;
-
-  assert(BUILTIN_TYPE(str) == RUBY_T_STRING);
-
-  // We should be guaranteed that the string has the correct encoding because
-  // we ensured this at assignment time and then froze the string.
-  if (upb_fielddef_type(f) == UPB_TYPE_STRING) {
-    assert(rb_enc_from_index(ENCODING_GET(str)) == kRubyStringUtf8Encoding);
-  } else {
-    assert(rb_enc_from_index(ENCODING_GET(str)) == kRubyString8bitEncoding);
-  }
-
-  upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), RSTRING_LEN(str),
-                    &subsink);
-  upb_sink_putstring(subsink, getsel(f, UPB_HANDLER_STRING), RSTRING_PTR(str),
-                     RSTRING_LEN(str), NULL);
-  upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR));
-}
-
-static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink sink,
-                      int depth, bool emit_defaults, bool is_json) {
-  upb_sink subsink;
-  VALUE descriptor;
-  Descriptor* subdesc;
-
-  if (submsg == Qnil) return;
-
-  descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned);
-  subdesc = ruby_to_Descriptor(descriptor);
-
-  upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink);
-  putmsg(submsg, subdesc, subsink, depth + 1, emit_defaults, is_json, true);
-  upb_sink_endsubmsg(sink, subsink, getsel(f, UPB_HANDLER_ENDSUBMSG));
-}
-
-static void putary(VALUE ary, const upb_fielddef* f, upb_sink sink, int depth,
-                   bool emit_defaults, bool is_json) {
-  upb_sink subsink;
-  upb_fieldtype_t type = upb_fielddef_type(f);
-  upb_selector_t sel = 0;
-  int size;
-  int i;
-  VALUE type_class = ruby_to_RepeatedField(ary)->field_type_class;
-
-  if (ary == Qnil) return;
-  if (!emit_defaults && NUM2INT(RepeatedField_length(ary)) == 0) return;
-
-  size = NUM2INT(RepeatedField_length(ary));
-  if (size == 0 && !emit_defaults) return;
-
-  upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
-
-  if (upb_fielddef_isprimitive(f)) {
-    sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
-  }
-
-  for (i = 0; i < size; i++) {
-    void* memory = RepeatedField_index_native(ary, i);
-    switch (type) {
-#define T(upbtypeconst, upbtype, ctype)                     \
-  case upbtypeconst:                                        \
-    upb_sink_put##upbtype(subsink, sel, *((ctype*)memory)); \
-    break;
-
-      T(UPB_TYPE_FLOAT,  float,  float)
-      T(UPB_TYPE_DOUBLE, double, double)
-      T(UPB_TYPE_BOOL,   bool,   int8_t)
-      case UPB_TYPE_ENUM:
-      T(UPB_TYPE_INT32,  int32,  int32_t)
-      T(UPB_TYPE_UINT32, uint32, uint32_t)
-      T(UPB_TYPE_INT64,  int64,  int64_t)
-      T(UPB_TYPE_UINT64, uint64, uint64_t)
-
-      case UPB_TYPE_STRING:
-      case UPB_TYPE_BYTES:
-        putstr(*((VALUE *)memory), f, subsink);
-        break;
-      case UPB_TYPE_MESSAGE: {
-        VALUE val = native_slot_get(UPB_TYPE_MESSAGE, type_class, memory);
-        putsubmsg(val, f, subsink, depth, emit_defaults, is_json);
-        break;
-      }
-
-#undef T
-
-    }
-  }
-  upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
-}
-
-static void put_ruby_value(VALUE value, const upb_fielddef* f, VALUE type_class,
-                           int depth, upb_sink sink, bool emit_defaults,
-                           bool is_json) {
-  upb_selector_t sel = 0;
-
-  if (depth > ENCODE_MAX_NESTING) {
-    rb_raise(rb_eRuntimeError,
-             "Maximum recursion depth exceeded during encoding.");
-  }
-
-  if (upb_fielddef_isprimitive(f)) {
-    sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
-  }
-
-  switch (upb_fielddef_type(f)) {
-    case UPB_TYPE_INT32:
-      upb_sink_putint32(sink, sel, NUM2INT(value));
-      break;
-    case UPB_TYPE_INT64:
-      upb_sink_putint64(sink, sel, NUM2LL(value));
-      break;
-    case UPB_TYPE_UINT32:
-      upb_sink_putuint32(sink, sel, NUM2UINT(value));
-      break;
-    case UPB_TYPE_UINT64:
-      upb_sink_putuint64(sink, sel, NUM2ULL(value));
-      break;
-    case UPB_TYPE_FLOAT:
-      upb_sink_putfloat(sink, sel, NUM2DBL(value));
-      break;
-    case UPB_TYPE_DOUBLE:
-      upb_sink_putdouble(sink, sel, NUM2DBL(value));
-      break;
-    case UPB_TYPE_ENUM: {
-      if (TYPE(value) == T_SYMBOL) {
-        value = rb_funcall(type_class, rb_intern("resolve"), 1, value);
-      }
-      upb_sink_putint32(sink, sel, NUM2INT(value));
-      break;
-    }
-    case UPB_TYPE_BOOL:
-      upb_sink_putbool(sink, sel, value == Qtrue);
-      break;
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-      putstr(value, f, sink);
-      break;
-    case UPB_TYPE_MESSAGE:
-      putsubmsg(value, f, sink, depth, emit_defaults, is_json);
-  }
-}
-
-static void putmap(VALUE map, const upb_fielddef* f, upb_sink sink, int depth,
-                   bool emit_defaults, bool is_json) {
-  Map* self;
-  upb_sink subsink;
-  const upb_fielddef* key_field;
-  const upb_fielddef* value_field;
-  Map_iter it;
-
-  if (map == Qnil) return;
-  if (!emit_defaults && Map_length(map) == 0) return;
-
-  self = ruby_to_Map(map);
-
-  upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
-
-  assert(upb_fielddef_type(f) == UPB_TYPE_MESSAGE);
-  key_field = map_field_key(f);
-  value_field = map_field_value(f);
-
-  for (Map_begin(map, &it); !Map_done(&it); Map_next(&it)) {
-    VALUE key = Map_iter_key(&it);
-    VALUE value = Map_iter_value(&it);
-    upb_status status;
-
-    upb_sink entry_sink;
-    upb_sink_startsubmsg(subsink, getsel(f, UPB_HANDLER_STARTSUBMSG),
-                         &entry_sink);
-    upb_sink_startmsg(entry_sink);
-
-    put_ruby_value(key, key_field, Qnil, depth + 1, entry_sink, emit_defaults,
-                   is_json);
-    put_ruby_value(value, value_field, self->value_type_class, depth + 1,
-                   entry_sink, emit_defaults, is_json);
-
-    upb_sink_endmsg(entry_sink, &status);
-    upb_sink_endsubmsg(subsink, entry_sink, getsel(f, UPB_HANDLER_ENDSUBMSG));
-  }
-
-  upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
-}
-
-static const upb_handlers* msgdef_json_serialize_handlers(
-    Descriptor* desc, bool preserve_proto_fieldnames);
-
-static void putjsonany(VALUE msg_rb, const Descriptor* desc, upb_sink sink,
-                       int depth, bool emit_defaults) {
-  upb_status status;
-  MessageHeader* msg = NULL;
-  const upb_fielddef* type_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_TYPE);
-  const upb_fielddef* value_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_VALUE);
-
-  size_t type_url_offset;
-  VALUE type_url_str_rb;
-  const upb_msgdef *payload_type = NULL;
-
-  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
-
-  upb_sink_startmsg(sink);
-
-  /* Handle type url */
-  type_url_offset = desc->layout->fields[upb_fielddef_index(type_field)].offset;
-  type_url_str_rb = DEREF(Message_data(msg), type_url_offset, VALUE);
-  if (RSTRING_LEN(type_url_str_rb) > 0) {
-    putstr(type_url_str_rb, type_field, sink);
-  }
-
-  {
-    const char* type_url_str = RSTRING_PTR(type_url_str_rb);
-    size_t type_url_len = RSTRING_LEN(type_url_str_rb);
-    DescriptorPool* pool = ruby_to_DescriptorPool(generated_pool);
-
-    if (type_url_len <= 20 ||
-        strncmp(type_url_str, "type.googleapis.com/", 20) != 0) {
-      rb_raise(rb_eRuntimeError, "Invalid type url: %s", type_url_str);
-      return;
-    }
-
-    /* Resolve type url */
-    type_url_str += 20;
-    type_url_len -= 20;
-
-    payload_type = upb_symtab_lookupmsg2(
-        pool->symtab, type_url_str, type_url_len);
-    if (payload_type == NULL) {
-      rb_raise(rb_eRuntimeError, "Unknown type: %s", type_url_str);
-      return;
-    }
-  }
-
-  {
-    uint32_t value_offset;
-    VALUE value_str_rb;
-    size_t value_len;
-
-    value_offset = desc->layout->fields[upb_fielddef_index(value_field)].offset;
-    value_str_rb = DEREF(Message_data(msg), value_offset, VALUE);
-    value_len = RSTRING_LEN(value_str_rb);
-
-    if (value_len > 0) {
-      VALUE payload_desc_rb = get_msgdef_obj(generated_pool, payload_type);
-      Descriptor* payload_desc = ruby_to_Descriptor(payload_desc_rb);
-      VALUE payload_class = Descriptor_msgclass(payload_desc_rb);
-      upb_sink subsink;
-      bool is_wellknown;
-
-      VALUE payload_msg_rb = Message_decode(payload_class, value_str_rb);
-
-      is_wellknown =
-          upb_msgdef_wellknowntype(payload_desc->msgdef) !=
-              UPB_WELLKNOWN_UNSPECIFIED;
-      if (is_wellknown) {
-        upb_sink_startstr(sink, getsel(value_field, UPB_HANDLER_STARTSTR), 0,
-                          &subsink);
-      }
-
-      subsink.handlers =
-          msgdef_json_serialize_handlers(payload_desc, true);
-      subsink.closure = sink.closure;
-      putmsg(payload_msg_rb, payload_desc, subsink, depth, emit_defaults, true,
-             is_wellknown);
-    }
-  }
-
-  upb_sink_endmsg(sink, &status);
-}
-
-static void putjsonlistvalue(
-    VALUE msg_rb, const Descriptor* desc,
-    upb_sink sink, int depth, bool emit_defaults) {
-  upb_status status;
-  upb_sink subsink;
-  MessageHeader* msg = NULL;
-  const upb_fielddef* f = upb_msgdef_itof(desc->msgdef, 1);
-  uint32_t offset =
-      desc->layout->fields[upb_fielddef_index(f)].offset +
-      sizeof(MessageHeader);
-  VALUE ary;
-
-  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
-
-  upb_sink_startmsg(sink);
-
-  ary = DEREF(msg, offset, VALUE);
-
-  if (ary == Qnil || RepeatedField_size(ary) == 0) {
-    upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
-    upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
-  } else {
-    putary(ary, f, sink, depth, emit_defaults, true);
-  }
-
-  upb_sink_endmsg(sink, &status);
-}
-
-static void putmsg(VALUE msg_rb, const Descriptor* desc,
-                   upb_sink sink, int depth, bool emit_defaults,
-                   bool is_json, bool open_msg) {
-  MessageHeader* msg;
-  upb_msg_field_iter i;
-  upb_status status;
-  bool json_wrapper = is_wrapper(desc->msgdef) && is_json;
-
-  if (is_json &&
-      upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_ANY) {
-    putjsonany(msg_rb, desc, sink, depth, emit_defaults);
-    return;
-  }
-
-  if (is_json &&
-      upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_LISTVALUE) {
-    putjsonlistvalue(msg_rb, desc, sink, depth, emit_defaults);
-    return;
-  }
-
-  if (open_msg) {
-    upb_sink_startmsg(sink);
-  }
-
-  // Protect against cycles (possible because users may freely reassign message
-  // and repeated fields) by imposing a maximum recursion depth.
-  if (depth > ENCODE_MAX_NESTING) {
-    rb_raise(rb_eRuntimeError,
-             "Maximum recursion depth exceeded during encoding.");
-  }
-
-  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
-
-  if (desc != msg->descriptor) {
-    rb_raise(rb_eArgError,
-             "The type of given msg is '%s', expect '%s'.",
-             upb_msgdef_fullname(msg->descriptor->msgdef),
-             upb_msgdef_fullname(desc->msgdef));
-  }
-
-  for (upb_msg_field_begin(&i, desc->msgdef);
-       !upb_msg_field_done(&i);
-       upb_msg_field_next(&i)) {
-    upb_fielddef *f = upb_msg_iter_field(&i);
-    const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(f);
-    bool is_matching_oneof = false;
-    uint32_t offset =
-        desc->layout->fields[upb_fielddef_index(f)].offset +
-        sizeof(MessageHeader);
-
-    if (oneof) {
-      uint32_t oneof_case =
-          slot_read_oneof_case(desc->layout, Message_data(msg), oneof);
-      // For a oneof, check that this field is actually present -- skip all the
-      // below if not.
-      if (oneof_case != upb_fielddef_number(f)) {
-        continue;
-      }
-      // Otherwise, fall through to the appropriate singular-field handler
-      // below.
-      is_matching_oneof = true;
-    }
-
-    if (is_map_field(f)) {
-      VALUE map = DEREF(msg, offset, VALUE);
-      if (map != Qnil || emit_defaults) {
-        putmap(map, f, sink, depth, emit_defaults, is_json);
-      }
-    } else if (upb_fielddef_isseq(f)) {
-      VALUE ary = DEREF(msg, offset, VALUE);
-      if (ary != Qnil) {
-        putary(ary, f, sink, depth, emit_defaults, is_json);
-      }
-    } else if (upb_fielddef_isstring(f)) {
-      VALUE str = DEREF(msg, offset, VALUE);
-      bool is_default = false;
-
-      if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO2) {
-        is_default = layout_has(desc->layout, Message_data(msg), f) == Qfalse;
-      } else if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO3) {
-        is_default = RSTRING_LEN(str) == 0;
-      }
-
-      if (is_matching_oneof || emit_defaults || !is_default || json_wrapper) {
-        putstr(str, f, sink);
-      }
-    } else if (upb_fielddef_issubmsg(f)) {
-      // OPT: could try to avoid the layout_get() (which will expand lazy
-      // wrappers).
-      VALUE val = layout_get(desc->layout, Message_data(msg), f);
-      putsubmsg(val, f, sink, depth, emit_defaults, is_json);
-    } else {
-      upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
-
-#define T(upbtypeconst, upbtype, ctype, default_value)                       \
-  case upbtypeconst: {                                                       \
-    ctype value = DEREF(msg, offset, ctype);                                 \
-    bool is_default = false;                                                 \
-    if (upb_fielddef_haspresence(f)) {                                       \
-      is_default = layout_has(desc->layout, Message_data(msg), f) == Qfalse; \
-    } else if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO3) {       \
-      is_default = default_value == value;                                   \
-    }                                                                        \
-    if (is_matching_oneof || emit_defaults || !is_default || json_wrapper) { \
-      upb_sink_put##upbtype(sink, sel, value);                               \
-    }                                                                        \
-  } break;
-
-      switch (upb_fielddef_type(f)) {
-        T(UPB_TYPE_FLOAT,  float,  float, 0.0)
-        T(UPB_TYPE_DOUBLE, double, double, 0.0)
-        T(UPB_TYPE_BOOL,   bool,   uint8_t, 0)
-        case UPB_TYPE_ENUM:
-        T(UPB_TYPE_INT32,  int32,  int32_t, 0)
-        T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
-        T(UPB_TYPE_INT64,  int64,  int64_t, 0)
-        T(UPB_TYPE_UINT64, uint64, uint64_t, 0)
-
-        case UPB_TYPE_STRING:
-        case UPB_TYPE_BYTES:
-        case UPB_TYPE_MESSAGE: rb_raise(rb_eRuntimeError, "Internal error.");
-      }
-
-#undef T
-    }
-  }
-
-  {
-    stringsink* unknown = msg->unknown_fields;
-    if (unknown != NULL) {
-      upb_sink_putunknown(sink, unknown->ptr, unknown->len);
-    }
-  }
-
-  if (open_msg) {
-    upb_sink_endmsg(sink, &status);
-  }
-}
-
-/*
- * call-seq:
- *     MessageClass.encode(msg) => bytes
- *
- * Encodes the given message object to its serialized form in protocol buffers
- * wire format.
- */
-VALUE Message_encode(VALUE klass, VALUE msg_rb) {
-  VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
-  Descriptor* desc = ruby_to_Descriptor(descriptor);
-
-  stringsink sink;
-  stringsink_init(&sink);
-
-  {
-    const upb_handlers* serialize_handlers =
-        msgdef_pb_serialize_handlers(desc);
-
-    stackenv se;
-    upb_pb_encoder* encoder;
-    VALUE ret;
-
-    stackenv_init(&se, "Error occurred during encoding: %" PRIsVALUE);
-    encoder = upb_pb_encoder_create(se.arena, serialize_handlers, sink.sink);
-
-    putmsg(msg_rb, desc, upb_pb_encoder_input(encoder), 0, false, false, true);
-
-    ret = rb_str_new(sink.ptr, sink.len);
-
-    stackenv_uninit(&se);
-    stringsink_uninit(&sink);
-
-    return ret;
-  }
-}
-
-/*
- * call-seq:
- *     MessageClass.encode_json(msg, options = {}) => json_string
- *
- * Encodes the given message object into its serialized JSON representation.
- * @param options [Hash] options for the decoder
- *  preserve_proto_fieldnames: set true to use original fieldnames (default is to camelCase)
- *  emit_defaults: set true to emit 0/false values (default is to omit them)
- */
-VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
-  VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
-  Descriptor* desc = ruby_to_Descriptor(descriptor);
-  VALUE msg_rb;
-  VALUE preserve_proto_fieldnames = Qfalse;
-  VALUE emit_defaults = Qfalse;
-  stringsink sink;
-
-  if (argc < 1 || argc > 2) {
-    rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
-  }
-
-  msg_rb = argv[0];
-
-  if (argc == 2) {
-    VALUE hash_args = argv[1];
-    if (TYPE(hash_args) != T_HASH) {
-      rb_raise(rb_eArgError, "Expected hash arguments.");
-    }
-    preserve_proto_fieldnames = rb_hash_lookup2(
-        hash_args, ID2SYM(rb_intern("preserve_proto_fieldnames")), Qfalse);
-
-    emit_defaults = rb_hash_lookup2(
-        hash_args, ID2SYM(rb_intern("emit_defaults")), Qfalse);
-  }
-
-  stringsink_init(&sink);
-
-  {
-    const upb_handlers* serialize_handlers =
-        msgdef_json_serialize_handlers(desc, RTEST(preserve_proto_fieldnames));
-    upb_json_printer* printer;
-    stackenv se;
-    VALUE ret;
-
-    stackenv_init(&se, "Error occurred during encoding: %" PRIsVALUE);
-    printer = upb_json_printer_create(se.arena, serialize_handlers, sink.sink);
-
-    putmsg(msg_rb, desc, upb_json_printer_input(printer), 0,
-           RTEST(emit_defaults), true, true);
-
-    ret = rb_enc_str_new(sink.ptr, sink.len, rb_utf8_encoding());
-
-    stackenv_uninit(&se);
-    stringsink_uninit(&sink);
-
-    return ret;
-  }
-}
-
-static void discard_unknown(VALUE msg_rb, const Descriptor* desc) {
-  MessageHeader* msg;
-  upb_msg_field_iter it;
-
-  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
-
-  {
-    stringsink* unknown = msg->unknown_fields;
-    if (unknown != NULL) {
-      stringsink_uninit(unknown);
-      msg->unknown_fields = NULL;
-    }
-  }
-
-  for (upb_msg_field_begin(&it, desc->msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    upb_fielddef *f = upb_msg_iter_field(&it);
-    const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(f);
-    uint32_t offset =
-        desc->layout->fields[upb_fielddef_index(f)].offset +
-        sizeof(MessageHeader);
-
-    if (oneof) {
-      uint32_t oneof_case =
-          slot_read_oneof_case(desc->layout, Message_data(msg), oneof);
-      // For a oneof, check that this field is actually present -- skip all the
-      // below if not.
-      if (oneof_case != upb_fielddef_number(f)) {
-        continue;
-      }
-      // Otherwise, fall through to the appropriate singular-field handler
-      // below.
-    }
-
-    if (!upb_fielddef_issubmsg(f)) {
-      continue;
-    }
-
-    if (is_map_field(f)) {
-      VALUE map;
-      Map_iter map_it;
-
-      if (!upb_fielddef_issubmsg(map_field_value(f))) continue;
-      map = DEREF(msg, offset, VALUE);
-      if (map == Qnil) continue;
-      for (Map_begin(map, &map_it); !Map_done(&map_it); Map_next(&map_it)) {
-        VALUE submsg = Map_iter_value(&map_it);
-        VALUE descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned);
-        const Descriptor* subdesc = ruby_to_Descriptor(descriptor);
-        discard_unknown(submsg, subdesc);
-      }
-    } else if (upb_fielddef_isseq(f)) {
-      VALUE ary = DEREF(msg, offset, VALUE);
-      int size;
-      int i;
-
-      if (ary == Qnil) continue;
-      size = NUM2INT(RepeatedField_length(ary));
-      for (i = 0; i < size; i++) {
-        void* memory = RepeatedField_index_native(ary, i);
-        VALUE submsg = *((VALUE *)memory);
-        VALUE descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned);
-        const Descriptor* subdesc = ruby_to_Descriptor(descriptor);
-        discard_unknown(submsg, subdesc);
-      }
-    } else {
-      VALUE submsg = DEREF(msg, offset, VALUE);
-      VALUE descriptor;
-      const Descriptor* subdesc;
-
-      if (submsg == Qnil) continue;
-      descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned);
-      subdesc = ruby_to_Descriptor(descriptor);
-      discard_unknown(submsg, subdesc);
-    }
-  }
-}
-
-/*
- * call-seq:
- *     Google::Protobuf.discard_unknown(msg)
- *
- * Discard unknown fields in the given message object and recursively discard
- * unknown fields in submessages.
- */
-VALUE Google_Protobuf_discard_unknown(VALUE self, VALUE msg_rb) {
-  VALUE klass = CLASS_OF(msg_rb);
-  VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
-  Descriptor* desc = ruby_to_Descriptor(descriptor);
-  if (klass == cRepeatedField || klass == cMap) {
-    rb_raise(rb_eArgError, "Expected proto msg for discard unknown.");
-  } else {
-    discard_unknown(msg_rb, desc);
-  }
-  return Qnil;
-}
diff --git a/ruby/ext/google/protobuf_c/extconf.rb b/ruby/ext/google/protobuf_c/extconf.rb
index 80b7985..ec17787 100755
--- a/ruby/ext/google/protobuf_c/extconf.rb
+++ b/ruby/ext/google/protobuf_c/extconf.rb
@@ -3,9 +3,9 @@
 require 'mkmf'
 
 if RUBY_PLATFORM =~ /darwin/ || RUBY_PLATFORM =~ /linux/
-  $CFLAGS += " -std=gnu90 -O3 -DNDEBUG -Wall -Wdeclaration-after-statement -Wsign-compare"
+  $CFLAGS += " -std=gnu99 -O3 -DNDEBUG -fvisibility=hidden -Wall -Wsign-compare -Wno-declaration-after-statement"
 else
-  $CFLAGS += " -std=gnu90 -O3 -DNDEBUG"
+  $CFLAGS += " -std=gnu99 -O3 -DNDEBUG"
 end
 
 
@@ -14,8 +14,7 @@
   $LDFLAGS += " -Wl,-wrap,memcpy"
 end
 
-$objs = ["protobuf.o", "defs.o", "storage.o", "message.o",
-         "repeated_field.o", "map.o", "encode_decode.o", "upb.o",
-         "wrap_memcpy.o"]
+$objs = ["protobuf.o", "convert.o", "defs.o", "message.o",
+         "repeated_field.o", "map.o", "ruby-upb.o", "wrap_memcpy.o"]
 
 create_makefile("google/protobuf_c")
diff --git a/ruby/ext/google/protobuf_c/map.c b/ruby/ext/google/protobuf_c/map.c
index 00d23a7..9d7d16b 100644
--- a/ruby/ext/google/protobuf_c/map.c
+++ b/ruby/ext/google/protobuf_c/map.c
@@ -28,170 +28,231 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#include "convert.h"
+#include "defs.h"
+#include "message.h"
 #include "protobuf.h"
 
 // -----------------------------------------------------------------------------
-// Basic map operations on top of upb's strtable.
+// Basic map operations on top of upb_map.
 //
 // Note that we roll our own `Map` container here because, as for
 // `RepeatedField`, we want a strongly-typed container. This is so that any user
 // errors due to incorrect map key or value types are raised as close as
 // possible to the error site, rather than at some deferred point (e.g.,
 // serialization).
-//
-// We build our `Map` on top of upb_strtable so that we're able to take
-// advantage of the native_slot storage abstraction, as RepeatedField does.
-// (This is not quite a perfect mapping -- see the key conversions below -- but
-// gives us full support and error-checking for all value types for free.)
 // -----------------------------------------------------------------------------
 
-// Map values are stored using the native_slot abstraction (as with repeated
-// field values), but keys are a bit special. Since we use a strtable, we need
-// to store keys as sequences of bytes such that equality of those bytes maps
-// one-to-one to equality of keys. We store strings directly (i.e., they map to
-// their own bytes) and integers as native integers (using the native_slot
-// abstraction).
-
-// Note that there is another tradeoff here in keeping string keys as native
-// strings rather than Ruby strings: traversing the Map requires conversion to
-// Ruby string values on every traversal, potentially creating more garbage. We
-// should consider ways to cache a Ruby version of the key if this becomes an
-// issue later.
-
-// Forms a key to use with the underlying strtable from a Ruby key value. |buf|
-// must point to TABLE_KEY_BUF_LENGTH bytes of temporary space, used to
-// construct a key byte sequence if needed. |out_key| and |out_length| provide
-// the resulting key data/length.
-#define TABLE_KEY_BUF_LENGTH 8  // sizeof(uint64_t)
-static VALUE table_key(Map* self, VALUE key,
-                       char* buf,
-                       const char** out_key,
-                       size_t* out_length) {
-  switch (self->key_type) {
-    case UPB_TYPE_BYTES:
-    case UPB_TYPE_STRING:
-      // Strings: use string content directly.
-      if (TYPE(key) == T_SYMBOL) {
-        key = rb_id2str(SYM2ID(key));
-      }
-      Check_Type(key, T_STRING);
-      key = native_slot_encode_and_freeze_string(self->key_type, key);
-      *out_key = RSTRING_PTR(key);
-      *out_length = RSTRING_LEN(key);
-      break;
-
-    case UPB_TYPE_BOOL:
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_UINT64:
-      native_slot_set("", self->key_type, Qnil, buf, key);
-      *out_key = buf;
-      *out_length = native_slot_size(self->key_type);
-      break;
-
-    default:
-      // Map constructor should not allow a Map with another key type to be
-      // constructed.
-      assert(false);
-      break;
-  }
-
-  return key;
-}
-
-static VALUE table_key_to_ruby(Map* self, upb_strview key) {
-  switch (self->key_type) {
-    case UPB_TYPE_BYTES:
-    case UPB_TYPE_STRING: {
-      VALUE ret = rb_str_new(key.data, key.size);
-      rb_enc_associate(ret,
-                       (self->key_type == UPB_TYPE_BYTES) ?
-                       kRubyString8bitEncoding : kRubyStringUtf8Encoding);
-      return ret;
-    }
-
-    case UPB_TYPE_BOOL:
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_UINT64:
-      return native_slot_get(self->key_type, Qnil, key.data);
-
-    default:
-      assert(false);
-      return Qnil;
-  }
-}
-
-static void* value_memory(upb_value* v) {
-  return (void*)(&v->val);
-}
-
 // -----------------------------------------------------------------------------
 // Map container type.
 // -----------------------------------------------------------------------------
 
+typedef struct {
+  const upb_map *map;  // Can convert to mutable when non-frozen.
+  upb_fieldtype_t key_type;
+  TypeInfo value_type_info;
+  VALUE value_type_class;
+  VALUE arena;
+} Map;
+
+static void Map_mark(void* _self) {
+  Map* self = _self;
+  rb_gc_mark(self->value_type_class);
+  rb_gc_mark(self->arena);
+}
+
 const rb_data_type_t Map_type = {
   "Google::Protobuf::Map",
-  { Map_mark, Map_free, NULL },
+  { Map_mark, RUBY_DEFAULT_FREE, NULL },
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
 };
 
 VALUE cMap;
 
-Map* ruby_to_Map(VALUE _self) {
+static Map* ruby_to_Map(VALUE _self) {
   Map* self;
   TypedData_Get_Struct(_self, Map, &Map_type, self);
   return self;
 }
 
-void Map_mark(void* _self) {
-  Map* self = _self;
-
-  rb_gc_mark(self->value_type_class);
-  rb_gc_mark(self->parse_frame);
-
-  if (self->value_type == UPB_TYPE_STRING ||
-      self->value_type == UPB_TYPE_BYTES ||
-      self->value_type == UPB_TYPE_MESSAGE) {
-    upb_strtable_iter it;
-    for (upb_strtable_begin(&it, &self->table);
-         !upb_strtable_done(&it);
-         upb_strtable_next(&it)) {
-      upb_value v = upb_strtable_iter_value(&it);
-      void* mem = value_memory(&v);
-      native_slot_mark(self->value_type, mem);
-    }
-  }
-}
-
-void Map_free(void* _self) {
-  Map* self = _self;
-  upb_strtable_uninit(&self->table);
-  xfree(self);
-}
-
-VALUE Map_alloc(VALUE klass) {
+static VALUE Map_alloc(VALUE klass) {
   Map* self = ALLOC(Map);
-  memset(self, 0, sizeof(Map));
+  self->map = NULL;
   self->value_type_class = Qnil;
+  self->value_type_info.def.msgdef = NULL;
+  self->arena = Qnil;
   return TypedData_Wrap_Struct(klass, &Map_type, self);
 }
 
-VALUE Map_set_frame(VALUE map, VALUE val) {
-  Map* self = ruby_to_Map(map);
-  self->parse_frame = val;
+VALUE Map_GetRubyWrapper(upb_map* map, upb_fieldtype_t key_type,
+                         TypeInfo value_type, VALUE arena) {
+  PBRUBY_ASSERT(map);
+
+  VALUE val = ObjectCache_Get(map);
+
+  if (val == Qnil) {
+    val = Map_alloc(cMap);
+    Map* self;
+    ObjectCache_Add(map, val, Arena_get(arena));
+    TypedData_Get_Struct(val, Map, &Map_type, self);
+    self->map = map;
+    self->arena = arena;
+    self->key_type = key_type;
+    self->value_type_info = value_type;
+    if (self->value_type_info.type == UPB_TYPE_MESSAGE) {
+      const upb_msgdef *val_m = self->value_type_info.def.msgdef;
+      self->value_type_class = Descriptor_DefToClass(val_m);
+    }
+  }
+
   return val;
 }
 
-static bool needs_typeclass(upb_fieldtype_t type) {
-  switch (type) {
-    case UPB_TYPE_MESSAGE:
-    case UPB_TYPE_ENUM:
-      return true;
-    default:
-      return false;
+static VALUE Map_new_this_type(Map *from) {
+  VALUE arena_rb = Arena_new();
+  upb_map* map = upb_map_new(Arena_get(arena_rb), from->key_type,
+                             from->value_type_info.type);
+  VALUE ret =
+      Map_GetRubyWrapper(map, from->key_type, from->value_type_info, arena_rb);
+  PBRUBY_ASSERT(ruby_to_Map(ret)->value_type_class == from->value_type_class);
+  return ret;
+}
+
+static TypeInfo Map_keyinfo(Map* self) {
+  TypeInfo ret;
+  ret.type = self->key_type;
+  ret.def.msgdef = NULL;
+  return ret;
+}
+
+static upb_map *Map_GetMutable(VALUE _self) {
+  rb_check_frozen(_self);
+  return (upb_map*)ruby_to_Map(_self)->map;
+}
+
+VALUE Map_CreateHash(const upb_map* map, upb_fieldtype_t key_type,
+                     TypeInfo val_info) {
+  VALUE hash = rb_hash_new();
+  size_t iter = UPB_MAP_BEGIN;
+  TypeInfo key_info = TypeInfo_from_type(key_type);
+
+  if (!map) return hash;
+
+  while (upb_mapiter_next(map, &iter)) {
+    upb_msgval key = upb_mapiter_key(map, iter);
+    upb_msgval val = upb_mapiter_value(map, iter);
+    VALUE key_val = Convert_UpbToRuby(key, key_info, Qnil);
+    VALUE val_val = Scalar_CreateHash(val, val_info);
+    rb_hash_aset(hash, key_val, val_val);
   }
+
+  return hash;
+}
+
+VALUE Map_deep_copy(VALUE obj) {
+  Map* self = ruby_to_Map(obj);
+  VALUE new_arena_rb = Arena_new();
+  upb_arena *arena = Arena_get(new_arena_rb);
+  upb_map* new_map =
+      upb_map_new(arena, self->key_type, self->value_type_info.type);
+  size_t iter = UPB_MAP_BEGIN;
+  while (upb_mapiter_next(self->map, &iter)) {
+    upb_msgval key = upb_mapiter_key(self->map, iter);
+    upb_msgval val = upb_mapiter_value(self->map, iter);
+    upb_msgval val_copy = Msgval_DeepCopy(val, self->value_type_info, arena);
+    upb_map_set(new_map, key, val_copy, arena);
+  }
+
+  return Map_GetRubyWrapper(new_map, self->key_type, self->value_type_info,
+                            new_arena_rb);
+}
+
+const upb_map* Map_GetUpbMap(VALUE val, const upb_fielddef *field) {
+  const upb_fielddef* key_field = map_field_key(field);
+  const upb_fielddef* value_field = map_field_value(field);
+  TypeInfo value_type_info = TypeInfo_get(value_field);
+  Map* self;
+
+  if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
+      RTYPEDDATA_TYPE(val) != &Map_type) {
+    rb_raise(cTypeError, "Expected Map instance");
+  }
+
+  self = ruby_to_Map(val);
+  if (self->key_type != upb_fielddef_type(key_field)) {
+    rb_raise(cTypeError, "Map key type does not match field's key type");
+  }
+  if (self->value_type_info.type != value_type_info.type) {
+    rb_raise(cTypeError, "Map value type does not match field's value type");
+  }
+  if (self->value_type_info.def.msgdef != value_type_info.def.msgdef) {
+    rb_raise(cTypeError, "Map value type has wrong message/enum class");
+  }
+
+  return self->map;
+}
+
+void Map_Inspect(StringBuilder* b, const upb_map* map, upb_fieldtype_t key_type,
+                 TypeInfo val_type) {
+  bool first = true;
+  TypeInfo key_type_info = {key_type};
+  StringBuilder_Printf(b, "{");
+  if (map) {
+    size_t iter = UPB_MAP_BEGIN;
+    while (upb_mapiter_next(map, &iter)) {
+      upb_msgval key = upb_mapiter_key(map, iter);
+      upb_msgval val = upb_mapiter_value(map, iter);
+      if (first) {
+        first = false;
+      } else {
+        StringBuilder_Printf(b, ", ");
+      }
+      StringBuilder_PrintMsgval(b, key, key_type_info);
+      StringBuilder_Printf(b, "=>");
+      StringBuilder_PrintMsgval(b, val, val_type);
+    }
+  }
+  StringBuilder_Printf(b, "}");
+}
+
+static int merge_into_self_callback(VALUE key, VALUE val, VALUE _self) {
+  Map* self = ruby_to_Map(_self);
+  upb_arena *arena = Arena_get(self->arena);
+  upb_msgval key_val = Convert_RubyToUpb(key, "", Map_keyinfo(self), arena);
+  upb_msgval val_val = Convert_RubyToUpb(val, "", self->value_type_info, arena);
+  upb_map_set(Map_GetMutable(_self), key_val, val_val, arena);
+  return ST_CONTINUE;
+}
+
+// Used only internally -- shared by #merge and #initialize.
+static VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
+  if (TYPE(hashmap) == T_HASH) {
+    rb_hash_foreach(hashmap, merge_into_self_callback, _self);
+  } else if (RB_TYPE_P(hashmap, T_DATA) && RTYPEDDATA_P(hashmap) &&
+             RTYPEDDATA_TYPE(hashmap) == &Map_type) {
+    Map* self = ruby_to_Map(_self);
+    Map* other = ruby_to_Map(hashmap);
+    upb_arena *arena = Arena_get(self->arena);
+    upb_msg *self_msg = Map_GetMutable(_self);
+    size_t iter = UPB_MAP_BEGIN;
+
+    upb_arena_fuse(arena, Arena_get(other->arena));
+
+    if (self->key_type != other->key_type ||
+        self->value_type_info.type != other->value_type_info.type ||
+        self->value_type_class != other->value_type_class) {
+      rb_raise(rb_eArgError, "Attempt to merge Map with mismatching types");
+    }
+
+    while (upb_mapiter_next(other->map, &iter)) {
+      upb_msgval key = upb_mapiter_key(other->map, iter);
+      upb_msgval val = upb_mapiter_value(other->map, iter);
+      upb_map_set(self_msg, key, val, arena);
+    }
+  } else {
+    rb_raise(rb_eArgError, "Unknown type merging into Map");
+  }
+  return _self;
 }
 
 /*
@@ -224,9 +285,9 @@
  * references to underlying objects will be shared if the value type is a
  * message type.
  */
-VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
+static VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
   Map* self = ruby_to_Map(_self);
-  int init_value_arg;
+  VALUE init_arg;
 
   // We take either two args (:key_type, :value_type), three args (:key_type,
   // :value_type, "ValueMessageType"), or four args (the above plus an initial
@@ -236,8 +297,9 @@
   }
 
   self->key_type = ruby_to_fieldtype(argv[0]);
-  self->value_type = ruby_to_fieldtype(argv[1]);
-  self->parse_frame = Qnil;
+  self->value_type_info =
+      TypeInfo_FromClass(argc, argv, 1, &self->value_type_class, &init_arg);
+  self->arena = Arena_new();
 
   // Check that the key type is an allowed type.
   switch (self->key_type) {
@@ -254,21 +316,12 @@
       rb_raise(rb_eArgError, "Invalid key type for map.");
   }
 
-  init_value_arg = 2;
-  if (needs_typeclass(self->value_type) && argc > 2) {
-    self->value_type_class = argv[2];
-    validate_type_class(self->value_type, self->value_type_class);
-    init_value_arg = 3;
-  }
+  self->map = upb_map_new(Arena_get(self->arena), self->key_type,
+                          self->value_type_info.type);
+  ObjectCache_Add(self->map, _self, Arena_get(self->arena));
 
-  // Table value type is always UINT64: this ensures enough space to store the
-  // native_slot value.
-  if (!upb_strtable_init(&self->table, UPB_CTYPE_UINT64)) {
-    rb_raise(rb_eRuntimeError, "Could not allocate table.");
-  }
-
-  if (argc > init_value_arg) {
-    Map_merge_into_self(_self, argv[init_value_arg]);
+  if (init_arg != Qnil) {
+    Map_merge_into_self(_self, init_arg);
   }
 
   return Qnil;
@@ -282,22 +335,16 @@
  * Note that Map also includes Enumerable; map thus acts like a normal Ruby
  * sequence.
  */
-VALUE Map_each(VALUE _self) {
+static VALUE Map_each(VALUE _self) {
   Map* self = ruby_to_Map(_self);
+  size_t iter = UPB_MAP_BEGIN;
 
-  upb_strtable_iter it;
-  for (upb_strtable_begin(&it, &self->table);
-       !upb_strtable_done(&it);
-       upb_strtable_next(&it)) {
-    VALUE key = table_key_to_ruby(self, upb_strtable_iter_key(&it));
-
-    upb_value v = upb_strtable_iter_value(&it);
-    void* mem = value_memory(&v);
-    VALUE value = native_slot_get(self->value_type,
-                                  self->value_type_class,
-                                  mem);
-
-    rb_yield_values(2, key, value);
+  while (upb_mapiter_next(self->map, &iter)) {
+    upb_msgval key = upb_mapiter_key(self->map, iter);
+    upb_msgval val = upb_mapiter_value(self->map, iter);
+    VALUE key_val = Convert_UpbToRuby(key, Map_keyinfo(self), self->arena);
+    VALUE val_val = Convert_UpbToRuby(val, self->value_type_info, self->arena);
+    rb_yield_values(2, key_val, val_val);
   }
 
   return Qnil;
@@ -309,17 +356,15 @@
  *
  * Returns the list of keys contained in the map, in unspecified order.
  */
-VALUE Map_keys(VALUE _self) {
+static VALUE Map_keys(VALUE _self) {
   Map* self = ruby_to_Map(_self);
-
+  size_t iter = UPB_MAP_BEGIN;
   VALUE ret = rb_ary_new();
-  upb_strtable_iter it;
-  for (upb_strtable_begin(&it, &self->table);
-       !upb_strtable_done(&it);
-       upb_strtable_next(&it)) {
-    VALUE key = table_key_to_ruby(self, upb_strtable_iter_key(&it));
 
-    rb_ary_push(ret, key);
+  while (upb_mapiter_next(self->map, &iter)) {
+    upb_msgval key = upb_mapiter_key(self->map, iter);
+    VALUE key_val = Convert_UpbToRuby(key, Map_keyinfo(self), self->arena);
+    rb_ary_push(ret, key_val);
   }
 
   return ret;
@@ -331,22 +376,15 @@
  *
  * Returns the list of values contained in the map, in unspecified order.
  */
-VALUE Map_values(VALUE _self) {
+static VALUE Map_values(VALUE _self) {
   Map* self = ruby_to_Map(_self);
-
+  size_t iter = UPB_MAP_BEGIN;
   VALUE ret = rb_ary_new();
-  upb_strtable_iter it;
-  for (upb_strtable_begin(&it, &self->table);
-       !upb_strtable_done(&it);
-       upb_strtable_next(&it)) {
 
-    upb_value v = upb_strtable_iter_value(&it);
-    void* mem = value_memory(&v);
-    VALUE value = native_slot_get(self->value_type,
-                                  self->value_type_class,
-                                  mem);
-
-    rb_ary_push(ret, value);
+  while (upb_mapiter_next(self->map, &iter)) {
+    upb_msgval val = upb_mapiter_value(self->map, iter);
+    VALUE val_val = Convert_UpbToRuby(val, self->value_type_info, self->arena);
+    rb_ary_push(ret, val_val);
   }
 
   return ret;
@@ -359,18 +397,13 @@
  * Accesses the element at the given key. Throws an exception if the key type is
  * incorrect. Returns nil when the key is not present in the map.
  */
-VALUE Map_index(VALUE _self, VALUE key) {
+static VALUE Map_index(VALUE _self, VALUE key) {
   Map* self = ruby_to_Map(_self);
+  upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
+  upb_msgval val;
 
-  char keybuf[TABLE_KEY_BUF_LENGTH];
-  const char* keyval = NULL;
-  size_t length = 0;
-  upb_value v;
-  key = table_key(self, key, keybuf, &keyval, &length);
-
-  if (upb_strtable_lookup2(&self->table, keyval, length, &v)) {
-    void* mem = value_memory(&v);
-    return native_slot_get(self->value_type, self->value_type_class, mem);
+  if (upb_map_get(self->map, key_upb, &val)) {
+    return Convert_UpbToRuby(val, self->value_type_info, self->arena);
   } else {
     return Qnil;
   }
@@ -384,33 +417,15 @@
  * Throws an exception if the key type is incorrect. Returns the new value that
  * was just inserted.
  */
-VALUE Map_index_set(VALUE _self, VALUE key, VALUE value) {
+static VALUE Map_index_set(VALUE _self, VALUE key, VALUE val) {
   Map* self = ruby_to_Map(_self);
-  char keybuf[TABLE_KEY_BUF_LENGTH];
-  const char* keyval = NULL;
-  size_t length = 0;
-  upb_value v;
-  void* mem;
-  key = table_key(self, key, keybuf, &keyval, &length);
+  upb_arena *arena = Arena_get(self->arena);
+  upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
+  upb_msgval val_upb = Convert_RubyToUpb(val, "", self->value_type_info, arena);
 
-  rb_check_frozen(_self);
+  upb_map_set(Map_GetMutable(_self), key_upb, val_upb, arena);
 
-  if (TYPE(value) == T_HASH) {
-    VALUE args[1] = { value };
-    value = rb_class_new_instance(1, args, self->value_type_class);
-  }
-
-  mem = value_memory(&v);
-  native_slot_set("", self->value_type, self->value_type_class, mem, value);
-
-  // Replace any existing value by issuing a 'remove' operation first.
-  upb_strtable_remove2(&self->table, keyval, length, NULL);
-  if (!upb_strtable_insert2(&self->table, keyval, length, v)) {
-    rb_raise(rb_eRuntimeError, "Could not insert into table");
-  }
-
-  // Ruby hashmap's :[]= method also returns the inserted value.
-  return value;
+  return val;
 }
 
 /*
@@ -420,15 +435,11 @@
  * Returns true if the given key is present in the map. Throws an exception if
  * the key has the wrong type.
  */
-VALUE Map_has_key(VALUE _self, VALUE key) {
+static VALUE Map_has_key(VALUE _self, VALUE key) {
   Map* self = ruby_to_Map(_self);
+  upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
 
-  char keybuf[TABLE_KEY_BUF_LENGTH];
-  const char* keyval = NULL;
-  size_t length = 0;
-  key = table_key(self, key, keybuf, &keyval, &length);
-
-  if (upb_strtable_lookup2(&self->table, keyval, length, NULL)) {
+  if (upb_map_get(self->map, key_upb, NULL)) {
     return Qtrue;
   } else {
     return Qfalse;
@@ -442,22 +453,25 @@
  * Deletes the value at the given key, if any, returning either the old value or
  * nil if none was present. Throws an exception if the key is of the wrong type.
  */
-VALUE Map_delete(VALUE _self, VALUE key) {
+static VALUE Map_delete(VALUE _self, VALUE key) {
   Map* self = ruby_to_Map(_self);
-  char keybuf[TABLE_KEY_BUF_LENGTH];
-  const char* keyval = NULL;
-  size_t length = 0;
-  upb_value v;
-  key = table_key(self, key, keybuf, &keyval, &length);
+  upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
+  upb_msgval val_upb;
+  VALUE ret;
 
   rb_check_frozen(_self);
 
-  if (upb_strtable_remove2(&self->table, keyval, length, &v)) {
-    void* mem = value_memory(&v);
-    return native_slot_get(self->value_type, self->value_type_class, mem);
+  // TODO(haberman): make upb_map_delete() also capable of returning the deleted
+  // value.
+  if (upb_map_get(self->map, key_upb, &val_upb)) {
+    ret = Convert_UpbToRuby(val_upb, self->value_type_info, self->arena);
   } else {
-    return Qnil;
+    ret = Qnil;
   }
+
+  upb_map_delete(Map_GetMutable(_self), key_upb);
+
+  return ret;
 }
 
 /*
@@ -466,17 +480,8 @@
  *
  * Removes all entries from the map.
  */
-VALUE Map_clear(VALUE _self) {
-  Map* self = ruby_to_Map(_self);
-
-  rb_check_frozen(_self);
-
-  // Uninit and reinit the table -- this is faster than iterating and doing a
-  // delete-lookup on each key.
-  upb_strtable_uninit(&self->table);
-  if (!upb_strtable_init(&self->table, UPB_CTYPE_INT64)) {
-    rb_raise(rb_eRuntimeError, "Unable to re-initialize table");
-  }
+static VALUE Map_clear(VALUE _self) {
+  upb_map_clear(Map_GetMutable(_self));
   return Qnil;
 }
 
@@ -486,24 +491,9 @@
  *
  * Returns the number of entries (key-value pairs) in the map.
  */
-VALUE Map_length(VALUE _self) {
+static VALUE Map_length(VALUE _self) {
   Map* self = ruby_to_Map(_self);
-  return ULL2NUM(upb_strtable_count(&self->table));
-}
-
-VALUE Map_new_this_type(VALUE _self) {
-  Map* self = ruby_to_Map(_self);
-  VALUE new_map = Qnil;
-  VALUE key_type = fieldtype_to_ruby(self->key_type);
-  VALUE value_type = fieldtype_to_ruby(self->value_type);
-  if (self->value_type_class != Qnil) {
-    new_map = rb_funcall(CLASS_OF(_self), rb_intern("new"), 3,
-                         key_type, value_type, self->value_type_class);
-  } else {
-    new_map = rb_funcall(CLASS_OF(_self), rb_intern("new"), 2,
-                         key_type, value_type);
-  }
-  return new_map;
+  return ULL2NUM(upb_map_size(self->map));
 }
 
 /*
@@ -513,54 +503,23 @@
  * Duplicates this map with a shallow copy. References to all non-primitive
  * element objects (e.g., submessages) are shared.
  */
-VALUE Map_dup(VALUE _self) {
+static VALUE Map_dup(VALUE _self) {
   Map* self = ruby_to_Map(_self);
-  VALUE new_map = Map_new_this_type(_self);
-  Map* new_self = ruby_to_Map(new_map);
+  VALUE new_map_rb = Map_new_this_type(self);
+  Map* new_self = ruby_to_Map(new_map_rb);
+  size_t iter = UPB_MAP_BEGIN;
+  upb_arena *arena = Arena_get(new_self->arena);
+  upb_map *new_map = Map_GetMutable(new_map_rb);
 
-  upb_strtable_iter it;
-  for (upb_strtable_begin(&it, &self->table);
-       !upb_strtable_done(&it);
-       upb_strtable_next(&it)) {
-    upb_strview k = upb_strtable_iter_key(&it);
-    upb_value v = upb_strtable_iter_value(&it);
-    void* mem = value_memory(&v);
-    upb_value dup;
-    void* dup_mem = value_memory(&dup);
-    native_slot_dup(self->value_type, dup_mem, mem);
+  upb_arena_fuse(arena, Arena_get(self->arena));
 
-    if (!upb_strtable_insert2(&new_self->table, k.data, k.size, dup)) {
-      rb_raise(rb_eRuntimeError, "Error inserting value into new table");
-    }
+  while (upb_mapiter_next(self->map, &iter)) {
+    upb_msgval key = upb_mapiter_key(self->map, iter);
+    upb_msgval val = upb_mapiter_value(self->map, iter);
+    upb_map_set(new_map, key, val, arena);
   }
 
-  return new_map;
-}
-
-// Used by Google::Protobuf.deep_copy but not exposed directly.
-VALUE Map_deep_copy(VALUE _self) {
-  Map* self = ruby_to_Map(_self);
-  VALUE new_map = Map_new_this_type(_self);
-  Map* new_self = ruby_to_Map(new_map);
-
-  upb_strtable_iter it;
-  for (upb_strtable_begin(&it, &self->table);
-       !upb_strtable_done(&it);
-       upb_strtable_next(&it)) {
-    upb_strview k = upb_strtable_iter_key(&it);
-    upb_value v = upb_strtable_iter_value(&it);
-    void* mem = value_memory(&v);
-    upb_value dup;
-    void* dup_mem = value_memory(&dup);
-    native_slot_deep_copy(self->value_type, self->value_type_class, dup_mem,
-                          mem);
-
-    if (!upb_strtable_insert2(&new_self->table, k.data, k.size, dup)) {
-      rb_raise(rb_eRuntimeError, "Error inserting value into new table");
-    }
-  }
-
-  return new_map;
+  return new_map_rb;
 }
 
 /*
@@ -579,12 +538,11 @@
 VALUE Map_eq(VALUE _self, VALUE _other) {
   Map* self = ruby_to_Map(_self);
   Map* other;
-  upb_strtable_iter it;
 
   // Allow comparisons to Ruby hashmaps by converting to a temporary Map
   // instance. Slow, but workable.
   if (TYPE(_other) == T_HASH) {
-    VALUE other_map = Map_new_this_type(_self);
+    VALUE other_map = Map_new_this_type(self);
     Map_merge_into_self(other_map, _other);
     _other = other_map;
   }
@@ -595,33 +553,27 @@
     return Qtrue;
   }
   if (self->key_type != other->key_type ||
-      self->value_type != other->value_type ||
+      self->value_type_info.type != other->value_type_info.type ||
       self->value_type_class != other->value_type_class) {
     return Qfalse;
   }
-  if (upb_strtable_count(&self->table) != upb_strtable_count(&other->table)) {
+  if (upb_map_size(self->map) != upb_map_size(other->map)) {
     return Qfalse;
   }
 
   // For each member of self, check that an equal member exists at the same key
   // in other.
-  for (upb_strtable_begin(&it, &self->table);
-       !upb_strtable_done(&it);
-       upb_strtable_next(&it)) {
-    upb_strview k = upb_strtable_iter_key(&it);
-    upb_value v = upb_strtable_iter_value(&it);
-    void* mem = value_memory(&v);
-    upb_value other_v;
-    void* other_mem = value_memory(&other_v);
-
-    if (!upb_strtable_lookup2(&other->table, k.data, k.size, &other_v)) {
+  size_t iter = UPB_MAP_BEGIN;
+  while (upb_mapiter_next(self->map, &iter)) {
+    upb_msgval key = upb_mapiter_key(self->map, iter);
+    upb_msgval val = upb_mapiter_value(self->map, iter);
+    upb_msgval other_val;
+    if (!upb_map_get(other->map, key, &other_val)) {
       // Not present in other map.
       return Qfalse;
     }
-
-    if (!native_slot_eq(self->value_type, self->value_type_class, mem,
-                        other_mem)) {
-      // Present, but value not equal.
+    if (!Msgval_IsEqual(val, other_val, self->value_type_info)) {
+      // Present but different value.
       return Qfalse;
     }
   }
@@ -631,32 +583,39 @@
 
 /*
  * call-seq:
+ *     Message.freeze => self
+ *
+ * Freezes the message object. We have to intercept this so we can pin the
+ * Ruby object into memory so we don't forget it's frozen.
+ */
+static VALUE Map_freeze(VALUE _self) {
+  Map* self = ruby_to_Map(_self);
+
+  ObjectCache_Pin(self->map, _self, Arena_get(self->arena));
+  RB_OBJ_FREEZE(_self);
+  return _self;
+}
+
+/*
+ * call-seq:
  *     Map.hash => hash_value
  *
  * Returns a hash value based on this map's contents.
  */
 VALUE Map_hash(VALUE _self) {
   Map* self = ruby_to_Map(_self);
+  uint64_t hash = 0;
 
-  st_index_t h = rb_hash_start(0);
-  VALUE hash_sym = rb_intern("hash");
-
-  upb_strtable_iter it;
-  for (upb_strtable_begin(&it, &self->table); !upb_strtable_done(&it);
-       upb_strtable_next(&it)) {
-    VALUE key = table_key_to_ruby(self, upb_strtable_iter_key(&it));
-
-    upb_value v = upb_strtable_iter_value(&it);
-    void* mem = value_memory(&v);
-    VALUE value = native_slot_get(self->value_type,
-                                  self->value_type_class,
-                                  mem);
-
-    h = rb_hash_uint(h, NUM2LONG(rb_funcall(key, hash_sym, 0)));
-    h = rb_hash_uint(h, NUM2LONG(rb_funcall(value, hash_sym, 0)));
+  size_t iter = UPB_MAP_BEGIN;
+  TypeInfo key_info = {self->key_type};
+  while (upb_mapiter_next(self->map, &iter)) {
+    upb_msgval key = upb_mapiter_key(self->map, iter);
+    upb_msgval val = upb_mapiter_value(self->map, iter);
+    hash = Msgval_GetHash(key, key_info, hash);
+    hash = Msgval_GetHash(val, self->value_type_info, hash);
   }
 
-  return INT2FIX(h);
+  return LL2NUM(hash);
 }
 
 /*
@@ -667,24 +626,7 @@
  */
 VALUE Map_to_h(VALUE _self) {
   Map* self = ruby_to_Map(_self);
-  VALUE hash = rb_hash_new();
-  upb_strtable_iter it;
-  for (upb_strtable_begin(&it, &self->table);
-       !upb_strtable_done(&it);
-       upb_strtable_next(&it)) {
-    VALUE key = table_key_to_ruby(self, upb_strtable_iter_key(&it));
-    upb_value v = upb_strtable_iter_value(&it);
-    void* mem = value_memory(&v);
-    VALUE value = native_slot_get(self->value_type,
-                                  self->value_type_class,
-                                  mem);
-
-    if (self->value_type == UPB_TYPE_MESSAGE) {
-      value = Message_to_h(value);
-    }
-    rb_hash_aset(hash, key, value);
-  }
-  return hash;
+  return Map_CreateHash(self->map, self->key_type, self->value_type_info);
 }
 
 /*
@@ -698,34 +640,11 @@
 VALUE Map_inspect(VALUE _self) {
   Map* self = ruby_to_Map(_self);
 
-  VALUE str = rb_str_new2("{");
-
-  bool first = true;
-  VALUE inspect_sym = rb_intern("inspect");
-
-  upb_strtable_iter it;
-  for (upb_strtable_begin(&it, &self->table); !upb_strtable_done(&it);
-       upb_strtable_next(&it)) {
-    VALUE key = table_key_to_ruby(self, upb_strtable_iter_key(&it));
-
-    upb_value v = upb_strtable_iter_value(&it);
-    void* mem = value_memory(&v);
-    VALUE value = native_slot_get(self->value_type,
-                                  self->value_type_class,
-                                  mem);
-
-    if (!first) {
-      str = rb_str_cat2(str, ", ");
-    } else {
-      first = false;
-    }
-    str = rb_str_append(str, rb_funcall(key, inspect_sym, 0));
-    str = rb_str_cat2(str, "=>");
-    str = rb_str_append(str, rb_funcall(value, inspect_sym, 0));
-  }
-
-  str = rb_str_cat2(str, "}");
-  return str;
+  StringBuilder* builder = StringBuilder_New();
+  Map_Inspect(builder, self->map, self->key_type, self->value_type_info);
+  VALUE ret = StringBuilder_ToRubyString(builder);
+  StringBuilder_Free(builder);
+  return ret;
 }
 
 /*
@@ -737,79 +656,11 @@
  * in the new copy of this map. Returns the new copy of this map with merged
  * contents.
  */
-VALUE Map_merge(VALUE _self, VALUE hashmap) {
+static VALUE Map_merge(VALUE _self, VALUE hashmap) {
   VALUE dupped = Map_dup(_self);
   return Map_merge_into_self(dupped, hashmap);
 }
 
-static int merge_into_self_callback(VALUE key, VALUE value, VALUE self) {
-  Map_index_set(self, key, value);
-  return ST_CONTINUE;
-}
-
-// Used only internally -- shared by #merge and #initialize.
-VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
-  if (TYPE(hashmap) == T_HASH) {
-    rb_hash_foreach(hashmap, merge_into_self_callback, _self);
-  } else if (RB_TYPE_P(hashmap, T_DATA) && RTYPEDDATA_P(hashmap) &&
-             RTYPEDDATA_TYPE(hashmap) == &Map_type) {
-
-    Map* self = ruby_to_Map(_self);
-    Map* other = ruby_to_Map(hashmap);
-    upb_strtable_iter it;
-
-    if (self->key_type != other->key_type ||
-        self->value_type != other->value_type ||
-        self->value_type_class != other->value_type_class) {
-      rb_raise(rb_eArgError, "Attempt to merge Map with mismatching types");
-    }
-
-    for (upb_strtable_begin(&it, &other->table);
-         !upb_strtable_done(&it);
-         upb_strtable_next(&it)) {
-      upb_strview k = upb_strtable_iter_key(&it);
-
-      // Replace any existing value by issuing a 'remove' operation first.
-      upb_value v;
-      upb_value oldv;
-      upb_strtable_remove2(&self->table, k.data, k.size, &oldv);
-
-      v = upb_strtable_iter_value(&it);
-      upb_strtable_insert2(&self->table, k.data, k.size, v);
-    }
-  } else {
-    rb_raise(rb_eArgError, "Unknown type merging into Map");
-  }
-  return _self;
-}
-
-// Internal method: map iterator initialization (used for serialization).
-void Map_begin(VALUE _self, Map_iter* iter) {
-  Map* self = ruby_to_Map(_self);
-  iter->self = self;
-  upb_strtable_begin(&iter->it, &self->table);
-}
-
-void Map_next(Map_iter* iter) {
-  upb_strtable_next(&iter->it);
-}
-
-bool Map_done(Map_iter* iter) {
-  return upb_strtable_done(&iter->it);
-}
-
-VALUE Map_iter_key(Map_iter* iter) {
-  return table_key_to_ruby(iter->self, upb_strtable_iter_key(&iter->it));
-}
-
-VALUE Map_iter_value(Map_iter* iter) {
-  upb_value v = upb_strtable_iter_value(&iter->it);
-  void* mem = value_memory(&v);
-  return native_slot_get(iter->self->value_type,
-                         iter->self->value_type_class,
-                         mem);
-}
-
 void Map_register(VALUE module) {
   VALUE klass = rb_define_class_under(module, "Map", rb_cObject);
   rb_define_alloc_func(klass, Map_alloc);
@@ -828,6 +679,7 @@
   rb_define_method(klass, "length", Map_length, 0);
   rb_define_method(klass, "dup", Map_dup, 0);
   rb_define_method(klass, "==", Map_eq, 1);
+  rb_define_method(klass, "freeze", Map_freeze, 0);
   rb_define_method(klass, "hash", Map_hash, 0);
   rb_define_method(klass, "to_h", Map_to_h, 0);
   rb_define_method(klass, "inspect", Map_inspect, 0);
diff --git a/ruby/ext/google/protobuf_c/map.h b/ruby/ext/google/protobuf_c/map.h
new file mode 100644
index 0000000..1b840c3
--- /dev/null
+++ b/ruby/ext/google/protobuf_c/map.h
@@ -0,0 +1,66 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef RUBY_PROTOBUF_MAP_H_
+#define RUBY_PROTOBUF_MAP_H_
+
+#include <ruby/ruby.h>
+
+#include "protobuf.h"
+#include "ruby-upb.h"
+
+// Returns a Ruby wrapper object for the given map, which will be created if
+// one does not exist already.
+VALUE Map_GetRubyWrapper(upb_map *map, upb_fieldtype_t key_type,
+                         TypeInfo value_type, VALUE arena);
+
+// Gets the underlying upb_map for this Ruby map object, which must have
+// key/value type that match |field|. If this is not a map or the type doesn't
+// match, raises an exception.
+const upb_map *Map_GetUpbMap(VALUE val, const upb_fielddef *field);
+
+// Implements #inspect for this map by appending its contents to |b|.
+void Map_Inspect(StringBuilder *b, const upb_map *map, upb_fieldtype_t key_type,
+                 TypeInfo val_type);
+
+// Returns a new Hash object containing the contents of this Map.
+VALUE Map_CreateHash(const upb_map* map, upb_fieldtype_t key_type,
+                     TypeInfo val_info);
+
+// Returns a deep copy of this Map object.
+VALUE Map_deep_copy(VALUE obj);
+
+// Ruby class of Google::Protobuf::Map.
+extern VALUE cMap;
+
+// Call at startup to register all types in this module.
+void Map_register(VALUE module);
+
+#endif  // RUBY_PROTOBUF_MAP_H_
diff --git a/ruby/ext/google/protobuf_c/message.c b/ruby/ext/google/protobuf_c/message.c
index 0050506..22a21c1 100644
--- a/ruby/ext/google/protobuf_c/message.c
+++ b/ruby/ext/google/protobuf_c/message.c
@@ -28,49 +28,61 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#include "message.h"
+
+#include "convert.h"
+#include "defs.h"
+#include "map.h"
 #include "protobuf.h"
+#include "repeated_field.h"
+#include "third_party/wyhash/wyhash.h"
+
+static VALUE cParseError = Qnil;
+static ID descriptor_instancevar_interned;
+
+static VALUE initialize_rb_class_with_no_args(VALUE klass) {
+    return rb_funcall(klass, rb_intern("new"), 0);
+}
+
+VALUE MessageOrEnum_GetDescriptor(VALUE klass) {
+  return rb_ivar_get(klass, descriptor_instancevar_interned);
+}
 
 // -----------------------------------------------------------------------------
 // Class/module creation from msgdefs and enumdefs, respectively.
 // -----------------------------------------------------------------------------
 
-void* Message_data(void* msg) {
-  return ((uint8_t *)msg) + sizeof(MessageHeader);
+typedef struct {
+  VALUE arena;
+  const upb_msg* msg;        // Can get as mutable when non-frozen.
+  const upb_msgdef* msgdef;  // kept alive by self.class.descriptor reference.
+} Message;
+
+static void Message_mark(void* _self) {
+  Message* self = (Message *)_self;
+  rb_gc_mark(self->arena);
 }
 
-void Message_mark(void* _self) {
-  MessageHeader* self = (MessageHeader *)_self;
-  layout_mark(self->descriptor->layout, Message_data(self));
-}
-
-void Message_free(void* self) {
-  stringsink* unknown = ((MessageHeader *)self)->unknown_fields;
-  if (unknown != NULL) {
-    stringsink_uninit(unknown);
-    free(unknown);
-  }
-  xfree(self);
-}
-
-rb_data_type_t Message_type = {
+static rb_data_type_t Message_type = {
   "Message",
-  { Message_mark, Message_free, NULL },
+  { Message_mark, RUBY_DEFAULT_FREE, NULL },
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
 };
 
-VALUE Message_alloc(VALUE klass) {
+static Message* ruby_to_Message(VALUE msg_rb) {
+  Message* msg;
+  TypedData_Get_Struct(msg_rb, Message, &Message_type, msg);
+  return msg;
+}
+
+static VALUE Message_alloc(VALUE klass) {
   VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
-  Descriptor* desc = ruby_to_Descriptor(descriptor);
-  MessageHeader* msg;
+  Message* msg = ALLOC(Message);
   VALUE ret;
 
-  if (desc->layout == NULL) {
-    create_layout(desc);
-  }
-
-  msg = (void*)ALLOC_N(uint8_t, sizeof(MessageHeader) + desc->layout->size);
-  msg->descriptor = desc;
-  msg->unknown_fields = NULL;
-  memcpy(Message_data(msg), desc->layout->empty_template, desc->layout->size);
+  msg->msgdef = Descriptor_GetMsgDef(descriptor);
+  msg->arena = Qnil;
+  msg->msg = NULL;
 
   ret = TypedData_Wrap_Struct(klass, &Message_type, msg);
   rb_ivar_set(ret, descriptor_instancevar_interned, descriptor);
@@ -78,24 +90,92 @@
   return ret;
 }
 
-static const upb_fielddef* which_oneof_field(MessageHeader* self, const upb_oneofdef* o) {
-  uint32_t oneof_case;
-  const upb_fielddef* f;
+const upb_msg *Message_Get(VALUE msg_rb, const upb_msgdef **m) {
+  Message* msg = ruby_to_Message(msg_rb);
+  if (m) *m = msg->msgdef;
+  return msg->msg;
+}
 
-  oneof_case =
-      slot_read_oneof_case(self->descriptor->layout, Message_data(self), o);
+upb_msg *Message_GetMutable(VALUE msg_rb, const upb_msgdef **m) {
+  rb_check_frozen(msg_rb);
+  return (upb_msg*)Message_Get(msg_rb, m);
+}
 
-  if (oneof_case == ONEOF_CASE_NONE) {
-    return NULL;
+void Message_InitPtr(VALUE self_, upb_msg *msg, VALUE arena) {
+  Message* self = ruby_to_Message(self_);
+  self->msg = msg;
+  self->arena = arena;
+  ObjectCache_Add(msg, self_, Arena_get(arena));
+}
+
+VALUE Message_GetArena(VALUE msg_rb) {
+  Message* msg = ruby_to_Message(msg_rb);
+  return msg->arena;
+}
+
+void Message_CheckClass(VALUE klass) {
+  if (rb_get_alloc_func(klass) != &Message_alloc) {
+    rb_raise(rb_eArgError,
+             "Message class was not returned by the DescriptorPool.");
+  }
+}
+
+VALUE Message_GetRubyWrapper(upb_msg* msg, const upb_msgdef* m, VALUE arena) {
+  if (msg == NULL) return Qnil;
+
+  VALUE val = ObjectCache_Get(msg);
+
+  if (val == Qnil) {
+    VALUE klass = Descriptor_DefToClass(m);
+    val = Message_alloc(klass);
+    Message_InitPtr(val, msg, arena);
   }
 
-  // oneof_case is a field index, so find that field.
-  f = upb_oneofdef_itof(o, oneof_case);
-  assert(f != NULL);
-
-  return f;
+  return val;
 }
 
+void Message_PrintMessage(StringBuilder* b, const upb_msg* msg,
+                          const upb_msgdef* m) {
+  bool first = true;
+  int n = upb_msgdef_fieldcount(m);
+  VALUE klass = Descriptor_DefToClass(m);
+  StringBuilder_Printf(b, "<%s: ", rb_class2name(klass));
+
+  for (int i = 0; i < n; i++) {
+    const upb_fielddef* field = upb_msgdef_field(m, i);
+
+    if (upb_fielddef_haspresence(field) && !upb_msg_has(msg, field)) {
+      continue;
+    }
+
+    if (!first) {
+      StringBuilder_Printf(b, ", ");
+    } else {
+      first = false;
+    }
+
+    upb_msgval msgval = upb_msg_get(msg, field);
+
+    StringBuilder_Printf(b, "%s: ", upb_fielddef_name(field));
+
+    if (upb_fielddef_ismap(field)) {
+      const upb_msgdef* entry_m = upb_fielddef_msgsubdef(field);
+      const upb_fielddef* key_f = upb_msgdef_itof(entry_m, 1);
+      const upb_fielddef* val_f = upb_msgdef_itof(entry_m, 2);
+      TypeInfo val_info = TypeInfo_get(val_f);
+      Map_Inspect(b, msgval.map_val, upb_fielddef_type(key_f), val_info);
+    } else if (upb_fielddef_isseq(field)) {
+      RepeatedField_Inspect(b, msgval.array_val, TypeInfo_get(field));
+    } else {
+      StringBuilder_PrintMsgval(b, msgval, TypeInfo_get(field));
+    }
+  }
+
+  StringBuilder_Printf(b, ">");
+}
+
+// Helper functions for #method_missing ////////////////////////////////////////
+
 enum {
   METHOD_UNKNOWN = 0,
   METHOD_GETTER = 1,
@@ -108,153 +188,199 @@
 };
 
 // Check if the field is a well known wrapper type
-bool is_wrapper_type_field(const upb_fielddef* field) {
-  const upb_msgdef *m;
-  if (upb_fielddef_type(field) != UPB_TYPE_MESSAGE) {
+static bool IsWrapper(const upb_fielddef* f) {
+  return upb_fielddef_issubmsg(f) &&
+         upb_msgdef_iswrapper(upb_fielddef_msgsubdef(f));
+}
+
+static bool Match(const upb_msgdef* m, const char* name, const upb_fielddef** f,
+                  const upb_oneofdef** o, const char* prefix,
+                  const char* suffix) {
+  size_t sp = strlen(prefix);
+  size_t ss = strlen(suffix);
+  size_t sn = strlen(name);
+
+  if (sn <= sp + ss) return false;
+
+  if (memcmp(name, prefix, sp) != 0 ||
+      memcmp(name + sn - ss, suffix, ss) != 0) {
     return false;
   }
-  m = upb_fielddef_msgsubdef(field);
-  switch (upb_msgdef_wellknowntype(m)) {
-    case UPB_WELLKNOWN_DOUBLEVALUE:
-    case UPB_WELLKNOWN_FLOATVALUE:
-    case UPB_WELLKNOWN_INT64VALUE:
-    case UPB_WELLKNOWN_UINT64VALUE:
-    case UPB_WELLKNOWN_INT32VALUE:
-    case UPB_WELLKNOWN_UINT32VALUE:
-    case UPB_WELLKNOWN_STRINGVALUE:
-    case UPB_WELLKNOWN_BYTESVALUE:
-    case UPB_WELLKNOWN_BOOLVALUE:
-      return true;
-    default:
-      return false;
-  }
+
+  return upb_msgdef_lookupname(m, name + sp, sn - sp - ss, f, o);
 }
 
-// Get a new Ruby wrapper type and set the initial value
-VALUE ruby_wrapper_type(VALUE type_class, VALUE value) {
-  if (value != Qnil) {
-    VALUE hash = rb_hash_new();
-    rb_hash_aset(hash, rb_str_new2("value"), value);
-    {
-      VALUE args[1] = {hash};
-      return rb_class_new_instance(1, args, type_class);
-    }
-  }
-  return Qnil;
-}
-
-static int extract_method_call(VALUE method_name, MessageHeader* self,
-                            const upb_fielddef **f, const upb_oneofdef **o) {
-  VALUE method_str;
-  char* name;
-  size_t name_len;
-  int accessor_type;
-  const upb_oneofdef* test_o;
-  const upb_fielddef* test_f;
-  bool has_field;
+static int extract_method_call(VALUE method_name, Message* self,
+                               const upb_fielddef** f, const upb_oneofdef** o) {
+  const upb_msgdef* m = self->msgdef;
+  const char* name;
 
   Check_Type(method_name, T_SYMBOL);
+  name = rb_id2name(SYM2ID(method_name));
 
-  method_str = rb_id2str(SYM2ID(method_name));
-  name = RSTRING_PTR(method_str);
-  name_len = RSTRING_LEN(method_str);
-
-  if (name[name_len - 1] == '=') {
-    accessor_type = METHOD_SETTER;
-    name_len--;
-    // We want to ensure if the proto has something named clear_foo or has_foo?,
-    // we don't strip the prefix.
-  } else if (strncmp("clear_", name, 6) == 0 &&
-             !upb_msgdef_lookupname(self->descriptor->msgdef, name, name_len,
-                                    &test_f, &test_o)) {
-    accessor_type = METHOD_CLEAR;
-    name = name + 6;
-    name_len = name_len - 6;
-  } else if (strncmp("has_", name, 4) == 0 && name[name_len - 1] == '?' &&
-             !upb_msgdef_lookupname(self->descriptor->msgdef, name, name_len,
-                                    &test_f, &test_o)) {
-    accessor_type = METHOD_PRESENCE;
-    name = name + 4;
-    name_len = name_len - 5;
-  } else {
-    accessor_type = METHOD_GETTER;
-  }
-
-  has_field = upb_msgdef_lookupname(self->descriptor->msgdef, name, name_len,
-                                    &test_f, &test_o);
-
-  // Look for wrapper type accessor of the form <field_name>_as_value
-  if (!has_field &&
-      (accessor_type == METHOD_GETTER || accessor_type == METHOD_SETTER) &&
-      name_len > 9 && strncmp(name + name_len - 9, "_as_value", 9) == 0) {
-    const upb_oneofdef* test_o_wrapper;
-    const upb_fielddef* test_f_wrapper;
-    char wrapper_field_name[name_len - 8];
-
-    // Find the field name
-    strncpy(wrapper_field_name, name, name_len - 9);
-    wrapper_field_name[name_len - 9] = '\0';
-
-    // Check if field exists and is a wrapper type
-    if (upb_msgdef_lookupname(self->descriptor->msgdef, wrapper_field_name,
-                              name_len - 9, &test_f_wrapper, &test_o_wrapper) &&
-        is_wrapper_type_field(test_f_wrapper)) {
-      // It does exist!
-      has_field = true;
-      if (accessor_type == METHOD_SETTER) {
-        accessor_type = METHOD_WRAPPER_SETTER;
-      } else {
-        accessor_type = METHOD_WRAPPER_GETTER;
-      }
-      test_o = test_o_wrapper;
-      test_f = test_f_wrapper;
-    }
-  }
-
-  // Look for enum accessor of the form <enum_name>_const
-  if (!has_field && accessor_type == METHOD_GETTER &&
-      name_len > 6 && strncmp(name + name_len - 6, "_const", 6) == 0) {
-    const upb_oneofdef* test_o_enum;
-    const upb_fielddef* test_f_enum;
-    char enum_name[name_len - 5];
-
-    // Find enum field name
-    strncpy(enum_name, name, name_len - 6);
-    enum_name[name_len - 6] = '\0';
-
-    // Check if enum field exists
-    if (upb_msgdef_lookupname(self->descriptor->msgdef, enum_name, name_len - 6,
-                                             &test_f_enum, &test_o_enum) &&
-        upb_fielddef_type(test_f_enum) == UPB_TYPE_ENUM) {
-      // It does exist!
-      has_field = true;
-      accessor_type = METHOD_ENUM_GETTER;
-      test_o = test_o_enum;
-      test_f = test_f_enum;
-    }
-  }
-
-  // Verify the name corresponds to a oneof or field in this message.
-  if (!has_field) {
-    return METHOD_UNKNOWN;
-  }
-
-  // Method calls like 'has_foo?' are not allowed if field "foo" does not have
-  // a hasbit (e.g. repeated fields or non-message type fields for proto3
-  // syntax).
-  if (accessor_type == METHOD_PRESENCE && test_f != NULL) {
-    if (!upb_fielddef_haspresence(test_f)) return METHOD_UNKNOWN;
-
-    // TODO(haberman): remove this case, allow for proto3 oneofs.
-    if (upb_fielddef_realcontainingoneof(test_f) &&
-        upb_filedef_syntax(upb_fielddef_file(test_f)) == UPB_SYNTAX_PROTO3) {
+  if (Match(m, name, f, o, "", "")) return METHOD_GETTER;
+  if (Match(m, name, f, o, "", "=")) return METHOD_SETTER;
+  if (Match(m, name, f, o, "clear_", "")) return METHOD_CLEAR;
+  if (Match(m, name, f, o, "has_", "?") &&
+      (*o || (*f && upb_fielddef_haspresence(*f)))) {
+    // Disallow oneof hazzers for proto3.
+    // TODO(haberman): remove this test when we are enabling oneof hazzers for
+    // proto3.
+    if (*f && !upb_fielddef_issubmsg(*f) &&
+        upb_fielddef_realcontainingoneof(*f) &&
+        upb_msgdef_syntax(upb_fielddef_containingtype(*f)) !=
+            UPB_SYNTAX_PROTO2) {
       return METHOD_UNKNOWN;
     }
+    return METHOD_PRESENCE;
+  }
+  if (Match(m, name, f, o, "", "_as_value") && *f && !upb_fielddef_isseq(*f) &&
+      IsWrapper(*f)) {
+    return METHOD_WRAPPER_GETTER;
+  }
+  if (Match(m, name, f, o, "", "_as_value=") && *f && !upb_fielddef_isseq(*f) &&
+      IsWrapper(*f)) {
+    return METHOD_WRAPPER_SETTER;
+  }
+  if (Match(m, name, f, o, "", "_const") && *f &&
+      upb_fielddef_type(*f) == UPB_TYPE_ENUM) {
+    return METHOD_ENUM_GETTER;
   }
 
-  *o = test_o;
-  *f = test_f;
-  return accessor_type;
+  return METHOD_UNKNOWN;
+}
+
+static VALUE Message_oneof_accessor(VALUE _self, const upb_oneofdef* o,
+                                    int accessor_type) {
+  Message* self = ruby_to_Message(_self);
+  const upb_fielddef* oneof_field = upb_msg_whichoneof(self->msg, o);
+
+  switch (accessor_type) {
+    case METHOD_PRESENCE:
+      return oneof_field == NULL ? Qfalse : Qtrue;
+    case METHOD_CLEAR:
+      if (oneof_field != NULL) {
+        upb_msg_clearfield(Message_GetMutable(_self, NULL), oneof_field);
+      }
+      return Qnil;
+    case METHOD_GETTER:
+      return oneof_field == NULL
+                 ? Qnil
+                 : ID2SYM(rb_intern(upb_fielddef_name(oneof_field)));
+    case METHOD_SETTER:
+      rb_raise(rb_eRuntimeError, "Oneof accessors are read-only.");
+  }
+  rb_raise(rb_eRuntimeError, "Invalid access of oneof field.");
+}
+
+static void Message_setfield(upb_msg* msg, const upb_fielddef* f, VALUE val,
+                             upb_arena* arena) {
+  upb_msgval msgval;
+  if (upb_fielddef_ismap(f)) {
+    msgval.map_val = Map_GetUpbMap(val, f);
+  } else if (upb_fielddef_isseq(f)) {
+    msgval.array_val = RepeatedField_GetUpbArray(val, f);
+  } else {
+    if (val == Qnil &&
+        (upb_fielddef_issubmsg(f) || upb_fielddef_realcontainingoneof(f))) {
+      upb_msg_clearfield(msg, f);
+      return;
+    }
+    msgval =
+        Convert_RubyToUpb(val, upb_fielddef_name(f), TypeInfo_get(f), arena);
+  }
+  upb_msg_set(msg, f, msgval, arena);
+}
+
+static VALUE Message_field_accessor(VALUE _self, const upb_fielddef* f,
+                                    int accessor_type, int argc, VALUE* argv) {
+  upb_arena *arena = Arena_get(Message_GetArena(_self));
+
+  switch (accessor_type) {
+    case METHOD_SETTER:
+      Message_setfield(Message_GetMutable(_self, NULL), f, argv[1], arena);
+      return Qnil;
+    case METHOD_CLEAR:
+      upb_msg_clearfield(Message_GetMutable(_self, NULL), f);
+      return Qnil;
+    case METHOD_PRESENCE:
+      if (!upb_fielddef_haspresence(f)) {
+        rb_raise(rb_eRuntimeError, "Field does not have presence.");
+      }
+      return upb_msg_has(Message_Get(_self, NULL), f);
+    case METHOD_WRAPPER_GETTER: {
+      Message* self = ruby_to_Message(_self);
+      if (upb_msg_has(self->msg, f)) {
+        PBRUBY_ASSERT(upb_fielddef_issubmsg(f) && !upb_fielddef_isseq(f));
+        upb_msgval wrapper = upb_msg_get(self->msg, f);
+        const upb_msgdef *wrapper_m = upb_fielddef_msgsubdef(f);
+        const upb_fielddef *value_f = upb_msgdef_itof(wrapper_m, 1);
+        upb_msgval value = upb_msg_get(wrapper.msg_val, value_f);
+        return Convert_UpbToRuby(value, TypeInfo_get(value_f), self->arena);
+      } else {
+        return Qnil;
+      }
+    }
+    case METHOD_WRAPPER_SETTER: {
+      upb_msg *msg = Message_GetMutable(_self, NULL);
+      if (argv[1] == Qnil) {
+        upb_msg_clearfield(msg, f);
+      } else {
+        const upb_fielddef *val_f = upb_msgdef_itof(upb_fielddef_msgsubdef(f), 1);
+        upb_msgval msgval = Convert_RubyToUpb(argv[1], upb_fielddef_name(f),
+                                              TypeInfo_get(val_f), arena);
+        upb_msg *wrapper = upb_msg_mutable(msg, f, arena).msg;
+        upb_msg_set(wrapper, val_f, msgval, arena);
+      }
+      return Qnil;
+    }
+    case METHOD_ENUM_GETTER: {
+      upb_msgval msgval = upb_msg_get(Message_Get(_self, NULL), f);
+
+      if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
+        // Map repeated fields to a new type with ints
+        VALUE arr = rb_ary_new();
+        size_t i, n = upb_array_size(msgval.array_val);
+        for (i = 0; i < n; i++) {
+          upb_msgval elem = upb_array_get(msgval.array_val, i);
+          rb_ary_push(arr, INT2NUM(elem.int32_val));
+        }
+        return arr;
+      } else {
+        return INT2NUM(msgval.int32_val);
+      }
+    }
+    case METHOD_GETTER: {
+      Message* self = ruby_to_Message(_self);
+      // This is a special-case: upb_msg_mutable() for map & array are logically
+      // const (they will not change what is serialized) but physically
+      // non-const, as they do allocate a repeated field or map. The logical
+      // constness means it's ok to do even if the message is frozen.
+      upb_msg *msg = (upb_msg*)self->msg;
+      if (upb_fielddef_ismap(f)) {
+        upb_map *map = upb_msg_mutable(msg, f, arena).map;
+        const upb_fielddef *key_f = map_field_key(f);
+        const upb_fielddef *val_f = map_field_value(f);
+        upb_fieldtype_t key_type = upb_fielddef_type(key_f);
+        TypeInfo value_type_info = TypeInfo_get(val_f);
+        return Map_GetRubyWrapper(map, key_type, value_type_info, self->arena);
+      } else if (upb_fielddef_isseq(f)) {
+        upb_array *arr = upb_msg_mutable(msg, f, arena).array;
+        return RepeatedField_GetRubyWrapper(arr, TypeInfo_get(f), self->arena);
+      } else if (upb_fielddef_issubmsg(f)) {
+        if (!upb_msg_has(self->msg, f)) return Qnil;
+        upb_msg *submsg = upb_msg_mutable(msg, f, arena).msg;
+        const upb_msgdef *m = upb_fielddef_msgsubdef(f);
+        return Message_GetRubyWrapper(submsg, m, self->arena);
+      } else {
+        upb_msgval msgval = upb_msg_get(self->msg, f);
+        return Convert_UpbToRuby(msgval, TypeInfo_get(f), self->arena);
+      }
+    default:
+      rb_raise(rb_eRuntimeError, "Internal error, no such accessor: %d",
+               accessor_type);
+    }
+  }
 }
 
 /*
@@ -284,111 +410,56 @@
  * true if the field 'fieldname' is set in the message object, else false. For
  * 'proto3' syntax, calling this for a basic type field will result in an error.
  */
-VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
-  MessageHeader* self;
+static VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
+  Message* self = ruby_to_Message(_self);
   const upb_oneofdef* o;
   const upb_fielddef* f;
   int accessor_type;
 
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
   if (argc < 1) {
     rb_raise(rb_eArgError, "Expected method name as first argument.");
   }
 
   accessor_type = extract_method_call(argv[0], self, &f, &o);
-  if (accessor_type == METHOD_UNKNOWN || (o == NULL && f == NULL) ) {
-    return rb_call_super(argc, argv);
-  } else if (accessor_type == METHOD_SETTER || accessor_type == METHOD_WRAPPER_SETTER) {
-    if (argc != 2) {
-      rb_raise(rb_eArgError, "Expected 2 arguments, received %d", argc);
-    }
-    rb_check_frozen(_self);
-  } else if (argc != 1) {
-    rb_raise(rb_eArgError, "Expected 1 argument, received %d", argc);
+
+  if (accessor_type == METHOD_UNKNOWN) return rb_call_super(argc, argv);
+
+  // Validate argument count.
+  switch (accessor_type) {
+    case METHOD_SETTER:
+    case METHOD_WRAPPER_SETTER:
+      if (argc != 2) {
+        rb_raise(rb_eArgError, "Expected 2 arguments, received %d", argc);
+      }
+      rb_check_frozen(_self);
+      break;
+    default:
+      if (argc != 1) {
+        rb_raise(rb_eArgError, "Expected 1 argument, received %d", argc);
+      }
+      break;
   }
 
-  // Return which of the oneof fields are set
+  // Dispatch accessor.
   if (o != NULL) {
-    const upb_fielddef* oneof_field = which_oneof_field(self, o);
-
-    if (accessor_type == METHOD_SETTER) {
-      rb_raise(rb_eRuntimeError, "Oneof accessors are read-only.");
-    }
-
-    if (accessor_type == METHOD_PRESENCE) {
-      return oneof_field == NULL ? Qfalse : Qtrue;
-    } else if (accessor_type == METHOD_CLEAR) {
-      if (oneof_field != NULL) {
-        layout_clear(self->descriptor->layout, Message_data(self), oneof_field);
-      }
-      return Qnil;
-    } else {
-      // METHOD_ACCESSOR
-      return oneof_field == NULL ? Qnil :
-        ID2SYM(rb_intern(upb_fielddef_name(oneof_field)));
-    }
-  // Otherwise we're operating on a single proto field
-  } else if (accessor_type == METHOD_SETTER) {
-    layout_set(self->descriptor->layout, Message_data(self), f, argv[1]);
-    return Qnil;
-  } else if (accessor_type == METHOD_CLEAR) {
-    layout_clear(self->descriptor->layout, Message_data(self), f);
-    return Qnil;
-  } else if (accessor_type == METHOD_PRESENCE) {
-    return layout_has(self->descriptor->layout, Message_data(self), f);
-  } else if (accessor_type == METHOD_WRAPPER_GETTER) {
-    VALUE value = layout_get(self->descriptor->layout, Message_data(self), f);
-    switch (TYPE(value)) {
-      case T_DATA:
-        return rb_funcall(value, rb_intern("value"), 0);
-      case T_NIL:
-        return Qnil;
-      default:
-        return value;
-    }
-  } else if (accessor_type == METHOD_WRAPPER_SETTER) {
-    VALUE wrapper = ruby_wrapper_type(
-        field_type_class(self->descriptor->layout, f), argv[1]);
-    layout_set(self->descriptor->layout, Message_data(self), f, wrapper);
-    return Qnil;
-  } else if (accessor_type == METHOD_ENUM_GETTER) {
-    VALUE enum_type = field_type_class(self->descriptor->layout, f);
-    VALUE method = rb_intern("const_get");
-    VALUE raw_value = layout_get(self->descriptor->layout, Message_data(self), f);
-
-    // Map repeated fields to a new type with ints
-    if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
-      int array_size = FIX2INT(rb_funcall(raw_value, rb_intern("length"), 0));
-      int i;
-      VALUE array_args[1] = { ID2SYM(rb_intern("int64")) };
-      VALUE array = rb_class_new_instance(1, array_args, CLASS_OF(raw_value));
-      for (i = 0; i < array_size; i++) {
-        VALUE entry = rb_funcall(enum_type, method, 1, rb_funcall(raw_value,
-                                 rb_intern("at"), 1, INT2NUM(i)));
-        rb_funcall(array, rb_intern("push"), 1, entry);
-      }
-      return array;
-    }
-    // Convert the value for singular fields
-    return rb_funcall(enum_type, method, 1, raw_value);
+    return Message_oneof_accessor(_self, o, accessor_type);
   } else {
-    return layout_get(self->descriptor->layout, Message_data(self), f);
+    return Message_field_accessor(_self, f, accessor_type, argc, argv);
   }
 }
 
-
-VALUE Message_respond_to_missing(int argc, VALUE* argv, VALUE _self) {
-  MessageHeader* self;
+static VALUE Message_respond_to_missing(int argc, VALUE* argv, VALUE _self) {
+  Message* self = ruby_to_Message(_self);
   const upb_oneofdef* o;
   const upb_fielddef* f;
   int accessor_type;
 
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
   if (argc < 1) {
     rb_raise(rb_eArgError, "Expected method name as first argument.");
   }
 
   accessor_type = extract_method_call(argv[0], self, &f, &o);
+
   if (accessor_type == METHOD_UNKNOWN) {
     return rb_call_super(argc, argv);
   } else if (o != NULL) {
@@ -398,17 +469,116 @@
   }
 }
 
-VALUE create_submsg_from_hash(const MessageLayout* layout,
-                              const upb_fielddef* f, VALUE hash) {
-  VALUE args[1] = { hash };
-  return rb_class_new_instance(1, args, field_type_class(layout, f));
+void Message_InitFromValue(upb_msg* msg, const upb_msgdef* m, VALUE val,
+                           upb_arena* arena);
+
+typedef struct {
+  upb_map *map;
+  TypeInfo key_type;
+  TypeInfo val_type;
+  upb_arena *arena;
+} MapInit;
+
+static int Map_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
+  MapInit *map_init = (MapInit*)_self;
+  upb_msgval k, v;
+  k = Convert_RubyToUpb(key, "", map_init->key_type, NULL);
+
+  if (map_init->val_type.type == UPB_TYPE_MESSAGE && TYPE(val) == T_HASH) {
+    upb_msg *msg = upb_msg_new(map_init->val_type.def.msgdef, map_init->arena);
+    Message_InitFromValue(msg, map_init->val_type.def.msgdef, val,
+                          map_init->arena);
+    v.msg_val = msg;
+  } else {
+    v = Convert_RubyToUpb(val, "", map_init->val_type, map_init->arena);
+  }
+  upb_map_set(map_init->map, k, v, map_init->arena);
+  return ST_CONTINUE;
 }
 
-int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
-  MessageHeader* self;
-  char *name;
-  const upb_fielddef* f;
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+static void Map_InitFromValue(upb_map* map, const upb_fielddef* f, VALUE val,
+                       upb_arena* arena) {
+  const upb_msgdef* entry_m = upb_fielddef_msgsubdef(f);
+  const upb_fielddef* key_f = upb_msgdef_itof(entry_m, 1);
+  const upb_fielddef* val_f = upb_msgdef_itof(entry_m, 2);
+  if (TYPE(val) != T_HASH) {
+    rb_raise(rb_eArgError,
+             "Expected Hash object as initializer value for map field '%s' "
+             "(given %s).",
+             upb_fielddef_name(f), rb_class2name(CLASS_OF(val)));
+  }
+  MapInit map_init = {map, TypeInfo_get(key_f), TypeInfo_get(val_f), arena};
+  rb_hash_foreach(val, Map_initialize_kwarg, (VALUE)&map_init);
+}
+
+static upb_msgval MessageValue_FromValue(VALUE val, TypeInfo info,
+                                         upb_arena* arena) {
+  if (info.type == UPB_TYPE_MESSAGE) {
+    upb_msgval msgval;
+    upb_msg* msg = upb_msg_new(info.def.msgdef, arena);
+    Message_InitFromValue(msg, info.def.msgdef, val, arena);
+    msgval.msg_val = msg;
+    return msgval;
+  } else {
+    return Convert_RubyToUpb(val, "", info, arena);
+  }
+}
+
+static void RepeatedField_InitFromValue(upb_array* arr, const upb_fielddef* f,
+                                        VALUE val, upb_arena* arena) {
+  TypeInfo type_info = TypeInfo_get(f);
+
+  if (TYPE(val) != T_ARRAY) {
+    rb_raise(rb_eArgError,
+             "Expected array as initializer value for repeated field '%s' (given %s).",
+             upb_fielddef_name(f), rb_class2name(CLASS_OF(val)));
+  }
+
+  for (int i = 0; i < RARRAY_LEN(val); i++) {
+    VALUE entry = rb_ary_entry(val, i);
+    upb_msgval msgval;
+    if (upb_fielddef_issubmsg(f) && TYPE(entry) == T_HASH) {
+      msgval = MessageValue_FromValue(entry, type_info, arena);
+    } else {
+      msgval = Convert_RubyToUpb(entry, upb_fielddef_name(f), type_info, arena);
+    }
+    upb_array_append(arr, msgval, arena);
+  }
+}
+
+static void Message_InitFieldFromValue(upb_msg* msg, const upb_fielddef* f,
+                                       VALUE val, upb_arena* arena) {
+  if (TYPE(val) == T_NIL) return;
+
+  if (upb_fielddef_ismap(f)) {
+    upb_map *map = upb_msg_mutable(msg, f, arena).map;
+    Map_InitFromValue(map, f, val, arena);
+  } else if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
+    upb_array *arr = upb_msg_mutable(msg, f, arena).array;
+    RepeatedField_InitFromValue(arr, f, val, arena);
+  } else if (upb_fielddef_issubmsg(f)) {
+    if (TYPE(val) == T_HASH) {
+      upb_msg *submsg = upb_msg_mutable(msg, f, arena).msg;
+      Message_InitFromValue(submsg, upb_fielddef_msgsubdef(f), val, arena);
+    } else {
+      Message_setfield(msg, f, val, arena);
+    }
+  } else {
+    upb_msgval msgval =
+        Convert_RubyToUpb(val, upb_fielddef_name(f), TypeInfo_get(f), arena);
+    upb_msg_set(msg, f, msgval, arena);
+  }
+}
+
+typedef struct {
+  upb_msg *msg;
+  const upb_msgdef *msgdef;
+  upb_arena *arena;
+} MsgInit;
+
+static int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
+  MsgInit *msg_init = (MsgInit*)_self;
+  const char *name;
 
   if (TYPE(key) == T_STRING) {
     name = RSTRING_PTR(key);
@@ -419,52 +589,26 @@
              "Expected string or symbols as hash keys when initializing proto from hash.");
   }
 
-  f = upb_msgdef_ntofz(self->descriptor->msgdef, name);
+  const upb_fielddef* f = upb_msgdef_ntofz(msg_init->msgdef, name);
+
   if (f == NULL) {
     rb_raise(rb_eArgError,
              "Unknown field name '%s' in initialization map entry.", name);
   }
 
-  if (TYPE(val) == T_NIL) {
-    return 0;
-  }
+  Message_InitFieldFromValue(msg_init->msg, f, val, msg_init->arena);
+  return ST_CONTINUE;
+}
 
-  if (is_map_field(f)) {
-    VALUE map;
-
-    if (TYPE(val) != T_HASH) {
-      rb_raise(rb_eArgError,
-               "Expected Hash object as initializer value for map field '%s' (given %s).",
-               name, rb_class2name(CLASS_OF(val)));
-    }
-    map = layout_get(self->descriptor->layout, Message_data(self), f);
-    Map_merge_into_self(map, val);
-  } else if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
-    VALUE ary;
-    int i;
-
-    if (TYPE(val) != T_ARRAY) {
-      rb_raise(rb_eArgError,
-               "Expected array as initializer value for repeated field '%s' (given %s).",
-               name, rb_class2name(CLASS_OF(val)));
-    }
-    ary = layout_get(self->descriptor->layout, Message_data(self), f);
-    for (i = 0; i < RARRAY_LEN(val); i++) {
-      VALUE entry = rb_ary_entry(val, i);
-      if (TYPE(entry) == T_HASH && upb_fielddef_issubmsg(f)) {
-        entry = create_submsg_from_hash(self->descriptor->layout, f, entry);
-      }
-
-      RepeatedField_push(ary, entry);
-    }
+void Message_InitFromValue(upb_msg* msg, const upb_msgdef* m, VALUE val,
+                           upb_arena* arena) {
+  MsgInit msg_init = {msg, m, arena};
+  if (TYPE(val) == T_HASH) {
+    rb_hash_foreach(val, Message_initialize_kwarg, (VALUE)&msg_init);
   } else {
-    if (TYPE(val) == T_HASH && upb_fielddef_issubmsg(f)) {
-      val = create_submsg_from_hash(self->descriptor->layout, f, val);
-    }
-
-    layout_set(self->descriptor->layout, Message_data(self), f, val);
+    rb_raise(rb_eArgError, "Expected hash arguments or message, not %s",
+             rb_class2name(CLASS_OF(val)));
   }
-  return 0;
 }
 
 /*
@@ -479,12 +623,13 @@
  * have been added to a pool. The method definitions described here on the
  * Message class are provided on each concrete message class.
  */
-VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
-  MessageHeader* self;
-  VALUE hash_args;
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+static VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
+  Message* self = ruby_to_Message(_self);
+  VALUE arena_rb = Arena_new();
+  upb_arena *arena = Arena_get(arena_rb);
+  upb_msg *msg = upb_msg_new(self->msgdef, arena);
 
-  layout_init(self->descriptor->layout, Message_data(self));
+  Message_InitPtr(_self, msg, arena_rb);
 
   if (argc == 0) {
     return Qnil;
@@ -492,12 +637,7 @@
   if (argc != 1) {
     rb_raise(rb_eArgError, "Expected 0 or 1 arguments.");
   }
-  hash_args = argv[0];
-  if (TYPE(hash_args) != T_HASH) {
-    rb_raise(rb_eArgError, "Expected hash arguments.");
-  }
-
-  rb_hash_foreach(hash_args, Message_initialize_kwarg, _self);
+  Message_InitFromValue((upb_msg*)self->msg, self->msgdef, argv[0], arena);
   return Qnil;
 }
 
@@ -507,37 +647,40 @@
  *
  * Performs a shallow copy of this message and returns the new copy.
  */
-VALUE Message_dup(VALUE _self) {
-  MessageHeader* self;
-  VALUE new_msg;
-  MessageHeader* new_msg_self;
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+static VALUE Message_dup(VALUE _self) {
+  Message* self = ruby_to_Message(_self);
+  VALUE new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
+  Message* new_msg_self = ruby_to_Message(new_msg);
+  size_t size = upb_msgdef_layout(self->msgdef)->size;
 
-  new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
-  TypedData_Get_Struct(new_msg, MessageHeader, &Message_type, new_msg_self);
-
-  layout_dup(self->descriptor->layout,
-             Message_data(new_msg_self),
-             Message_data(self));
-
+  // TODO(copy unknown fields?)
+  // TODO(use official upb msg copy function)
+  memcpy((upb_msg*)new_msg_self->msg, self->msg, size);
+  upb_arena_fuse(Arena_get(new_msg_self->arena), Arena_get(self->arena));
   return new_msg;
 }
 
-// Internal only; used by Google::Protobuf.deep_copy.
-VALUE Message_deep_copy(VALUE _self) {
-  MessageHeader* self;
-  MessageHeader* new_msg_self;
-  VALUE new_msg;
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+// Support function for Message_eq, and also used by other #eq functions.
+bool Message_Equal(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m) {
+  if (m1 == m2) return true;
 
-  new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
-  TypedData_Get_Struct(new_msg, MessageHeader, &Message_type, new_msg_self);
+  size_t size1, size2;
+  int encode_opts = UPB_ENCODE_SKIPUNKNOWN | UPB_ENCODE_DETERMINISTIC;
+  upb_arena *arena_tmp = upb_arena_new();
+  const upb_msglayout *layout = upb_msgdef_layout(m);
 
-  layout_deep_copy(self->descriptor->layout,
-                   Message_data(new_msg_self),
-                   Message_data(self));
+  // Compare deterministically serialized payloads with no unknown fields.
+  char *data1 = upb_encode_ex(m1, layout, encode_opts, arena_tmp, &size1);
+  char *data2 = upb_encode_ex(m2, layout, encode_opts, arena_tmp, &size2);
 
-  return new_msg;
+  if (data1 && data2) {
+    bool ret = (size1 == size2) && (memcmp(data1, data2, size1) == 0);
+    upb_arena_free(arena_tmp);
+    return ret;
+  } else {
+    upb_arena_free(arena_tmp);
+    rb_raise(cParseError, "Error comparing messages");
+  }
 }
 
 /*
@@ -549,22 +692,37 @@
  * method's semantics (a more efficient comparison may actually be done if the
  * field is of a primitive type).
  */
-VALUE Message_eq(VALUE _self, VALUE _other) {
-  MessageHeader* self;
-  MessageHeader* other;
+static VALUE Message_eq(VALUE _self, VALUE _other) {
   if (TYPE(_self) != TYPE(_other)) {
     return Qfalse;
   }
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
-  TypedData_Get_Struct(_other, MessageHeader, &Message_type, other);
 
-  if (self->descriptor != other->descriptor) {
-    return Qfalse;
+  Message* self = ruby_to_Message(_self);
+  Message* other = ruby_to_Message(_other);
+
+  return Message_Equal(self->msg, other->msg, self->msgdef)
+             ? Qtrue
+             : Qfalse;
+}
+
+uint64_t Message_Hash(const upb_msg* msg, const upb_msgdef* m, uint64_t seed) {
+  upb_arena *arena = upb_arena_new();
+  const char *data;
+  size_t size;
+
+  // Hash a deterministically serialized payloads with no unknown fields.
+  data = upb_encode_ex(msg, upb_msgdef_layout(m),
+                       UPB_ENCODE_SKIPUNKNOWN | UPB_ENCODE_DETERMINISTIC, arena,
+                       &size);
+
+  if (data) {
+    uint64_t ret = wyhash(data, size, seed, _wyp);
+    upb_arena_free(arena);
+    return ret;
+  } else {
+    upb_arena_free(arena);
+    rb_raise(cParseError, "Error calculating hash");
   }
-
-  return layout_eq(self->descriptor->layout,
-                   Message_data(self),
-                   Message_data(other));
 }
 
 /*
@@ -573,11 +731,9 @@
  *
  * Returns a hash value that represents this message's field values.
  */
-VALUE Message_hash(VALUE _self) {
-  MessageHeader* self;
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
-
-  return layout_hash(self->descriptor->layout, Message_data(self));
+static VALUE Message_hash(VALUE _self) {
+  Message* self = ruby_to_Message(_self);
+  return INT2FIX(Message_Hash(self->msg, self->msgdef, 0));
 }
 
 /*
@@ -588,18 +744,91 @@
  * formatted as "<MessageType: field1: value1, field2: value2, ...>". Each
  * field's value is represented according to its own #inspect method.
  */
-VALUE Message_inspect(VALUE _self) {
-  MessageHeader* self;
-  VALUE str;
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+static VALUE Message_inspect(VALUE _self) {
+  Message* self = ruby_to_Message(_self);
 
-  str = rb_str_new2("<");
-  str = rb_str_append(str, rb_str_new2(rb_class2name(CLASS_OF(_self))));
-  str = rb_str_cat2(str, ": ");
-  str = rb_str_append(str, layout_inspect(
-      self->descriptor->layout, Message_data(self)));
-  str = rb_str_cat2(str, ">");
-  return str;
+  StringBuilder* builder = StringBuilder_New();
+  Message_PrintMessage(builder, self->msg, self->msgdef);
+  VALUE ret = StringBuilder_ToRubyString(builder);
+  StringBuilder_Free(builder);
+  return ret;
+}
+
+// Support functions for Message_to_h //////////////////////////////////////////
+
+static VALUE RepeatedField_CreateArray(const upb_array* arr,
+                                       TypeInfo type_info) {
+  int size = arr ? upb_array_size(arr) : 0;
+  VALUE ary = rb_ary_new2(size);
+
+  for (int i = 0; i < size; i++) {
+    upb_msgval msgval = upb_array_get(arr, i);
+    VALUE val = Scalar_CreateHash(msgval, type_info);
+    rb_ary_push(ary, val);
+  }
+
+  return ary;
+}
+
+static VALUE Message_CreateHash(const upb_msg *msg, const upb_msgdef *m) {
+  if (!msg) return Qnil;
+
+  VALUE hash = rb_hash_new();
+  int n = upb_msgdef_fieldcount(m);
+  bool is_proto2;
+
+  // We currently have a few behaviors that are specific to proto2.
+  // This is unfortunate, we should key behaviors off field attributes (like
+  // whether a field has presence), not proto2 vs. proto3. We should see if we
+  // can change this without breaking users.
+  is_proto2 = upb_msgdef_syntax(m) == UPB_SYNTAX_PROTO2;
+
+  for (int i = 0; i < n; i++) {
+    const upb_fielddef* field = upb_msgdef_field(m, i);
+    TypeInfo type_info = TypeInfo_get(field);
+    upb_msgval msgval;
+    VALUE msg_value;
+    VALUE msg_key;
+
+    // Do not include fields that are not present (oneof or optional fields).
+    if (is_proto2 && upb_fielddef_haspresence(field) &&
+        !upb_msg_has(msg, field)) {
+      continue;
+    }
+
+    msg_key = ID2SYM(rb_intern(upb_fielddef_name(field)));
+    msgval = upb_msg_get(msg, field);
+
+    // Proto2 omits empty map/repeated filds also.
+
+    if (upb_fielddef_ismap(field)) {
+      const upb_msgdef *entry_m = upb_fielddef_msgsubdef(field);
+      const upb_fielddef *key_f = upb_msgdef_itof(entry_m, 1);
+      const upb_fielddef *val_f = upb_msgdef_itof(entry_m, 2);
+      upb_fieldtype_t key_type = upb_fielddef_type(key_f);
+      msg_value = Map_CreateHash(msgval.map_val, key_type, TypeInfo_get(val_f));
+    } else if (upb_fielddef_isseq(field)) {
+      if (is_proto2 &&
+          (!msgval.array_val || upb_array_size(msgval.array_val) == 0)) {
+        continue;
+      }
+      msg_value = RepeatedField_CreateArray(msgval.array_val, type_info);
+    } else {
+      msg_value = Scalar_CreateHash(msgval, type_info);
+    }
+
+    rb_hash_aset(hash, msg_key, msg_value);
+  }
+
+  return hash;
+}
+
+VALUE Scalar_CreateHash(upb_msgval msgval, TypeInfo type_info) {
+  if (type_info.type == UPB_TYPE_MESSAGE) {
+    return Message_CreateHash(msgval.msg_val, type_info.def.msgdef);
+  } else {
+    return Convert_UpbToRuby(msgval, type_info, Qnil);
+  }
 }
 
 /*
@@ -608,61 +837,24 @@
  *
  * Returns the message as a Ruby Hash object, with keys as symbols.
  */
-VALUE Message_to_h(VALUE _self) {
-  MessageHeader* self;
-  VALUE hash = rb_hash_new();
-  upb_msg_field_iter it;
-  bool is_proto2;
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
-
-  // We currently have a few behaviors that are specific to proto2.
-  // This is unfortunate, we should key behaviors off field attributes (like
-  // whether a field has presence), not proto2 vs. proto3. We should see if we
-  // can change this without breaking users.
-  is_proto2 =
-      upb_msgdef_syntax(self->descriptor->msgdef) == UPB_SYNTAX_PROTO2;
-
-  for (upb_msg_field_begin(&it, self->descriptor->msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    VALUE msg_value;
-    VALUE msg_key;
-
-    // Do not include fields that are not present (oneof or optional fields).
-    if (is_proto2 && upb_fielddef_haspresence(field) &&
-        !layout_has(self->descriptor->layout, Message_data(self), field)) {
-      continue;
-    }
-
-    msg_value = layout_get(self->descriptor->layout, Message_data(self), field);
-    msg_key = ID2SYM(rb_intern(upb_fielddef_name(field)));
-    if (is_map_field(field)) {
-      msg_value = Map_to_h(msg_value);
-    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
-      msg_value = RepeatedField_to_ary(msg_value);
-      if (is_proto2 && RARRAY_LEN(msg_value) == 0) {
-        continue;
-      }
-
-      if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
-        int i;
-        for (i = 0; i < RARRAY_LEN(msg_value); i++) {
-          VALUE elem = rb_ary_entry(msg_value, i);
-          rb_ary_store(msg_value, i, Message_to_h(elem));
-        }
-      }
-
-    } else if (msg_value != Qnil &&
-               upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
-      msg_value = Message_to_h(msg_value);
-    }
-    rb_hash_aset(hash, msg_key, msg_value);
-  }
-  return hash;
+static VALUE Message_to_h(VALUE _self) {
+  Message* self = ruby_to_Message(_self);
+  return Message_CreateHash(self->msg, self->msgdef);
 }
 
-
+/*
+ * call-seq:
+ *     Message.freeze => self
+ *
+ * Freezes the message object. We have to intercept this so we can pin the
+ * Ruby object into memory so we don't forget it's frozen.
+ */
+static VALUE Message_freeze(VALUE _self) {
+  Message* self = ruby_to_Message(_self);
+  ObjectCache_Pin(self->msg, _self, Arena_get(self->arena));
+  RB_OBJ_FREEZE(_self);
+  return _self;
+}
 
 /*
  * call-seq:
@@ -671,16 +863,20 @@
  * Accesses a field's value by field name. The provided field name should be a
  * string.
  */
-VALUE Message_index(VALUE _self, VALUE field_name) {
-  MessageHeader* self;
+static VALUE Message_index(VALUE _self, VALUE field_name) {
+  Message* self = ruby_to_Message(_self);
   const upb_fielddef* field;
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+  upb_msgval val;
+
   Check_Type(field_name, T_STRING);
-  field = upb_msgdef_ntofz(self->descriptor->msgdef, RSTRING_PTR(field_name));
+  field = upb_msgdef_ntofz(self->msgdef, RSTRING_PTR(field_name));
+
   if (field == NULL) {
     return Qnil;
   }
-  return layout_get(self->descriptor->layout, Message_data(self), field);
+
+  val = upb_msg_get(self->msg, field);
+  return Convert_UpbToRuby(val, TypeInfo_get(field), self->arena);
 }
 
 /*
@@ -690,36 +886,224 @@
  * Sets a field's value by field name. The provided field name should be a
  * string.
  */
-VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
-  MessageHeader* self;
-  const upb_fielddef* field;
-  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+static VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
+  Message* self = ruby_to_Message(_self);
+  const upb_fielddef* f;
+  upb_msgval val;
+  upb_arena *arena = Arena_get(self->arena);
+
   Check_Type(field_name, T_STRING);
-  field = upb_msgdef_ntofz(self->descriptor->msgdef, RSTRING_PTR(field_name));
-  if (field == NULL) {
+  f = upb_msgdef_ntofz(self->msgdef, RSTRING_PTR(field_name));
+
+  if (f == NULL) {
     rb_raise(rb_eArgError, "Unknown field: %s", RSTRING_PTR(field_name));
   }
-  layout_set(self->descriptor->layout, Message_data(self), field, value);
+
+  val = Convert_RubyToUpb(value, upb_fielddef_name(f), TypeInfo_get(f), arena);
+  upb_msg_set(Message_GetMutable(_self, NULL), f, val, arena);
+
   return Qnil;
 }
 
 /*
  * call-seq:
+ *     MessageClass.decode(data) => message
+ *
+ * Decodes the given data (as a string containing bytes in protocol buffers wire
+ * format) under the interpretration given by this message class's definition
+ * and returns a message object with the corresponding field values.
+ */
+static VALUE Message_decode(VALUE klass, VALUE data) {
+  if (TYPE(data) != T_STRING) {
+    rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
+  }
+
+  VALUE msg_rb = initialize_rb_class_with_no_args(klass);
+  Message* msg = ruby_to_Message(msg_rb);
+
+  if (!upb_decode(RSTRING_PTR(data), RSTRING_LEN(data), (upb_msg*)msg->msg,
+                 upb_msgdef_layout(msg->msgdef),
+                 Arena_get(msg->arena))) {
+    rb_raise(cParseError, "Error occurred during parsing");
+  }
+
+  return msg_rb;
+}
+
+/*
+ * call-seq:
+ *     MessageClass.decode_json(data, options = {}) => message
+ *
+ * Decodes the given data (as a string containing bytes in protocol buffers wire
+ * format) under the interpretration given by this message class's definition
+ * and returns a message object with the corresponding field values.
+ *
+ *  @param options [Hash] options for the decoder
+ *   ignore_unknown_fields: set true to ignore unknown fields (default is to
+ *   raise an error)
+ */
+static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
+  VALUE data = argv[0];
+  int options = 0;
+  upb_status status;
+
+  // TODO(haberman): use this message's pool instead.
+  const upb_symtab *symtab = DescriptorPool_GetSymtab(generated_pool);
+
+  if (argc < 1 || argc > 2) {
+    rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
+  }
+
+  if (argc == 2) {
+    VALUE hash_args = argv[1];
+    if (TYPE(hash_args) != T_HASH) {
+      rb_raise(rb_eArgError, "Expected hash arguments.");
+    }
+
+    if (RTEST(rb_hash_lookup2( hash_args, ID2SYM(rb_intern("ignore_unknown_fields")), Qfalse))) {
+      options |= UPB_JSONDEC_IGNOREUNKNOWN;
+    }
+  }
+
+  if (TYPE(data) != T_STRING) {
+    rb_raise(rb_eArgError, "Expected string for JSON data.");
+  }
+
+  // TODO(cfallin): Check and respect string encoding. If not UTF-8, we need to
+  // convert, because string handlers pass data directly to message string
+  // fields.
+
+  VALUE msg_rb = initialize_rb_class_with_no_args(klass);
+  Message* msg = ruby_to_Message(msg_rb);
+
+  // We don't allow users to decode a wrapper type directly.
+  if (upb_msgdef_iswrapper(msg->msgdef)) {
+    rb_raise(rb_eRuntimeError, "Cannot parse a wrapper directly.");
+  }
+
+  upb_status_clear(&status);
+  if (!upb_json_decode(RSTRING_PTR(data), RSTRING_LEN(data), (upb_msg*)msg->msg,
+                       msg->msgdef, symtab, options,
+                       Arena_get(msg->arena), &status)) {
+    rb_raise(cParseError, "Error occurred during parsing: %s",
+             upb_status_errmsg(&status));
+  }
+
+  return msg_rb;
+}
+
+/*
+ * call-seq:
+ *     MessageClass.encode(msg) => bytes
+ *
+ * Encodes the given message object to its serialized form in protocol buffers
+ * wire format.
+ */
+static VALUE Message_encode(VALUE klass, VALUE msg_rb) {
+  Message* msg = ruby_to_Message(msg_rb);
+  upb_arena *arena = upb_arena_new();
+  const char *data;
+  size_t size;
+
+  if (CLASS_OF(msg_rb) != klass) {
+    rb_raise(rb_eArgError, "Message of wrong type.");
+  }
+
+  data = upb_encode(msg->msg, upb_msgdef_layout(msg->msgdef), arena,
+                    &size);
+
+  if (data) {
+    VALUE ret = rb_str_new(data, size);
+    rb_enc_associate(ret, rb_ascii8bit_encoding());
+    upb_arena_free(arena);
+    return ret;
+  } else {
+    upb_arena_free(arena);
+    rb_raise(rb_eRuntimeError, "Exceeded maximum depth (possibly cycle)");
+  }
+}
+
+/*
+ * call-seq:
+ *     MessageClass.encode_json(msg, options = {}) => json_string
+ *
+ * Encodes the given message object into its serialized JSON representation.
+ * @param options [Hash] options for the decoder
+ *  preserve_proto_fieldnames: set true to use original fieldnames (default is to camelCase)
+ *  emit_defaults: set true to emit 0/false values (default is to omit them)
+ */
+static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
+  Message* msg = ruby_to_Message(argv[0]);
+  int options = 0;
+  char buf[1024];
+  size_t size;
+  upb_status status;
+
+  // TODO(haberman): use this message's pool instead.
+  const upb_symtab *symtab = DescriptorPool_GetSymtab(generated_pool);
+
+  if (argc < 1 || argc > 2) {
+    rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
+  }
+
+  if (argc == 2) {
+    VALUE hash_args = argv[1];
+    if (TYPE(hash_args) != T_HASH) {
+      rb_raise(rb_eArgError, "Expected hash arguments.");
+    }
+
+    if (RTEST(rb_hash_lookup2(hash_args,
+                              ID2SYM(rb_intern("preserve_proto_fieldnames")),
+                              Qfalse))) {
+      options |= UPB_JSONENC_PROTONAMES;
+    }
+
+    if (RTEST(rb_hash_lookup2(hash_args, ID2SYM(rb_intern("emit_defaults")),
+                              Qfalse))) {
+      options |= UPB_JSONENC_EMITDEFAULTS;
+    }
+  }
+
+  upb_status_clear(&status);
+  size = upb_json_encode(msg->msg, msg->msgdef, symtab, options, buf,
+                         sizeof(buf), &status);
+
+  if (!upb_ok(&status)) {
+    rb_raise(cParseError, "Error occurred during encoding: %s",
+             upb_status_errmsg(&status));
+  }
+
+  VALUE ret;
+  if (size >= sizeof(buf)) {
+    char* buf2 = malloc(size + 1);
+    upb_json_encode(msg->msg, msg->msgdef, symtab, options, buf2, size + 1,
+                    &status);
+    ret = rb_str_new(buf2, size);
+    free(buf2);
+  } else {
+    ret = rb_str_new(buf, size);
+  }
+
+  rb_enc_associate(ret, rb_utf8_encoding());
+  return ret;
+}
+
+/*
+ * call-seq:
  *     Message.descriptor => descriptor
  *
  * Class method that returns the Descriptor instance corresponding to this
  * message class's type.
  */
-VALUE Message_descriptor(VALUE klass) {
+static VALUE Message_descriptor(VALUE klass) {
   return rb_ivar_get(klass, descriptor_instancevar_interned);
 }
 
 VALUE build_class_from_descriptor(VALUE descriptor) {
-  Descriptor* desc = ruby_to_Descriptor(descriptor);
   const char *name;
   VALUE klass;
 
-  name = upb_msgdef_fullname(desc->msgdef);
+  name = upb_msgdef_fullname(Descriptor_GetMsgDef(descriptor));
   if (name == NULL) {
     rb_raise(rb_eRuntimeError, "Descriptor does not have assigned name.");
   }
@@ -746,6 +1130,7 @@
   rb_define_method(klass, "clone", Message_dup, 0);
   rb_define_method(klass, "==", Message_eq, 1);
   rb_define_method(klass, "eql?", Message_eq, 1);
+  rb_define_method(klass, "freeze", Message_freeze, 0);
   rb_define_method(klass, "hash", Message_hash, 0);
   rb_define_method(klass, "to_h", Message_to_h, 0);
   rb_define_method(klass, "inspect", Message_inspect, 0);
@@ -768,12 +1153,12 @@
  * This module method, provided on each generated enum module, looks up an enum
  * value by number and returns its name as a Ruby symbol, or nil if not found.
  */
-VALUE enum_lookup(VALUE self, VALUE number) {
+static VALUE enum_lookup(VALUE self, VALUE number) {
   int32_t num = NUM2INT(number);
   VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned);
-  EnumDescriptor* enumdesc = ruby_to_EnumDescriptor(desc);
+  const upb_enumdef *e = EnumDescriptor_GetEnumDef(desc);
 
-  const char* name = upb_enumdef_iton(enumdesc->enumdef, num);
+  const char* name = upb_enumdef_iton(e, num);
   if (name == NULL) {
     return Qnil;
   } else {
@@ -788,13 +1173,13 @@
  * This module method, provided on each generated enum module, looks up an enum
  * value by name (as a Ruby symbol) and returns its name, or nil if not found.
  */
-VALUE enum_resolve(VALUE self, VALUE sym) {
+static VALUE enum_resolve(VALUE self, VALUE sym) {
   const char* name = rb_id2name(SYM2ID(sym));
   VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned);
-  EnumDescriptor* enumdesc = ruby_to_EnumDescriptor(desc);
+  const upb_enumdef *e = EnumDescriptor_GetEnumDef(desc);
 
   int32_t num = 0;
-  bool found = upb_enumdef_ntoiz(enumdesc->enumdef, name, &num);
+  bool found = upb_enumdef_ntoiz(e, name, &num);
   if (!found) {
     return Qnil;
   } else {
@@ -809,17 +1194,16 @@
  * This module method, provided on each generated enum module, returns the
  * EnumDescriptor corresponding to this enum type.
  */
-VALUE enum_descriptor(VALUE self) {
+static VALUE enum_descriptor(VALUE self) {
   return rb_ivar_get(self, descriptor_instancevar_interned);
 }
 
 VALUE build_module_from_enumdesc(VALUE _enumdesc) {
-  EnumDescriptor* enumdesc = ruby_to_EnumDescriptor(_enumdesc);
-  VALUE mod = rb_define_module_id(
-      rb_intern(upb_enumdef_fullname(enumdesc->enumdef)));
+  const upb_enumdef *e = EnumDescriptor_GetEnumDef(_enumdesc);
+  VALUE mod = rb_define_module_id(rb_intern(upb_enumdef_fullname(e)));
 
   upb_enum_iter it;
-  for (upb_enum_begin(&it, enumdesc->enumdef);
+  for (upb_enum_begin(&it, e);
        !upb_enum_done(&it);
        upb_enum_next(&it)) {
     const char* name = upb_enum_iter_name(&it);
@@ -840,20 +1224,92 @@
   return mod;
 }
 
-/*
- * call-seq:
- *     Google::Protobuf.deep_copy(obj) => copy_of_obj
- *
- * Performs a deep copy of a RepeatedField instance, a Map instance, or a
- * message object, recursively copying its members.
- */
-VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj) {
-  VALUE klass = CLASS_OF(obj);
-  if (klass == cRepeatedField) {
-    return RepeatedField_deep_copy(obj);
-  } else if (klass == cMap) {
-    return Map_deep_copy(obj);
-  } else {
-    return Message_deep_copy(obj);
+// Internal only; used by Google::Protobuf.deep_copy.
+upb_msg* Message_deep_copy(const upb_msg* msg, const upb_msgdef* m,
+                           upb_arena *arena) {
+  // Serialize and parse.
+  upb_arena *tmp_arena = upb_arena_new();
+  const upb_msglayout *layout = upb_msgdef_layout(m);
+  size_t size;
+
+  char* data = upb_encode_ex(msg, layout, 0, tmp_arena, &size);
+  upb_msg* new_msg = upb_msg_new(m, arena);
+
+  if (!data || !upb_decode(data, size, new_msg, layout, arena)) {
+    upb_arena_free(tmp_arena);
+    rb_raise(cParseError, "Error occurred copying proto");
   }
+
+  upb_arena_free(tmp_arena);
+  return new_msg;
+}
+
+const upb_msg* Message_GetUpbMessage(VALUE value, const upb_msgdef* m,
+                                     const char* name, upb_arena* arena) {
+  if (value == Qnil) return NULL;
+
+  VALUE klass = CLASS_OF(value);
+  VALUE desc_rb = rb_ivar_get(klass, descriptor_instancevar_interned);
+  const upb_msgdef* val_m =
+      desc_rb == Qnil ? NULL : Descriptor_GetMsgDef(desc_rb);
+
+  if (val_m != m) {
+    // Check for possible implicit conversions
+    // TODO: hash conversion?
+
+    switch (upb_msgdef_wellknowntype(m)) {
+      case UPB_WELLKNOWN_TIMESTAMP: {
+        // Time -> Google::Protobuf::Timestamp
+        upb_msg *msg = upb_msg_new(m, arena);
+        upb_msgval sec, nsec;
+        struct timespec time;
+        const upb_fielddef *sec_f = upb_msgdef_itof(m, 1);
+        const upb_fielddef *nsec_f = upb_msgdef_itof(m, 2);
+
+        if (!rb_obj_is_kind_of(value, rb_cTime)) goto badtype;
+
+        time = rb_time_timespec(value);
+        sec.int64_val = time.tv_sec;
+        nsec.int32_val = time.tv_nsec;
+        upb_msg_set(msg, sec_f, sec, arena);
+        upb_msg_set(msg, nsec_f, nsec, arena);
+        return msg;
+      }
+      case UPB_WELLKNOWN_DURATION: {
+        // Numeric -> Google::Protobuf::Duration
+        upb_msg *msg = upb_msg_new(m, arena);
+        upb_msgval sec, nsec;
+        const upb_fielddef *sec_f = upb_msgdef_itof(m, 1);
+        const upb_fielddef *nsec_f = upb_msgdef_itof(m, 2);
+
+        if (!rb_obj_is_kind_of(value, rb_cNumeric)) goto badtype;
+
+        sec.int64_val = NUM2LL(value);
+        nsec.int32_val = (NUM2DBL(value) - NUM2LL(value)) * 1000000000;
+        upb_msg_set(msg, sec_f, sec, arena);
+        upb_msg_set(msg, nsec_f, nsec, arena);
+        return msg;
+      }
+      default:
+      badtype:
+        rb_raise(cTypeError,
+                 "Invalid type %s to assign to submessage field '%s'.",
+                rb_class2name(CLASS_OF(value)), name);
+    }
+
+  }
+
+  Message* self = ruby_to_Message(value);
+  upb_arena_fuse(arena, Arena_get(self->arena));
+
+  return self->msg;
+}
+
+void Message_register(VALUE protobuf) {
+  cParseError = rb_const_get(protobuf, rb_intern("ParseError"));
+
+  // Ruby-interned string: "descriptor". We use this identifier to store an
+  // instance variable on message classes we create in order to link them back
+  // to their descriptors.
+  descriptor_instancevar_interned = rb_intern("descriptor");
 }
diff --git a/ruby/ext/google/protobuf_c/message.h b/ruby/ext/google/protobuf_c/message.h
new file mode 100644
index 0000000..551f41f
--- /dev/null
+++ b/ruby/ext/google/protobuf_c/message.h
@@ -0,0 +1,98 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef RUBY_PROTOBUF_MESSAGE_H_
+#define RUBY_PROTOBUF_MESSAGE_H_
+
+#include <ruby/ruby.h>
+
+#include "protobuf.h"
+#include "ruby-upb.h"
+
+// Gets the underlying upb_msg* and upb_msgdef for the given Ruby message
+// wrapper. Requires that |value| is indeed a message object.
+const upb_msg *Message_Get(VALUE value, const upb_msgdef **m);
+
+// Like Message_Get(), but checks that the object is not frozen and returns a
+// mutable pointer.
+upb_msg *Message_GetMutable(VALUE value, const upb_msgdef **m);
+
+// Returns the Arena object for this message.
+VALUE Message_GetArena(VALUE value);
+
+// Converts |value| into a upb_msg value of the expected upb_msgdef type,
+// raising an error if this is not possible. Used when assigning |value| to a
+// field of another message, which means the message must be of a particular
+// type.
+//
+// This will perform automatic conversions in some cases (for example, Time ->
+// Google::Protobuf::Timestamp). If any new message is created, it will be
+// created on |arena|, and any existing message will have its arena fused with
+// |arena|.
+const upb_msg* Message_GetUpbMessage(VALUE value, const upb_msgdef* m,
+                                     const char* name, upb_arena* arena);
+
+// Gets or constructs a Ruby wrapper object for the given message. The wrapper
+// object will reference |arena| and ensure that it outlives this object.
+VALUE Message_GetRubyWrapper(upb_msg* msg, const upb_msgdef* m, VALUE arena);
+
+// Implements #inspect for this message, printing the text to |b|.
+void Message_PrintMessage(StringBuilder* b, const upb_msg* msg,
+                          const upb_msgdef* m);
+
+// Returns a hash value for the given message.
+uint64_t Message_Hash(const upb_msg *msg, const upb_msgdef *m, uint64_t seed);
+
+// Returns a deep copy of the given message.
+upb_msg* Message_deep_copy(const upb_msg* msg, const upb_msgdef* m,
+                           upb_arena *arena);
+
+// Returns true if these two messages are equal.
+bool Message_Equal(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m);
+
+// Checks that this Ruby object is a message, and raises an exception if not.
+void Message_CheckClass(VALUE klass);
+
+// Returns a new Hash object containing the contents of this message.
+VALUE Scalar_CreateHash(upb_msgval val, TypeInfo type_info);
+
+// Creates a message class or enum module for this descriptor, respectively.
+VALUE build_class_from_descriptor(VALUE descriptor);
+VALUE build_module_from_enumdesc(VALUE _enumdesc);
+
+// Returns the Descriptor/EnumDescriptor for the given message class or enum
+// module, respectively. Returns nil if this is not a message class or enum
+// module.
+VALUE MessageOrEnum_GetDescriptor(VALUE klass);
+
+// Call at startup to register all types in this module.
+void Message_register(VALUE protobuf);
+
+#endif  // RUBY_PROTOBUF_MESSAGE_H_
diff --git a/ruby/ext/google/protobuf_c/protobuf.c b/ruby/ext/google/protobuf_c/protobuf.c
index 60c1e2a..737cd28 100644
--- a/ruby/ext/google/protobuf_c/protobuf.c
+++ b/ruby/ext/google/protobuf_c/protobuf.c
@@ -30,62 +30,342 @@
 
 #include "protobuf.h"
 
+#include <ruby/version.h>
+
+#include "defs.h"
+#include "map.h"
+#include "message.h"
+#include "repeated_field.h"
+
 VALUE cError;
-VALUE cParseError;
 VALUE cTypeError;
-VALUE c_only_cookie = Qnil;
 
-static VALUE cached_empty_string = Qnil;
-static VALUE cached_empty_bytes = Qnil;
-
-static VALUE create_frozen_string(const char* str, size_t size, bool binary) {
-  VALUE str_rb = rb_str_new(str, size);
-
-  rb_enc_associate(str_rb,
-                   binary ? kRubyString8bitEncoding : kRubyStringUtf8Encoding);
-  rb_obj_freeze(str_rb);
-  return str_rb;
+const upb_fielddef* map_field_key(const upb_fielddef* field) {
+  const upb_msgdef *entry = upb_fielddef_msgsubdef(field);
+  return upb_msgdef_itof(entry, 1);
 }
 
-VALUE get_frozen_string(const char* str, size_t size, bool binary) {
-  if (size == 0) {
-    return binary ? cached_empty_bytes : cached_empty_string;
+const upb_fielddef* map_field_value(const upb_fielddef* field) {
+  const upb_msgdef *entry = upb_fielddef_msgsubdef(field);
+  return upb_msgdef_itof(entry, 2);
+}
+
+// -----------------------------------------------------------------------------
+// StringBuilder, for inspect
+// -----------------------------------------------------------------------------
+
+struct StringBuilder {
+  size_t size;
+  size_t cap;
+  char *data;
+};
+
+typedef struct StringBuilder StringBuilder;
+
+static size_t StringBuilder_SizeOf(size_t cap) {
+  return sizeof(StringBuilder) + cap;
+}
+
+StringBuilder* StringBuilder_New() {
+  const size_t cap = 128;
+  StringBuilder* builder = malloc(sizeof(*builder));
+  builder->size = 0;
+  builder->cap = cap;
+  builder->data = malloc(builder->cap);
+  return builder;
+}
+
+void StringBuilder_Free(StringBuilder* b) {
+  free(b->data);
+  free(b);
+}
+
+void StringBuilder_Printf(StringBuilder* b, const char *fmt, ...) {
+  size_t have = b->cap - b->size;
+  size_t n;
+  va_list args;
+
+  va_start(args, fmt);
+  n = vsnprintf(&b->data[b->size], have, fmt, args);
+  va_end(args);
+
+  if (have <= n) {
+    while (have <= n) {
+      b->cap *= 2;
+      have = b->cap - b->size;
+    }
+    b->data = realloc(b->data, StringBuilder_SizeOf(b->cap));
+    va_start(args, fmt);
+    n = vsnprintf(&b->data[b->size], have, fmt, args);
+    va_end(args);
+    PBRUBY_ASSERT(n < have);
+  }
+
+  b->size += n;
+}
+
+VALUE StringBuilder_ToRubyString(StringBuilder* b) {
+  VALUE ret = rb_str_new(b->data, b->size);
+  rb_enc_associate(ret, rb_utf8_encoding());
+  return ret;
+}
+
+static void StringBuilder_PrintEnum(StringBuilder* b, int32_t val,
+                                    const upb_enumdef* e) {
+  const char *name = upb_enumdef_iton(e, val);
+  if (name) {
+    StringBuilder_Printf(b, ":%s", name);
   } else {
-    // It is harder to memoize non-empty strings.  The obvious approach would be
-    // to use a Ruby hash keyed by string as memo table, but looking up in such a table
-    // requires constructing a string (the very thing we're trying to avoid).
-    //
-    // Since few fields have defaults, we will just optimize the empty string
-    // case for now.
-    return create_frozen_string(str, size, binary);
+    StringBuilder_Printf(b, "%" PRId32, val);
+  }
+}
+
+void StringBuilder_PrintMsgval(StringBuilder* b, upb_msgval val,
+                               TypeInfo info) {
+  switch (info.type) {
+    case UPB_TYPE_BOOL:
+      StringBuilder_Printf(b, "%s", val.bool_val ? "true" : "false");
+      break;
+    case UPB_TYPE_FLOAT: {
+      VALUE str = rb_inspect(DBL2NUM(val.float_val));
+      StringBuilder_Printf(b, "%s", RSTRING_PTR(str));
+      break;
+    }
+    case UPB_TYPE_DOUBLE: {
+      VALUE str = rb_inspect(DBL2NUM(val.double_val));
+      StringBuilder_Printf(b, "%s", RSTRING_PTR(str));
+      break;
+    }
+    case UPB_TYPE_INT32:
+      StringBuilder_Printf(b, "%" PRId32, val.int32_val);
+      break;
+    case UPB_TYPE_UINT32:
+      StringBuilder_Printf(b, "%" PRIu32, val.uint32_val);
+      break;
+    case UPB_TYPE_INT64:
+      StringBuilder_Printf(b, "%" PRId64, val.int64_val);
+      break;
+    case UPB_TYPE_UINT64:
+      StringBuilder_Printf(b, "%" PRIu64, val.uint64_val);
+      break;
+    case UPB_TYPE_STRING:
+      StringBuilder_Printf(b, "\"%.*s\"", (int)val.str_val.size, val.str_val.data);
+      break;
+    case UPB_TYPE_BYTES:
+      StringBuilder_Printf(b, "\"%.*s\"", (int)val.str_val.size, val.str_val.data);
+      break;
+    case UPB_TYPE_ENUM:
+      StringBuilder_PrintEnum(b, val.int32_val, info.def.enumdef);
+      break;
+    case UPB_TYPE_MESSAGE:
+      Message_PrintMessage(b, val.msg_val, info.def.msgdef);
+      break;
   }
 }
 
 // -----------------------------------------------------------------------------
-// Utilities.
+// Arena
 // -----------------------------------------------------------------------------
 
-// Raises a Ruby error if |status| is not OK, using its error message.
-void check_upb_status(const upb_status* status, const char* msg) {
-  if (!upb_ok(status)) {
-    rb_raise(rb_eRuntimeError, "%s: %s\n", msg, upb_status_errmsg(status));
-  }
+void Arena_free(void* data) { upb_arena_free(data); }
+
+static VALUE cArena;
+
+const rb_data_type_t Arena_type = {
+  "Google::Protobuf::Internal::Arena",
+  { NULL, Arena_free, NULL },
+};
+
+static VALUE Arena_alloc(VALUE klass) {
+  upb_arena *arena = upb_arena_new();
+  return TypedData_Wrap_Struct(klass, &Arena_type, arena);
 }
 
-// String encodings: we look these up once, at load time, and then cache them
-// here.
-rb_encoding* kRubyStringUtf8Encoding;
-rb_encoding* kRubyStringASCIIEncoding;
-rb_encoding* kRubyString8bitEncoding;
+upb_arena *Arena_get(VALUE _arena) {
+  upb_arena *arena;
+  TypedData_Get_Struct(_arena, upb_arena, &Arena_type, arena);
+  return arena;
+}
 
-// Ruby-interned string: "descriptor". We use this identifier to store an
-// instance variable on message classes we create in order to link them back to
-// their descriptors.
+VALUE Arena_new() {
+  return Arena_alloc(cArena);
+}
+
+void Arena_register(VALUE module) {
+  VALUE internal = rb_define_module_under(module, "Internal");
+  VALUE klass = rb_define_class_under(internal, "Arena", rb_cObject);
+  rb_define_alloc_func(klass, Arena_alloc);
+  rb_gc_register_address(&cArena);
+  cArena = klass;
+}
+
+// -----------------------------------------------------------------------------
+// Object Cache
+// -----------------------------------------------------------------------------
+
+// A pointer -> Ruby Object cache that keeps references to Ruby wrapper
+// objects.  This allows us to look up any Ruby wrapper object by the address
+// of the object it is wrapping. That way we can avoid ever creating two
+// different wrapper objects for the same C object, which saves memory and
+// preserves object identity.
 //
-// We intern this once at module load time then use the interned identifier at
-// runtime in order to avoid the cost of repeatedly interning in hot paths.
-const char* kDescriptorInstanceVar = "descriptor";
-ID descriptor_instancevar_interned;
+// We use Hash and/or WeakMap for the cache. WeakMap is faster overall
+// (probably due to removal being integrated with GC) but doesn't work for Ruby
+// <2.7 (see note below). We need Hash for Ruby <2.7 and for cases where we
+// need to GC-root the object (notably when the object has been frozen).
+
+#if RUBY_API_VERSION_CODE >= 20700
+#define USE_WEAK_MAP 1
+#else
+#define USE_WEAK_MAP 0
+#endif
+
+static VALUE ObjectCache_GetKey(const void* key) {
+  char buf[sizeof(key)];
+  memcpy(&buf, &key, sizeof(key));
+  intptr_t key_int = (intptr_t)key;
+  PBRUBY_ASSERT((key_int & 3) == 0);
+  return LL2NUM(key_int >> 2);
+}
+
+// Strong object cache, uses regular Hash and GC-roots objects.
+// - For Ruby <2.7, used for all objects.
+// - For Ruby >=2.7, used only for frozen objects, so we preserve the "frozen"
+//   bit (since this information is not preserved at the upb level).
+
+VALUE strong_obj_cache = Qnil;
+
+static void StrongObjectCache_Init() {
+  rb_gc_register_address(&strong_obj_cache);
+  strong_obj_cache = rb_hash_new();
+}
+
+static void StrongObjectCache_Remove(void* key) {
+  VALUE key_rb = ObjectCache_GetKey(key);
+  PBRUBY_ASSERT(rb_hash_lookup(strong_obj_cache, key_rb) != Qnil);
+  rb_hash_delete(strong_obj_cache, key_rb);
+}
+
+static VALUE StrongObjectCache_Get(const void* key) {
+  VALUE key_rb = ObjectCache_GetKey(key);
+  return rb_hash_lookup(strong_obj_cache, key_rb);
+}
+
+static void StrongObjectCache_Add(const void* key, VALUE val,
+                                  upb_arena* arena) {
+  PBRUBY_ASSERT(StrongObjectCache_Get(key) == Qnil);
+  VALUE key_rb = ObjectCache_GetKey(key);
+  rb_hash_aset(strong_obj_cache, key_rb, val);
+  upb_arena_addcleanup(arena, (void*)key, StrongObjectCache_Remove);
+}
+
+// Weak object cache. This speeds up the test suite significantly, so we
+// presume it speeds up real code also. However we can only use it in Ruby
+// >=2.7 due to:
+//   https://bugs.ruby-lang.org/issues/16035
+
+#if USE_WEAK_MAP
+
+VALUE weak_obj_cache = Qnil;
+
+static void WeakObjectCache_Init() {
+  rb_gc_register_address(&weak_obj_cache);
+  VALUE klass = rb_eval_string("ObjectSpace::WeakMap");
+  weak_obj_cache = rb_class_new_instance(0, NULL, klass);
+}
+
+static VALUE WeakObjectCache_Get(const void* key) {
+  VALUE key_rb = ObjectCache_GetKey(key);
+  VALUE ret = rb_funcall(weak_obj_cache, rb_intern("[]"), 1, key_rb);
+  return ret;
+}
+
+static void WeakObjectCache_Add(const void* key, VALUE val) {
+  PBRUBY_ASSERT(WeakObjectCache_Get(key) == Qnil);
+  VALUE key_rb = ObjectCache_GetKey(key);
+  rb_funcall(weak_obj_cache, rb_intern("[]="), 2, key_rb, val);
+  PBRUBY_ASSERT(WeakObjectCache_Get(key) == val);
+}
+
+#endif
+
+// Public ObjectCache API.
+
+static void ObjectCache_Init() {
+  StrongObjectCache_Init();
+#if USE_WEAK_MAP
+  WeakObjectCache_Init();
+#endif
+}
+
+void ObjectCache_Add(const void* key, VALUE val, upb_arena *arena) {
+#if USE_WEAK_MAP
+  (void)arena;
+  WeakObjectCache_Add(key, val);
+#else
+  StrongObjectCache_Add(key, val, arena);
+#endif
+}
+
+// Returns the cached object for this key, if any. Otherwise returns Qnil.
+VALUE ObjectCache_Get(const void* key) {
+#if USE_WEAK_MAP
+  return WeakObjectCache_Get(key);
+#else
+  return StrongObjectCache_Get(key);
+#endif
+}
+
+void ObjectCache_Pin(const void* key, VALUE val, upb_arena *arena) {
+#if USE_WEAK_MAP
+  PBRUBY_ASSERT(WeakObjectCache_Get(key) == val);
+  // This will GC-root the object, but we'll still use the weak map for
+  // actual lookup.
+  StrongObjectCache_Add(key, val, arena);
+#else
+  // Value is already pinned, nothing to do.
+#endif
+}
+
+/*
+ * call-seq:
+ *     Google::Protobuf.discard_unknown(msg)
+ *
+ * Discard unknown fields in the given message object and recursively discard
+ * unknown fields in submessages.
+ */
+static VALUE Google_Protobuf_discard_unknown(VALUE self, VALUE msg_rb) {
+  const upb_msgdef *m;
+  upb_msg *msg = Message_GetMutable(msg_rb, &m);
+  if (!upb_msg_discardunknown(msg, m, 128)) {
+    rb_raise(rb_eRuntimeError, "Messages nested too deeply.");
+  }
+
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *     Google::Protobuf.deep_copy(obj) => copy_of_obj
+ *
+ * Performs a deep copy of a RepeatedField instance, a Map instance, or a
+ * message object, recursively copying its members.
+ */
+VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj) {
+  VALUE klass = CLASS_OF(obj);
+  if (klass == cRepeatedField) {
+    return RepeatedField_deep_copy(obj);
+  } else if (klass == cMap) {
+    return Map_deep_copy(obj);
+  } else {
+    VALUE new_arena_rb = Arena_new();
+    upb_arena *new_arena = Arena_get(new_arena_rb);
+    const upb_msgdef *m;
+    const upb_msg *msg = Message_Get(obj, &m);
+    upb_msg* new_msg = Message_deep_copy(msg, m, new_arena);
+    return Message_GetRubyWrapper(new_msg, m, new_arena_rb);
+  }
+}
 
 // -----------------------------------------------------------------------------
 // Initialization/entry point.
@@ -93,44 +373,24 @@
 
 // This must be named "Init_protobuf_c" because the Ruby module is named
 // "protobuf_c" -- the VM looks for this symbol in our .so.
+__attribute__ ((visibility ("default")))
 void Init_protobuf_c() {
+  ObjectCache_Init();
+
   VALUE google = rb_define_module("Google");
   VALUE protobuf = rb_define_module_under(google, "Protobuf");
-  VALUE internal = rb_define_module_under(protobuf, "Internal");
 
-  descriptor_instancevar_interned = rb_intern(kDescriptorInstanceVar);
-  DescriptorPool_register(protobuf);
-  Descriptor_register(protobuf);
-  FileDescriptor_register(protobuf);
-  FieldDescriptor_register(protobuf);
-  OneofDescriptor_register(protobuf);
-  EnumDescriptor_register(protobuf);
-  MessageBuilderContext_register(internal);
-  OneofBuilderContext_register(internal);
-  EnumBuilderContext_register(internal);
-  FileBuilderContext_register(internal);
-  Builder_register(internal);
+  Arena_register(protobuf);
+  Defs_register(protobuf);
   RepeatedField_register(protobuf);
   Map_register(protobuf);
+  Message_register(protobuf);
 
   cError = rb_const_get(protobuf, rb_intern("Error"));
-  cParseError = rb_const_get(protobuf, rb_intern("ParseError"));
   cTypeError = rb_const_get(protobuf, rb_intern("TypeError"));
 
   rb_define_singleton_method(protobuf, "discard_unknown",
                              Google_Protobuf_discard_unknown, 1);
   rb_define_singleton_method(protobuf, "deep_copy",
                              Google_Protobuf_deep_copy, 1);
-
-  kRubyStringUtf8Encoding = rb_utf8_encoding();
-  kRubyStringASCIIEncoding = rb_usascii_encoding();
-  kRubyString8bitEncoding = rb_ascii8bit_encoding();
-
-  rb_gc_register_address(&c_only_cookie);
-  c_only_cookie = rb_class_new_instance(0, NULL, rb_cObject);
-
-  rb_gc_register_address(&cached_empty_string);
-  rb_gc_register_address(&cached_empty_bytes);
-  cached_empty_string = create_frozen_string("", 0, false);
-  cached_empty_bytes = create_frozen_string("", 0, true);
 }
diff --git a/ruby/ext/google/protobuf_c/protobuf.h b/ruby/ext/google/protobuf_c/protobuf.h
index 0ec78fc..90fb0a2 100644
--- a/ruby/ext/google/protobuf_c/protobuf.h
+++ b/ruby/ext/google/protobuf_c/protobuf.h
@@ -35,631 +35,76 @@
 #include <ruby/vm.h>
 #include <ruby/encoding.h>
 
-#include "upb.h"
-
-// Forward decls.
-struct DescriptorPool;
-struct Descriptor;
-struct FileDescriptor;
-struct FieldDescriptor;
-struct EnumDescriptor;
-struct MessageLayout;
-struct MessageField;
-struct MessageHeader;
-struct MessageBuilderContext;
-struct EnumBuilderContext;
-struct FileBuilderContext;
-struct Builder;
-
-typedef struct DescriptorPool DescriptorPool;
-typedef struct Descriptor Descriptor;
-typedef struct FileDescriptor FileDescriptor;
-typedef struct FieldDescriptor FieldDescriptor;
-typedef struct OneofDescriptor OneofDescriptor;
-typedef struct EnumDescriptor EnumDescriptor;
-typedef struct MessageLayout MessageLayout;
-typedef struct MessageField MessageField;
-typedef struct MessageOneof MessageOneof;
-typedef struct MessageHeader MessageHeader;
-typedef struct MessageBuilderContext MessageBuilderContext;
-typedef struct OneofBuilderContext OneofBuilderContext;
-typedef struct EnumBuilderContext EnumBuilderContext;
-typedef struct FileBuilderContext FileBuilderContext;
-typedef struct Builder Builder;
-
-/*
- It can be a bit confusing how the C structs defined below and the Ruby
- objects interact and hold references to each other. First, a few principles:
-
- - Ruby's "TypedData" abstraction lets a Ruby VALUE hold a pointer to a C
-   struct (or arbitrary memory chunk), own it, and free it when collected.
-   Thus, each struct below will have a corresponding Ruby object
-   wrapping/owning it.
-
- - To get back from an underlying upb {msg,enum}def to the Ruby object, we
-   keep a global hashmap, accessed by get_def_obj/add_def_obj below.
-
- The in-memory structure is then something like:
-
-   Ruby                        |      upb
-                               |
-   DescriptorPool  ------------|-----------> upb_symtab____________________
-                               |                | (message types)          \
-                               |                v                           \
-   Descriptor   ---------------|-----------> upb_msgdef         (enum types)|
-    |--> msgclass              |                |   ^                       |
-    |    (dynamically built)   |                |   | (submsg fields)       |
-    |--> MessageLayout         |                |   |                       /
-    |--------------------------|> decoder method|   |                      /
-    \--------------------------|> serialize     |   |                     /
-                               |  handlers      v   |                    /
-   FieldDescriptor  -----------|-----------> upb_fielddef               /
-                               |                    |                  /
-                               |                    v (enum fields)   /
-   EnumDescriptor  ------------|-----------> upb_enumdef  <----------'
-                               |
-                               |
-               ^               |               \___/
-               `---------------|-----------------'    (get_def_obj map)
- */
-
-// -----------------------------------------------------------------------------
-// Ruby class structure definitions.
-// -----------------------------------------------------------------------------
-
-struct DescriptorPool {
-  VALUE def_to_descriptor;  // Hash table of def* -> Ruby descriptor.
-  upb_symtab* symtab;
-  upb_handlercache* fill_handler_cache;
-  upb_handlercache* pb_serialize_handler_cache;
-  upb_handlercache* json_serialize_handler_cache;
-  upb_handlercache* json_serialize_handler_preserve_cache;
-  upb_pbcodecache* fill_method_cache;
-  upb_json_codecache* json_fill_method_cache;
-};
-
-struct Descriptor {
-  const upb_msgdef* msgdef;
-  MessageLayout* layout;
-  VALUE klass;
-  VALUE descriptor_pool;
-};
-
-struct FileDescriptor {
-  const upb_filedef* filedef;
-  VALUE descriptor_pool;  // Owns the upb_filedef.
-};
-
-struct FieldDescriptor {
-  const upb_fielddef* fielddef;
-  VALUE descriptor_pool;  // Owns the upb_fielddef.
-};
-
-struct OneofDescriptor {
-  const upb_oneofdef* oneofdef;
-  VALUE descriptor_pool;  // Owns the upb_oneofdef.
-};
-
-struct EnumDescriptor {
-  const upb_enumdef* enumdef;
-  VALUE module;  // begins as nil
-  VALUE descriptor_pool;  // Owns the upb_enumdef.
-};
-
-struct MessageBuilderContext {
-  google_protobuf_DescriptorProto* msg_proto;
-  VALUE file_builder;
-};
-
-struct OneofBuilderContext {
-  int oneof_index;
-  VALUE message_builder;
-};
-
-struct EnumBuilderContext {
-  google_protobuf_EnumDescriptorProto* enum_proto;
-  VALUE file_builder;
-};
-
-struct FileBuilderContext {
-  upb_arena *arena;
-  google_protobuf_FileDescriptorProto* file_proto;
-  VALUE descriptor_pool;
-};
-
-struct Builder {
-  VALUE descriptor_pool;
-  VALUE default_file_builder;
-};
-
-extern VALUE cDescriptorPool;
-extern VALUE cDescriptor;
-extern VALUE cFileDescriptor;
-extern VALUE cFieldDescriptor;
-extern VALUE cEnumDescriptor;
-extern VALUE cMessageBuilderContext;
-extern VALUE cOneofBuilderContext;
-extern VALUE cEnumBuilderContext;
-extern VALUE cFileBuilderContext;
-extern VALUE cBuilder;
-
-extern VALUE cError;
-extern VALUE cParseError;
-extern VALUE cTypeError;
-
-// We forward-declare all of the Ruby method implementations here because we
-// sometimes call the methods directly across .c files, rather than going
-// through Ruby's method dispatching (e.g. during message parse). It's cleaner
-// to keep the list of object methods together than to split them between
-// static-in-file definitions and header declarations.
-
-void DescriptorPool_mark(void* _self);
-void DescriptorPool_free(void* _self);
-VALUE DescriptorPool_alloc(VALUE klass);
-void DescriptorPool_register(VALUE module);
-DescriptorPool* ruby_to_DescriptorPool(VALUE value);
-VALUE DescriptorPool_build(int argc, VALUE* argv, VALUE _self);
-VALUE DescriptorPool_lookup(VALUE _self, VALUE name);
-VALUE DescriptorPool_generated_pool(VALUE _self);
-
-extern VALUE generated_pool;
-
-void Descriptor_mark(void* _self);
-void Descriptor_free(void* _self);
-VALUE Descriptor_alloc(VALUE klass);
-void Descriptor_register(VALUE module);
-Descriptor* ruby_to_Descriptor(VALUE value);
-VALUE Descriptor_initialize(VALUE _self, VALUE cookie, VALUE descriptor_pool,
-                            VALUE ptr);
-VALUE Descriptor_name(VALUE _self);
-VALUE Descriptor_each(VALUE _self);
-VALUE Descriptor_lookup(VALUE _self, VALUE name);
-VALUE Descriptor_each_oneof(VALUE _self);
-VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name);
-VALUE Descriptor_msgclass(VALUE _self);
-VALUE Descriptor_file_descriptor(VALUE _self);
-extern const rb_data_type_t _Descriptor_type;
-
-void FileDescriptor_mark(void* _self);
-void FileDescriptor_free(void* _self);
-VALUE FileDescriptor_alloc(VALUE klass);
-void FileDescriptor_register(VALUE module);
-FileDescriptor* ruby_to_FileDescriptor(VALUE value);
-VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie,
-                                VALUE descriptor_pool, VALUE ptr);
-VALUE FileDescriptor_name(VALUE _self);
-VALUE FileDescriptor_syntax(VALUE _self);
-
-void FieldDescriptor_mark(void* _self);
-void FieldDescriptor_free(void* _self);
-VALUE FieldDescriptor_alloc(VALUE klass);
-void FieldDescriptor_register(VALUE module);
-FieldDescriptor* ruby_to_FieldDescriptor(VALUE value);
-VALUE FieldDescriptor_initialize(VALUE _self, VALUE cookie,
-                                 VALUE descriptor_pool, VALUE ptr);
-VALUE FieldDescriptor_name(VALUE _self);
-VALUE FieldDescriptor_type(VALUE _self);
-VALUE FieldDescriptor_default(VALUE _self);
-VALUE FieldDescriptor_label(VALUE _self);
-VALUE FieldDescriptor_number(VALUE _self);
-VALUE FieldDescriptor_submsg_name(VALUE _self);
-VALUE FieldDescriptor_subtype(VALUE _self);
-VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb);
-VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb);
-VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb);
-VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value);
-upb_fieldtype_t ruby_to_fieldtype(VALUE type);
-VALUE fieldtype_to_ruby(upb_fieldtype_t type);
-
-void OneofDescriptor_mark(void* _self);
-void OneofDescriptor_free(void* _self);
-VALUE OneofDescriptor_alloc(VALUE klass);
-void OneofDescriptor_register(VALUE module);
-OneofDescriptor* ruby_to_OneofDescriptor(VALUE value);
-VALUE OneofDescriptor_initialize(VALUE _self, VALUE cookie,
-                                 VALUE descriptor_pool, VALUE ptr);
-VALUE OneofDescriptor_name(VALUE _self);
-VALUE OneofDescriptor_each(VALUE _self);
-
-void EnumDescriptor_mark(void* _self);
-void EnumDescriptor_free(void* _self);
-VALUE EnumDescriptor_alloc(VALUE klass);
-VALUE EnumDescriptor_initialize(VALUE _self, VALUE cookie,
-                                VALUE descriptor_pool, VALUE ptr);
-void EnumDescriptor_register(VALUE module);
-EnumDescriptor* ruby_to_EnumDescriptor(VALUE value);
-VALUE EnumDescriptor_file_descriptor(VALUE _self);
-VALUE EnumDescriptor_name(VALUE _self);
-VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name);
-VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number);
-VALUE EnumDescriptor_each(VALUE _self);
-VALUE EnumDescriptor_enummodule(VALUE _self);
-extern const rb_data_type_t _EnumDescriptor_type;
-
-void MessageBuilderContext_mark(void* _self);
-void MessageBuilderContext_free(void* _self);
-VALUE MessageBuilderContext_alloc(VALUE klass);
-void MessageBuilderContext_register(VALUE module);
-MessageBuilderContext* ruby_to_MessageBuilderContext(VALUE value);
-VALUE MessageBuilderContext_initialize(VALUE _self,
-                                       VALUE _file_builder,
-                                       VALUE name);
-VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self);
-VALUE MessageBuilderContext_proto3_optional(int argc, VALUE* argv, VALUE _self);
-VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self);
-VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self);
-VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self);
-VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name);
-
-void OneofBuilderContext_mark(void* _self);
-void OneofBuilderContext_free(void* _self);
-VALUE OneofBuilderContext_alloc(VALUE klass);
-void OneofBuilderContext_register(VALUE module);
-OneofBuilderContext* ruby_to_OneofBuilderContext(VALUE value);
-VALUE OneofBuilderContext_initialize(VALUE _self,
-                                     VALUE descriptor,
-                                     VALUE builder);
-VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self);
-
-void EnumBuilderContext_mark(void* _self);
-void EnumBuilderContext_free(void* _self);
-VALUE EnumBuilderContext_alloc(VALUE klass);
-void EnumBuilderContext_register(VALUE module);
-EnumBuilderContext* ruby_to_EnumBuilderContext(VALUE value);
-VALUE EnumBuilderContext_initialize(VALUE _self, VALUE _file_builder,
-                                    VALUE name);
-VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number);
-
-void FileBuilderContext_mark(void* _self);
-void FileBuilderContext_free(void* _self);
-VALUE FileBuilderContext_alloc(VALUE klass);
-void FileBuilderContext_register(VALUE module);
-FileBuilderContext* ruby_to_FileBuilderContext(VALUE _self);
-upb_strview FileBuilderContext_strdup(VALUE _self, VALUE rb_str);
-upb_strview FileBuilderContext_strdup_name(VALUE _self, VALUE rb_str);
-upb_strview FileBuilderContext_strdup_sym(VALUE _self, VALUE rb_sym);
-VALUE FileBuilderContext_initialize(VALUE _self, VALUE descriptor_pool,
-                                    VALUE name, VALUE options);
-VALUE FileBuilderContext_add_message(VALUE _self, VALUE name);
-VALUE FileBuilderContext_add_enum(VALUE _self, VALUE name);
-VALUE FileBuilderContext_pending_descriptors(VALUE _self);
-
-void Builder_mark(void* _self);
-void Builder_free(void* _self);
-VALUE Builder_alloc(VALUE klass);
-void Builder_register(VALUE module);
-Builder* ruby_to_Builder(VALUE value);
-VALUE Builder_build(VALUE _self);
-VALUE Builder_initialize(VALUE _self, VALUE descriptor_pool);
-VALUE Builder_add_file(int argc, VALUE *argv, VALUE _self);
-VALUE Builder_add_message(VALUE _self, VALUE name);
-VALUE Builder_add_enum(VALUE _self, VALUE name);
-VALUE Builder_finalize_to_pool(VALUE _self, VALUE pool_rb);
-
-// -----------------------------------------------------------------------------
-// Native slot storage abstraction.
-// -----------------------------------------------------------------------------
-
-#define NATIVE_SLOT_MAX_SIZE sizeof(uint64_t)
-
-size_t native_slot_size(upb_fieldtype_t type);
-void native_slot_set(const char* name,
-                     upb_fieldtype_t type,
-                     VALUE type_class,
-                     void* memory,
-                     VALUE value);
-// Atomically (with respect to Ruby VM calls) either update the value and set a
-// oneof case, or do neither. If |case_memory| is null, then no case value is
-// set.
-void native_slot_set_value_and_case(const char* name,
-                                    upb_fieldtype_t type,
-                                    VALUE type_class,
-                                    void* memory,
-                                    VALUE value,
-                                    uint32_t* case_memory,
-                                    uint32_t case_number);
-VALUE native_slot_get(upb_fieldtype_t type,
-                      VALUE type_class,
-                      const void* memory);
-void native_slot_init(upb_fieldtype_t type, void* memory);
-void native_slot_mark(upb_fieldtype_t type, void* memory);
-void native_slot_dup(upb_fieldtype_t type, void* to, void* from);
-void native_slot_deep_copy(upb_fieldtype_t type, VALUE type_class, void* to,
-                           void* from);
-bool native_slot_eq(upb_fieldtype_t type, VALUE type_class, void* mem1,
-                    void* mem2);
-
-VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value);
-void native_slot_check_int_range_precision(const char* name, upb_fieldtype_t type, VALUE value);
-uint32_t slot_read_oneof_case(MessageLayout* layout, const void* storage,
-                              const upb_oneofdef* oneof);
-bool is_value_field(const upb_fielddef* f);
-
-extern rb_encoding* kRubyStringUtf8Encoding;
-extern rb_encoding* kRubyStringASCIIEncoding;
-extern rb_encoding* kRubyString8bitEncoding;
-
-VALUE field_type_class(const MessageLayout* layout, const upb_fielddef* field);
-
-#define MAP_KEY_FIELD 1
-#define MAP_VALUE_FIELD 2
-
-// Oneof case slot value to indicate that no oneof case is set. The value `0` is
-// safe because field numbers are used as case identifiers, and no field can
-// have a number of 0.
-#define ONEOF_CASE_NONE 0
+#include "ruby-upb.h"
+#include "defs.h"
 
 // These operate on a map field (i.e., a repeated field of submessages whose
 // submessage type is a map-entry msgdef).
-bool is_map_field(const upb_fielddef* field);
 const upb_fielddef* map_field_key(const upb_fielddef* field);
 const upb_fielddef* map_field_value(const upb_fielddef* field);
 
-// These operate on a map-entry msgdef.
-const upb_fielddef* map_entry_key(const upb_msgdef* msgdef);
-const upb_fielddef* map_entry_value(const upb_msgdef* msgdef);
-
 // -----------------------------------------------------------------------------
-// Repeated field container type.
+// Arena
 // -----------------------------------------------------------------------------
 
-typedef struct {
-  upb_fieldtype_t field_type;
-  VALUE field_type_class;
-  void* elements;
-  int size;
-  int capacity;
-} RepeatedField;
+// A Ruby object that wraps an underlying upb_arena.  Any objects that are
+// allocated from this arena should reference the Arena in rb_gc_mark(), to
+// ensure that the object's underlying memory outlives any Ruby object that can
+// reach it.
 
-void RepeatedField_mark(void* self);
-void RepeatedField_free(void* self);
-VALUE RepeatedField_alloc(VALUE klass);
-VALUE RepeatedField_init(int argc, VALUE* argv, VALUE self);
-void RepeatedField_register(VALUE module);
-
-extern const rb_data_type_t RepeatedField_type;
-extern VALUE cRepeatedField;
-
-RepeatedField* ruby_to_RepeatedField(VALUE value);
-
-VALUE RepeatedField_new_this_type(VALUE _self);
-VALUE RepeatedField_each(VALUE _self);
-VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self);
-void* RepeatedField_index_native(VALUE _self, int index);
-int RepeatedField_size(VALUE _self);
-VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val);
-void RepeatedField_reserve(RepeatedField* self, int new_size);
-VALUE RepeatedField_push(VALUE _self, VALUE val);
-void RepeatedField_push_native(VALUE _self, void* data);
-VALUE RepeatedField_pop_one(VALUE _self);
-VALUE RepeatedField_insert(int argc, VALUE* argv, VALUE _self);
-VALUE RepeatedField_replace(VALUE _self, VALUE list);
-VALUE RepeatedField_clear(VALUE _self);
-VALUE RepeatedField_length(VALUE _self);
-VALUE RepeatedField_dup(VALUE _self);
-VALUE RepeatedField_deep_copy(VALUE _self);
-VALUE RepeatedField_to_ary(VALUE _self);
-VALUE RepeatedField_eq(VALUE _self, VALUE _other);
-VALUE RepeatedField_hash(VALUE _self);
-VALUE RepeatedField_inspect(VALUE _self);
-VALUE RepeatedField_plus(VALUE _self, VALUE list);
-
-// Defined in repeated_field.c; also used by Map.
-void validate_type_class(upb_fieldtype_t type, VALUE klass);
+VALUE Arena_new();
+upb_arena *Arena_get(VALUE arena);
 
 // -----------------------------------------------------------------------------
-// Map container type.
+// ObjectCache
 // -----------------------------------------------------------------------------
 
-typedef struct {
-  upb_fieldtype_t key_type;
-  upb_fieldtype_t value_type;
-  VALUE value_type_class;
-  VALUE parse_frame;
-  upb_strtable table;
-} Map;
+// Global object cache from upb array/map/message/symtab to wrapper object.
+//
+// This is a conceptually "weak" cache, in that it does not prevent "val" from
+// being collected (though in Ruby <2.7 is it effectively strong, due to
+// implementation limitations).
 
-void Map_mark(void* self);
-void Map_free(void* self);
-VALUE Map_alloc(VALUE klass);
-VALUE Map_init(int argc, VALUE* argv, VALUE self);
-void Map_register(VALUE module);
-VALUE Map_set_frame(VALUE self, VALUE val);
+// Adds an entry to the cache. The "arena" parameter must give the arena that
+// "key" was allocated from.  In Ruby <2.7.0, it will be used to remove the key
+// from the cache when the arena is destroyed.
+void ObjectCache_Add(const void* key, VALUE val, upb_arena *arena);
 
-extern const rb_data_type_t Map_type;
-extern VALUE cMap;
+// Returns the cached object for this key, if any. Otherwise returns Qnil.
+VALUE ObjectCache_Get(const void* key);
 
-Map* ruby_to_Map(VALUE value);
-
-VALUE Map_new_this_type(VALUE _self);
-VALUE Map_each(VALUE _self);
-VALUE Map_keys(VALUE _self);
-VALUE Map_values(VALUE _self);
-VALUE Map_index(VALUE _self, VALUE key);
-VALUE Map_index_set(VALUE _self, VALUE key, VALUE value);
-VALUE Map_has_key(VALUE _self, VALUE key);
-VALUE Map_delete(VALUE _self, VALUE key);
-VALUE Map_clear(VALUE _self);
-VALUE Map_length(VALUE _self);
-VALUE Map_dup(VALUE _self);
-VALUE Map_deep_copy(VALUE _self);
-VALUE Map_eq(VALUE _self, VALUE _other);
-VALUE Map_hash(VALUE _self);
-VALUE Map_to_h(VALUE _self);
-VALUE Map_inspect(VALUE _self);
-VALUE Map_merge(VALUE _self, VALUE hashmap);
-VALUE Map_merge_into_self(VALUE _self, VALUE hashmap);
-
-typedef struct {
-  Map* self;
-  upb_strtable_iter it;
-} Map_iter;
-
-void Map_begin(VALUE _self, Map_iter* iter);
-void Map_next(Map_iter* iter);
-bool Map_done(Map_iter* iter);
-VALUE Map_iter_key(Map_iter* iter);
-VALUE Map_iter_value(Map_iter* iter);
+// Pins the previously added object so it is GC-rooted. This turns the
+// reference to "val" from weak to strong.  We use this to guarantee that the
+// "frozen" bit on the object will be remembered, even if the user drops their
+// reference to this precise object.
+//
+// The "arena" parameter must give the arena that "key" was allocated from.
+void ObjectCache_Pin(const void* key, VALUE val, upb_arena *arena);
 
 // -----------------------------------------------------------------------------
-// Message layout / storage.
+// StringBuilder, for inspect
 // -----------------------------------------------------------------------------
 
-#define MESSAGE_FIELD_NO_HASBIT ((uint32_t)-1)
+struct StringBuilder;
+typedef struct StringBuilder StringBuilder;
 
-struct MessageField {
-  uint32_t offset;
-  uint32_t hasbit;
-};
+StringBuilder* StringBuilder_New();
+void StringBuilder_Free(StringBuilder* b);
+void StringBuilder_Printf(StringBuilder* b, const char *fmt, ...);
+VALUE StringBuilder_ToRubyString(StringBuilder* b);
 
-struct MessageOneof {
-  uint32_t offset;
-  uint32_t case_offset;
-};
-
-// MessageLayout is owned by the enclosing Descriptor, which must outlive us.
-struct MessageLayout {
-  const Descriptor* desc;
-  const upb_msgdef* msgdef;
-  void* empty_template;  // Can memcpy() onto a layout to clear it.
-  MessageField* fields;
-  MessageOneof* oneofs;
-  uint32_t size;
-  uint32_t value_offset;
-  int value_count;
-  int repeated_count;
-  int map_count;
-};
-
-#define ONEOF_CASE_MASK 0x80000000
-
-void create_layout(Descriptor* desc);
-void free_layout(MessageLayout* layout);
-bool field_contains_hasbit(MessageLayout* layout,
-                 const upb_fielddef* field);
-VALUE layout_get_default(const upb_fielddef* field);
-VALUE layout_get(MessageLayout* layout,
-                 const void* storage,
-                 const upb_fielddef* field);
-void layout_set(MessageLayout* layout,
-                void* storage,
-                const upb_fielddef* field,
-                VALUE val);
-VALUE layout_has(MessageLayout* layout,
-                 const void* storage,
-                 const upb_fielddef* field);
-void layout_clear(MessageLayout* layout,
-                 const void* storage,
-                 const upb_fielddef* field);
-void layout_init(MessageLayout* layout, void* storage);
-void layout_mark(MessageLayout* layout, void* storage);
-void layout_dup(MessageLayout* layout, void* to, void* from);
-void layout_deep_copy(MessageLayout* layout, void* to, void* from);
-VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2);
-VALUE layout_hash(MessageLayout* layout, void* storage);
-VALUE layout_inspect(MessageLayout* layout, void* storage);
-
-bool is_wrapper_type_field(const upb_fielddef* field);
-VALUE ruby_wrapper_type(VALUE type_class, VALUE value);
-
-// -----------------------------------------------------------------------------
-// Message class creation.
-// -----------------------------------------------------------------------------
-
-// This should probably be factored into a common upb component.
-
-typedef struct {
-  upb_byteshandler handler;
-  upb_bytessink sink;
-  char *ptr;
-  size_t len, size;
-} stringsink;
-
-void stringsink_uninit(stringsink *sink);
-
-struct MessageHeader {
-  Descriptor* descriptor;      // kept alive by self.class.descriptor reference.
-  stringsink* unknown_fields;  // store unknown fields in decoding.
-  // Data comes after this.
-};
-
-extern rb_data_type_t Message_type;
-
-VALUE build_class_from_descriptor(VALUE descriptor);
-void* Message_data(void* msg);
-void Message_mark(void* self);
-void Message_free(void* self);
-VALUE Message_alloc(VALUE klass);
-VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self);
-VALUE Message_initialize(int argc, VALUE* argv, VALUE _self);
-VALUE Message_dup(VALUE _self);
-VALUE Message_deep_copy(VALUE _self);
-VALUE Message_eq(VALUE _self, VALUE _other);
-VALUE Message_hash(VALUE _self);
-VALUE Message_inspect(VALUE _self);
-VALUE Message_to_h(VALUE _self);
-VALUE Message_index(VALUE _self, VALUE field_name);
-VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value);
-VALUE Message_descriptor(VALUE klass);
-VALUE Message_decode(VALUE klass, VALUE data);
-VALUE Message_encode(VALUE klass, VALUE msg_rb);
-VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass);
-VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass);
-
-VALUE Google_Protobuf_discard_unknown(VALUE self, VALUE msg_rb);
-VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj);
-
-VALUE build_module_from_enumdesc(VALUE _enumdesc);
-VALUE enum_lookup(VALUE self, VALUE number);
-VALUE enum_resolve(VALUE self, VALUE sym);
-VALUE enum_descriptor(VALUE self);
-
-const upb_pbdecodermethod *new_fillmsg_decodermethod(
-    Descriptor* descriptor, const void *owner);
-void add_handlers_for_message(const void *closure, upb_handlers *h);
-
-// Maximum depth allowed during encoding, to avoid stack overflows due to
-// cycles.
-#define ENCODE_MAX_NESTING 63
-
-// -----------------------------------------------------------------------------
-// A cache of frozen string objects to use as field defaults.
-// -----------------------------------------------------------------------------
-VALUE get_frozen_string(const char* data, size_t size, bool binary);
-
-// -----------------------------------------------------------------------------
-// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
-// instances.
-// -----------------------------------------------------------------------------
-VALUE get_msgdef_obj(VALUE descriptor_pool, const upb_msgdef* def);
-VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_enumdef* def);
-VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_fielddef* def);
-VALUE get_filedef_obj(VALUE descriptor_pool, const upb_filedef* def);
-VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_oneofdef* def);
+void StringBuilder_PrintMsgval(StringBuilder* b, upb_msgval val, TypeInfo info);
 
 // -----------------------------------------------------------------------------
 // Utilities.
 // -----------------------------------------------------------------------------
 
-void check_upb_status(const upb_status* status, const char* msg);
-
-#define CHECK_UPB(code, msg) do {                                             \
-    upb_status status = UPB_STATUS_INIT;                                      \
-    code;                                                                     \
-    check_upb_status(&status, msg);                                           \
-} while (0)
-
-extern ID descriptor_instancevar_interned;
-
-// A distinct object that is not accessible from Ruby.  We use this as a
-// constructor argument to enforce that certain objects cannot be created from
-// Ruby.
-extern VALUE c_only_cookie;
+extern VALUE cTypeError;
 
 #ifdef NDEBUG
-#define UPB_ASSERT(expr) do {} while (false && (expr))
+#define PBRUBY_ASSERT(expr) do {} while (false && (expr))
 #else
-#define UPB_ASSERT(expr) assert(expr)
+#define PBRUBY_ASSERT(expr) assert(expr)
 #endif
 
 #define UPB_UNUSED(var) (void)var
diff --git a/ruby/ext/google/protobuf_c/repeated_field.c b/ruby/ext/google/protobuf_c/repeated_field.c
index e3afb28..65ca3c6 100644
--- a/ruby/ext/google/protobuf_c/repeated_field.c
+++ b/ruby/ext/google/protobuf_c/repeated_field.c
@@ -28,49 +28,162 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#include "repeated_field.h"
+
+#include "convert.h"
+#include "defs.h"
+#include "message.h"
 #include "protobuf.h"
+#include "third_party/wyhash/wyhash.h"
 
 // -----------------------------------------------------------------------------
 // Repeated field container type.
 // -----------------------------------------------------------------------------
 
-const rb_data_type_t RepeatedField_type = {
-  "Google::Protobuf::RepeatedField",
-  { RepeatedField_mark, RepeatedField_free, NULL },
-};
+typedef struct {
+  const upb_array *array;   // Can get as mutable when non-frozen.
+  TypeInfo type_info;
+  VALUE type_class;  // To GC-root the msgdef/enumdef in type_info.
+  VALUE arena;       // To GC-root the upb_array.
+} RepeatedField;
 
 VALUE cRepeatedField;
 
-RepeatedField* ruby_to_RepeatedField(VALUE _self) {
+static void RepeatedField_mark(void* _self) {
+  RepeatedField* self = (RepeatedField*)_self;
+  rb_gc_mark(self->type_class);
+  rb_gc_mark(self->arena);
+}
+
+const rb_data_type_t RepeatedField_type = {
+  "Google::Protobuf::RepeatedField",
+  { RepeatedField_mark, RUBY_DEFAULT_FREE, NULL },
+  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static RepeatedField* ruby_to_RepeatedField(VALUE _self) {
   RepeatedField* self;
   TypedData_Get_Struct(_self, RepeatedField, &RepeatedField_type, self);
   return self;
 }
 
-void* RepeatedField_memoryat(RepeatedField* self, int index, int element_size) {
-  return ((uint8_t *)self->elements) + index * element_size;
+static upb_array *RepeatedField_GetMutable(VALUE _self) {
+  rb_check_frozen(_self);
+  return (upb_array*)ruby_to_RepeatedField(_self)->array;
+}
+
+VALUE RepeatedField_alloc(VALUE klass) {
+  RepeatedField* self = ALLOC(RepeatedField);
+  self->arena = Qnil;
+  self->type_class = Qnil;
+  self->array = NULL;
+  return TypedData_Wrap_Struct(klass, &RepeatedField_type, self);
+}
+
+VALUE RepeatedField_GetRubyWrapper(upb_array* array, TypeInfo type_info,
+                                   VALUE arena) {
+  PBRUBY_ASSERT(array);
+  VALUE val = ObjectCache_Get(array);
+
+  if (val == Qnil) {
+    val = RepeatedField_alloc(cRepeatedField);
+    RepeatedField* self;
+    ObjectCache_Add(array, val, Arena_get(arena));
+    TypedData_Get_Struct(val, RepeatedField, &RepeatedField_type, self);
+    self->array = array;
+    self->arena = arena;
+    self->type_info = type_info;
+    if (self->type_info.type == UPB_TYPE_MESSAGE) {
+      self->type_class = Descriptor_DefToClass(type_info.def.msgdef);
+    }
+  }
+
+  PBRUBY_ASSERT(ruby_to_RepeatedField(val)->type_info.type == type_info.type);
+  PBRUBY_ASSERT(ruby_to_RepeatedField(val)->type_info.def.msgdef ==
+                type_info.def.msgdef);
+  return val;
+}
+
+static VALUE RepeatedField_new_this_type(RepeatedField* from) {
+  VALUE arena_rb = Arena_new();
+  upb_array *array = upb_array_new(Arena_get(arena_rb), from->type_info.type);
+  VALUE ret = RepeatedField_GetRubyWrapper(array, from->type_info, arena_rb);
+  PBRUBY_ASSERT(ruby_to_RepeatedField(ret)->type_class == from->type_class);
+  return ret;
+}
+
+void RepeatedField_Inspect(StringBuilder* b, const upb_array* array,
+                           TypeInfo info) {
+  bool first = true;
+  StringBuilder_Printf(b, "[");
+  size_t n = array ? upb_array_size(array) : 0;
+  for (size_t i = 0; i < n; i++) {
+    if (first) {
+      first = false;
+    } else {
+      StringBuilder_Printf(b, ", ");
+    }
+    StringBuilder_PrintMsgval(b, upb_array_get(array, i), info);
+  }
+  StringBuilder_Printf(b, "]");
+}
+
+VALUE RepeatedField_deep_copy(VALUE _self) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  VALUE new_rptfield = RepeatedField_new_this_type(self);
+  RepeatedField* new_self = ruby_to_RepeatedField(new_rptfield);
+  VALUE arena_rb = new_self->arena;
+  upb_array *new_array = RepeatedField_GetMutable(new_rptfield);
+  upb_arena *arena = Arena_get(arena_rb);
+  size_t elements = upb_array_size(self->array);
+
+  upb_array_resize(new_array, elements, arena);
+
+  size_t size = upb_array_size(self->array);
+  for (size_t i = 0; i < size; i++) {
+    upb_msgval msgval = upb_array_get(self->array, i);
+    upb_msgval copy = Msgval_DeepCopy(msgval, self->type_info, arena);
+    upb_array_set(new_array, i, copy);
+  }
+
+  return new_rptfield;
+}
+
+const upb_array* RepeatedField_GetUpbArray(VALUE val, const upb_fielddef *field) {
+  RepeatedField* self;
+  TypeInfo type_info = TypeInfo_get(field);
+
+  if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
+      RTYPEDDATA_TYPE(val) != &RepeatedField_type) {
+    rb_raise(cTypeError, "Expected repeated field array");
+  }
+
+  self = ruby_to_RepeatedField(val);
+  if (self->type_info.type != type_info.type) {
+    rb_raise(cTypeError, "Repeated field array has wrong element type");
+  }
+
+  if (self->type_info.def.msgdef != type_info.def.msgdef) {
+    rb_raise(cTypeError, "Repeated field array has wrong message/enum class");
+  }
+
+  return self->array;
 }
 
 static int index_position(VALUE _index, RepeatedField* repeated_field) {
   int index = NUM2INT(_index);
-  if (index < 0 && repeated_field->size > 0) {
-    index = repeated_field->size + index;
-  }
+  if (index < 0) index += upb_array_size(repeated_field->array);
   return index;
 }
 
-VALUE RepeatedField_subarray(VALUE _self, long beg, long len) {
-  RepeatedField* self = ruby_to_RepeatedField(_self);
-  int element_size = native_slot_size(self->field_type);
-  upb_fieldtype_t field_type = self->field_type;
-  VALUE field_type_class = self->field_type_class;
-  size_t off = beg * element_size;
-  VALUE ary = rb_ary_new2(len);
-  int i;
+static VALUE RepeatedField_subarray(RepeatedField* self, long beg, long len) {
+  size_t size = upb_array_size(self->array);
+  VALUE ary = rb_ary_new2(size);
+  long i;
 
-  for (i = beg; i < beg + len; i++, off += element_size) {
-    void* mem = ((uint8_t *)self->elements) + off;
-    VALUE elem = native_slot_get(field_type, field_type_class, mem);
+  for (i = beg; i < beg + len; i++) {
+    upb_msgval msgval = upb_array_get(self->array, i);
+    VALUE elem = Convert_UpbToRuby(msgval, self->type_info, self->arena);
     rb_ary_push(ary, elem);
   }
   return ary;
@@ -84,17 +197,14 @@
  * also includes Enumerable; combined with this method, the repeated field thus
  * acts like an ordinary Ruby sequence.
  */
-VALUE RepeatedField_each(VALUE _self) {
+static VALUE RepeatedField_each(VALUE _self) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  upb_fieldtype_t field_type = self->field_type;
-  VALUE field_type_class = self->field_type_class;
-  int element_size = native_slot_size(field_type);
-  size_t off = 0;
+  int size = upb_array_size(self->array);
   int i;
 
-  for (i = 0; i < self->size; i++, off += element_size) {
-    void* memory = (void *) (((uint8_t *)self->elements) + off);
-    VALUE val = native_slot_get(field_type, field_type_class, memory);
+  for (i = 0; i < size; i++) {
+    upb_msgval msgval = upb_array_get(self->array, i);
+    VALUE val = Convert_UpbToRuby(msgval, self->type_info, self->arena);
     rb_yield(val);
   }
   return _self;
@@ -107,11 +217,9 @@
  *
  * Accesses the element at the given index. Returns nil on out-of-bounds
  */
-VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self) {
+static VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  int element_size = native_slot_size(self->field_type);
-  upb_fieldtype_t field_type = self->field_type;
-  VALUE field_type_class = self->field_type_class;
+  long size = upb_array_size(self->array);
 
   VALUE arg = argv[0];
   long beg, len;
@@ -119,35 +227,36 @@
   if (argc == 1){
     if (FIXNUM_P(arg)) {
       /* standard case */
-      void* memory;
+      upb_msgval msgval;
       int index = index_position(argv[0], self);
-      if (index < 0 || index >= self->size) {
+      if (index < 0 || (size_t)index >= upb_array_size(self->array)) {
         return Qnil;
       }
-      memory = RepeatedField_memoryat(self, index, element_size);
-      return native_slot_get(field_type, field_type_class, memory);
-    }else{
+      msgval = upb_array_get(self->array, index);
+      return Convert_UpbToRuby(msgval, self->type_info, self->arena);
+    } else {
       /* check if idx is Range */
-      switch (rb_range_beg_len(arg, &beg, &len, self->size, 0)) {
+      switch (rb_range_beg_len(arg, &beg, &len, size, 0)) {
         case Qfalse:
           break;
         case Qnil:
           return Qnil;
         default:
-          return RepeatedField_subarray(_self, beg, len);
+          return RepeatedField_subarray(self, beg, len);
       }
     }
   }
+
   /* assume 2 arguments */
   beg = NUM2LONG(argv[0]);
   len = NUM2LONG(argv[1]);
   if (beg < 0) {
-    beg += self->size;
+    beg += size;
   }
-  if (beg >= self->size) {
+  if (beg >= size) {
     return Qnil;
   }
-  return RepeatedField_subarray(_self, beg, len);
+  return RepeatedField_subarray(self, beg, len);
 }
 
 /*
@@ -157,128 +266,88 @@
  * Sets the element at the given index. On out-of-bounds assignments, extends
  * the array and fills the hole (if any) with default values.
  */
-VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) {
+static VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  upb_fieldtype_t field_type = self->field_type;
-  VALUE field_type_class = self->field_type_class;
-  int element_size = native_slot_size(field_type);
-  void* memory;
+  int size = upb_array_size(self->array);
+  upb_array *array = RepeatedField_GetMutable(_self);
+  upb_arena *arena = Arena_get(self->arena);
+  upb_msgval msgval = Convert_RubyToUpb(val, "", self->type_info, arena);
 
   int index = index_position(_index, self);
   if (index < 0 || index >= (INT_MAX - 1)) {
     return Qnil;
   }
-  if (index >= self->size) {
-    upb_fieldtype_t field_type = self->field_type;
-    int element_size = native_slot_size(field_type);
-    int i;
 
-    RepeatedField_reserve(self, index + 1);
-    for (i = self->size; i <= index; i++) {
-      void* elem = RepeatedField_memoryat(self, i, element_size);
-      native_slot_init(field_type, elem);
+  if (index >= size) {
+    upb_array_resize(array, index + 1, arena);
+    upb_msgval fill;
+    memset(&fill, 0, sizeof(fill));
+    for (int i = size; i < index; i++) {
+      // Fill default values.
+      // TODO(haberman): should this happen at the upb level?
+      upb_array_set(array, i, fill);
     }
-    self->size = index + 1;
   }
 
-  memory = RepeatedField_memoryat(self, index, element_size);
-  native_slot_set("", field_type, field_type_class, memory, val);
+  upb_array_set(array, index, msgval);
   return Qnil;
 }
 
-static int kInitialSize = 8;
-
-void RepeatedField_reserve(RepeatedField* self, int new_size) {
-  void* old_elems = self->elements;
-  int elem_size = native_slot_size(self->field_type);
-  if (new_size <= self->capacity) {
-    return;
-  }
-  if (self->capacity == 0) {
-    self->capacity = kInitialSize;
-  }
-  while (self->capacity < new_size) {
-    self->capacity *= 2;
-  }
-  self->elements = ALLOC_N(uint8_t, elem_size * self->capacity);
-  if (old_elems != NULL) {
-    memcpy(self->elements, old_elems, self->size * elem_size);
-    xfree(old_elems);
-  }
-}
-
 /*
  * call-seq:
- *     RepeatedField.push(value)
+ *     RepeatedField.push(value, ...)
  *
  * Adds a new element to the repeated field.
  */
-VALUE RepeatedField_push(VALUE _self, VALUE val) {
+static VALUE RepeatedField_push_vararg(int argc, VALUE* argv, VALUE _self) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  upb_fieldtype_t field_type = self->field_type;
-  int element_size = native_slot_size(field_type);
-  void* memory;
-
-  RepeatedField_reserve(self, self->size + 1);
-  memory = (void *) (((uint8_t *)self->elements) + self->size * element_size);
-  native_slot_set("", field_type, self->field_type_class, memory, val);
-  // native_slot_set may raise an error; bump size only after set.
-  self->size++;
-  return _self;
-}
-
-VALUE RepeatedField_push_vararg(VALUE _self, VALUE args) {
+  upb_arena *arena = Arena_get(self->arena);
+  upb_array *array = RepeatedField_GetMutable(_self);
   int i;
-  for (i = 0; i < RARRAY_LEN(args); i++) {
-    RepeatedField_push(_self, rb_ary_entry(args, i));
+
+  for (i = 0; i < argc; i++) {
+    upb_msgval msgval = Convert_RubyToUpb(argv[i], "", self->type_info, arena);
+    upb_array_append(array, msgval, arena);
   }
+
   return _self;
 }
 
-// Used by parsing handlers.
-void RepeatedField_push_native(VALUE _self, void* data) {
+/*
+ * call-seq:
+ *     RepeatedField.<<(value)
+ *
+ * Adds a new element to the repeated field.
+ */
+static VALUE RepeatedField_push(VALUE _self, VALUE val) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  upb_fieldtype_t field_type = self->field_type;
-  int element_size = native_slot_size(field_type);
-  void* memory;
+  upb_arena *arena = Arena_get(self->arena);
+  upb_array *array = RepeatedField_GetMutable(_self);
 
-  RepeatedField_reserve(self, self->size + 1);
-  memory = (void *) (((uint8_t *)self->elements) + self->size * element_size);
-  memcpy(memory, data, element_size);
-  self->size++;
-}
+  upb_msgval msgval = Convert_RubyToUpb(val, "", self->type_info, arena);
+  upb_array_append(array, msgval, arena);
 
-void* RepeatedField_index_native(VALUE _self, int index) {
-  RepeatedField* self = ruby_to_RepeatedField(_self);
-  upb_fieldtype_t field_type = self->field_type;
-  int element_size = native_slot_size(field_type);
-  return RepeatedField_memoryat(self, index, element_size);
-}
-
-int RepeatedField_size(VALUE _self) {
-  RepeatedField* self = ruby_to_RepeatedField(_self);
-  return self->size;
+  return _self;
 }
 
 /*
  * Private ruby method, used by RepeatedField.pop
  */
-VALUE RepeatedField_pop_one(VALUE _self) {
+static VALUE RepeatedField_pop_one(VALUE _self) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  upb_fieldtype_t field_type = self->field_type;
-  VALUE field_type_class = self->field_type_class;
-  int element_size = native_slot_size(field_type);
-  int index;
-  void* memory;
+  size_t size = upb_array_size(self->array);
+  upb_array *array = RepeatedField_GetMutable(_self);
+  upb_msgval last;
   VALUE ret;
 
-  if (self->size == 0) {
+  if (size == 0) {
     return Qnil;
   }
-  index = self->size - 1;
-  memory = RepeatedField_memoryat(self, index, element_size);
-  ret = native_slot_get(field_type, field_type_class, memory);
-  self->size--;
+
+  last = upb_array_get(self->array, size - 1);
+  ret = Convert_UpbToRuby(last, self->type_info, self->arena);
+
+  upb_array_resize(array, size - 1, Arena_get(self->arena));
   return ret;
 }
 
@@ -288,15 +357,18 @@
  *
  * Replaces the contents of the repeated field with the given list of elements.
  */
-VALUE RepeatedField_replace(VALUE _self, VALUE list) {
+static VALUE RepeatedField_replace(VALUE _self, VALUE list) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
+  upb_array *array = RepeatedField_GetMutable(_self);
   int i;
 
   Check_Type(list, T_ARRAY);
-  self->size = 0;
+  upb_array_resize(array, 0, Arena_get(self->arena));
+
   for (i = 0; i < RARRAY_LEN(list); i++) {
     RepeatedField_push(_self, rb_ary_entry(list, i));
   }
+
   return list;
 }
 
@@ -306,9 +378,10 @@
  *
  * Clears (removes all elements from) this repeated field.
  */
-VALUE RepeatedField_clear(VALUE _self) {
+static VALUE RepeatedField_clear(VALUE _self) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  self->size = 0;
+  upb_array *array = RepeatedField_GetMutable(_self);
+  upb_array_resize(array, 0, Arena_get(self->arena));
   return _self;
 }
 
@@ -318,23 +391,9 @@
  *
  * Returns the length of this repeated field.
  */
-VALUE RepeatedField_length(VALUE _self) {
+static VALUE RepeatedField_length(VALUE _self) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  return INT2NUM(self->size);
-}
-
-VALUE RepeatedField_new_this_type(VALUE _self) {
-  RepeatedField* self = ruby_to_RepeatedField(_self);
-  VALUE new_rptfield = Qnil;
-  VALUE element_type = fieldtype_to_ruby(self->field_type);
-  if (self->field_type_class != Qnil) {
-    new_rptfield = rb_funcall(CLASS_OF(_self), rb_intern("new"), 2,
-                              element_type, self->field_type_class);
-  } else {
-    new_rptfield = rb_funcall(CLASS_OF(_self), rb_intern("new"), 1,
-                              element_type);
-  }
-  return new_rptfield;
+  return INT2NUM(upb_array_size(self->array));
 }
 
 /*
@@ -344,42 +403,20 @@
  * Duplicates this repeated field with a shallow copy. References to all
  * non-primitive element objects (e.g., submessages) are shared.
  */
-VALUE RepeatedField_dup(VALUE _self) {
+static VALUE RepeatedField_dup(VALUE _self) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  VALUE new_rptfield = RepeatedField_new_this_type(_self);
+  VALUE new_rptfield = RepeatedField_new_this_type(self);
   RepeatedField* new_rptfield_self = ruby_to_RepeatedField(new_rptfield);
-  upb_fieldtype_t field_type = self->field_type;
-  size_t elem_size = native_slot_size(field_type);
-  size_t off = 0;
+  upb_array *new_array = RepeatedField_GetMutable(new_rptfield);
+  upb_arena* arena = Arena_get(new_rptfield_self->arena);
+  int size = upb_array_size(self->array);
   int i;
 
-  RepeatedField_reserve(new_rptfield_self, self->size);
-  for (i = 0; i < self->size; i++, off += elem_size) {
-    void* to_mem = (uint8_t *)new_rptfield_self->elements + off;
-    void* from_mem = (uint8_t *)self->elements + off;
-    native_slot_dup(field_type, to_mem, from_mem);
-    new_rptfield_self->size++;
-  }
+  upb_arena_fuse(arena, Arena_get(self->arena));
 
-  return new_rptfield;
-}
-
-// Internal only: used by Google::Protobuf.deep_copy.
-VALUE RepeatedField_deep_copy(VALUE _self) {
-  RepeatedField* self = ruby_to_RepeatedField(_self);
-  VALUE new_rptfield = RepeatedField_new_this_type(_self);
-  RepeatedField* new_rptfield_self = ruby_to_RepeatedField(new_rptfield);
-  upb_fieldtype_t field_type = self->field_type;
-  size_t elem_size = native_slot_size(field_type);
-  size_t off = 0;
-  int i;
-
-  RepeatedField_reserve(new_rptfield_self, self->size);
-  for (i = 0; i < self->size; i++, off += elem_size) {
-    void* to_mem = (uint8_t *)new_rptfield_self->elements + off;
-    void* from_mem = (uint8_t *)self->elements + off;
-    native_slot_deep_copy(field_type, self->field_type_class, to_mem, from_mem);
-    new_rptfield_self->size++;
+  for (i = 0; i < size; i++) {
+    upb_msgval msgval = upb_array_get(self->array, i);
+    upb_array_append(new_array, msgval, arena);
   }
 
   return new_rptfield;
@@ -394,17 +431,16 @@
  */
 VALUE RepeatedField_to_ary(VALUE _self) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  upb_fieldtype_t field_type = self->field_type;
-  size_t elem_size = native_slot_size(field_type);
-  size_t off = 0;
-  VALUE ary = rb_ary_new2(self->size);
+  int size = upb_array_size(self->array);
+  VALUE ary = rb_ary_new2(size);
   int i;
 
-  for (i = 0; i < self->size; i++, off += elem_size) {
-    void* mem = ((uint8_t *)self->elements) + off;
-    VALUE elem = native_slot_get(field_type, self->field_type_class, mem);
-    rb_ary_push(ary, elem);
+  for (i = 0; i < size; i++) {
+    upb_msgval msgval = upb_array_get(self->array, i);
+    VALUE val = Convert_UpbToRuby(msgval, self->type_info, self->arena);
+    rb_ary_push(ary, val);
   }
+
   return ary;
 }
 
@@ -436,28 +472,38 @@
 
   self = ruby_to_RepeatedField(_self);
   other = ruby_to_RepeatedField(_other);
-  if (self->field_type != other->field_type ||
-      self->field_type_class != other->field_type_class ||
-      self->size != other->size) {
+  size_t n = upb_array_size(self->array);
+
+  if (self->type_info.type != other->type_info.type ||
+      self->type_class != other->type_class ||
+      upb_array_size(other->array) != n) {
     return Qfalse;
   }
 
-  {
-    upb_fieldtype_t field_type = self->field_type;
-    size_t elem_size = native_slot_size(field_type);
-    size_t off = 0;
-    int i;
-
-    for (i = 0; i < self->size; i++, off += elem_size) {
-      void* self_mem = ((uint8_t *)self->elements) + off;
-      void* other_mem = ((uint8_t *)other->elements) + off;
-      if (!native_slot_eq(field_type, self->field_type_class, self_mem,
-                          other_mem)) {
-        return Qfalse;
-      }
+  for (size_t i = 0; i < n; i++) {
+    upb_msgval val1 = upb_array_get(self->array, i);
+    upb_msgval val2 = upb_array_get(other->array, i);
+    if (!Msgval_IsEqual(val1, val2, self->type_info)) {
+      return Qfalse;
     }
-    return Qtrue;
   }
+
+  return Qtrue;
+}
+
+/*
+ * call-seq:
+ *     RepeatedField.freeze => self
+ *
+ * Freezes the repeated field. We have to intercept this so we can pin the Ruby
+ * object into memory so we don't forget it's frozen.
+ */
+static VALUE RepeatedField_freeze(VALUE _self) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+
+  ObjectCache_Pin(self->array, _self, Arena_get(self->arena));
+  RB_OBJ_FREEZE(_self);
+  return _self;
 }
 
 /*
@@ -468,22 +514,15 @@
  */
 VALUE RepeatedField_hash(VALUE _self) {
   RepeatedField* self = ruby_to_RepeatedField(_self);
-  st_index_t h = rb_hash_start(0);
-  VALUE hash_sym = rb_intern("hash");
-  upb_fieldtype_t field_type = self->field_type;
-  VALUE field_type_class = self->field_type_class;
-  size_t elem_size = native_slot_size(field_type);
-  size_t off = 0;
-  int i;
+  uint64_t hash = 0;
+  size_t n = upb_array_size(self->array);
 
-  for (i = 0; i < self->size; i++, off += elem_size) {
-    void* mem = ((uint8_t *)self->elements) + off;
-    VALUE elem = native_slot_get(field_type, field_type_class, mem);
-    h = rb_hash_uint(h, NUM2LONG(rb_funcall(elem, hash_sym, 0)));
+  for (size_t i = 0; i < n; i++) {
+    upb_msgval val = upb_array_get(self->array, i);
+    hash = Msgval_GetHash(val, self->type_info, hash);
   }
-  h = rb_hash_end(h);
 
-  return INT2FIX(h);
+  return LL2NUM(hash);
 }
 
 /*
@@ -495,34 +534,39 @@
  * be either another repeated field or a Ruby array.
  */
 VALUE RepeatedField_plus(VALUE _self, VALUE list) {
-  VALUE dupped = RepeatedField_dup(_self);
+  VALUE dupped_ = RepeatedField_dup(_self);
 
   if (TYPE(list) == T_ARRAY) {
     int i;
     for (i = 0; i < RARRAY_LEN(list); i++) {
       VALUE elem = rb_ary_entry(list, i);
-      RepeatedField_push(dupped, elem);
+      RepeatedField_push(dupped_, elem);
     }
   } else if (RB_TYPE_P(list, T_DATA) && RTYPEDDATA_P(list) &&
              RTYPEDDATA_TYPE(list) == &RepeatedField_type) {
     RepeatedField* self = ruby_to_RepeatedField(_self);
     RepeatedField* list_rptfield = ruby_to_RepeatedField(list);
+    RepeatedField* dupped = ruby_to_RepeatedField(dupped_);
+    upb_array *dupped_array = RepeatedField_GetMutable(dupped_);
+    upb_arena* arena = Arena_get(dupped->arena);
+    int size = upb_array_size(list_rptfield->array);
     int i;
 
-    if (self->field_type != list_rptfield->field_type ||
-        self->field_type_class != list_rptfield->field_type_class) {
+    if (self->type_info.type != list_rptfield->type_info.type ||
+        self->type_class != list_rptfield->type_class) {
       rb_raise(rb_eArgError,
                "Attempt to append RepeatedField with different element type.");
     }
-    for (i = 0; i < list_rptfield->size; i++) {
-      void* mem = RepeatedField_index_native(list, i);
-      RepeatedField_push_native(dupped, mem);
+
+    for (i = 0; i < size; i++) {
+      upb_msgval msgval = upb_array_get(list_rptfield->array, i);
+      upb_array_append(dupped_array, msgval, arena);
     }
   } else {
     rb_raise(rb_eArgError, "Unknown type appending to RepeatedField");
   }
 
-  return dupped;
+  return dupped_;
 }
 
 /*
@@ -541,93 +585,6 @@
   return _self;
 }
 
-
-void validate_type_class(upb_fieldtype_t type, VALUE klass) {
-  if (rb_ivar_get(klass, descriptor_instancevar_interned) == Qnil) {
-    rb_raise(rb_eArgError,
-             "Type class has no descriptor. Please pass a "
-             "class or enum as returned by the DescriptorPool.");
-  }
-  if (type == UPB_TYPE_MESSAGE) {
-    VALUE desc = rb_ivar_get(klass, descriptor_instancevar_interned);
-    if (!RB_TYPE_P(desc, T_DATA) || !RTYPEDDATA_P(desc) ||
-        RTYPEDDATA_TYPE(desc) != &_Descriptor_type) {
-      rb_raise(rb_eArgError, "Descriptor has an incorrect type.");
-    }
-    if (rb_get_alloc_func(klass) != &Message_alloc) {
-      rb_raise(rb_eArgError,
-               "Message class was not returned by the DescriptorPool.");
-    }
-  } else if (type == UPB_TYPE_ENUM) {
-    VALUE enumdesc = rb_ivar_get(klass, descriptor_instancevar_interned);
-    if (!RB_TYPE_P(enumdesc, T_DATA) || !RTYPEDDATA_P(enumdesc) ||
-        RTYPEDDATA_TYPE(enumdesc) != &_EnumDescriptor_type) {
-      rb_raise(rb_eArgError, "Descriptor has an incorrect type.");
-    }
-  }
-}
-
-void RepeatedField_init_args(int argc, VALUE* argv,
-                             VALUE _self) {
-  RepeatedField* self = ruby_to_RepeatedField(_self);
-  VALUE ary = Qnil;
-  if (argc < 1) {
-    rb_raise(rb_eArgError, "Expected at least 1 argument.");
-  }
-  self->field_type = ruby_to_fieldtype(argv[0]);
-
-  if (self->field_type == UPB_TYPE_MESSAGE ||
-      self->field_type == UPB_TYPE_ENUM) {
-    if (argc < 2) {
-      rb_raise(rb_eArgError, "Expected at least 2 arguments for message/enum.");
-    }
-    self->field_type_class = argv[1];
-    if (argc > 2) {
-      ary = argv[2];
-    }
-    validate_type_class(self->field_type, self->field_type_class);
-  } else {
-    if (argc > 2) {
-      rb_raise(rb_eArgError, "Too many arguments: expected 1 or 2.");
-    }
-    if (argc > 1) {
-      ary = argv[1];
-    }
-  }
-
-  if (ary != Qnil) {
-    int i;
-
-    if (!RB_TYPE_P(ary, T_ARRAY)) {
-      rb_raise(rb_eArgError, "Expected array as initialize argument");
-    }
-    for (i = 0; i < RARRAY_LEN(ary); i++) {
-      RepeatedField_push(_self, rb_ary_entry(ary, i));
-    }
-  }
-}
-
-// Mark, free, alloc, init and class setup functions.
-
-void RepeatedField_mark(void* _self) {
-  RepeatedField* self = (RepeatedField*)_self;
-  upb_fieldtype_t field_type = self->field_type;
-  int element_size = native_slot_size(field_type);
-  int i;
-
-  rb_gc_mark(self->field_type_class);
-  for (i = 0; i < self->size; i++) {
-    void* memory = (((uint8_t *)self->elements) + i * element_size);
-    native_slot_mark(self->field_type, memory);
-  }
-}
-
-void RepeatedField_free(void* _self) {
-  RepeatedField* self = (RepeatedField*)_self;
-  xfree(self->elements);
-  xfree(self);
-}
-
 /*
  * call-seq:
  *     RepeatedField.new(type, type_class = nil, initial_elems = [])
@@ -639,18 +596,30 @@
  * EnumDescriptor#enummodule, respectively. An initial list of elements may also
  * be provided.
  */
-VALUE RepeatedField_alloc(VALUE klass) {
-  RepeatedField* self = ALLOC(RepeatedField);
-  self->elements = NULL;
-  self->size = 0;
-  self->capacity = 0;
-  self->field_type = -1;
-  self->field_type_class = Qnil;
-  return TypedData_Wrap_Struct(klass, &RepeatedField_type, self);
-}
+VALUE RepeatedField_init(int argc, VALUE* argv, VALUE _self) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  upb_arena *arena;
+  VALUE ary = Qnil;
 
-VALUE RepeatedField_init(int argc, VALUE* argv, VALUE self) {
-  RepeatedField_init_args(argc, argv, self);
+  self->arena = Arena_new();
+  arena = Arena_get(self->arena);
+
+  if (argc < 1) {
+    rb_raise(rb_eArgError, "Expected at least 1 argument.");
+  }
+
+  self->type_info = TypeInfo_FromClass(argc, argv, 0, &self->type_class, &ary);
+  self->array = upb_array_new(arena, self->type_info.type);
+  ObjectCache_Add(self->array, _self, arena);
+
+  if (ary != Qnil) {
+    if (!RB_TYPE_P(ary, T_ARRAY)) {
+      rb_raise(rb_eArgError, "Expected array as initialize argument");
+    }
+    for (int i = 0; i < RARRAY_LEN(ary); i++) {
+      RepeatedField_push(_self, rb_ary_entry(ary, i));
+    }
+  }
   return Qnil;
 }
 
@@ -667,7 +636,7 @@
   rb_define_method(klass, "[]", RepeatedField_index, -1);
   rb_define_method(klass, "at", RepeatedField_index, -1);
   rb_define_method(klass, "[]=", RepeatedField_index_set, 2);
-  rb_define_method(klass, "push", RepeatedField_push_vararg, -2);
+  rb_define_method(klass, "push", RepeatedField_push_vararg, -1);
   rb_define_method(klass, "<<", RepeatedField_push, 1);
   rb_define_private_method(klass, "pop_one", RepeatedField_pop_one, 0);
   rb_define_method(klass, "replace", RepeatedField_replace, 1);
@@ -679,6 +648,7 @@
   rb_define_method(klass, "clone", RepeatedField_dup, 0);
   rb_define_method(klass, "==", RepeatedField_eq, 1);
   rb_define_method(klass, "to_ary", RepeatedField_to_ary, 0);
+  rb_define_method(klass, "freeze", RepeatedField_freeze, 0);
   rb_define_method(klass, "hash", RepeatedField_hash, 0);
   rb_define_method(klass, "+", RepeatedField_plus, 1);
   rb_define_method(klass, "concat", RepeatedField_concat, 1);
diff --git a/ruby/ext/google/protobuf_c/repeated_field.h b/ruby/ext/google/protobuf_c/repeated_field.h
new file mode 100644
index 0000000..5a5959d
--- /dev/null
+++ b/ruby/ext/google/protobuf_c/repeated_field.h
@@ -0,0 +1,62 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef RUBY_PROTOBUF_REPEATED_FIELD_H_
+#define RUBY_PROTOBUF_REPEATED_FIELD_H_
+
+#include <ruby/ruby.h>
+
+#include "protobuf.h"
+#include "ruby-upb.h"
+
+// Returns a Ruby wrapper object for the given upb_array, which will be created
+// if one does not exist already.
+VALUE RepeatedField_GetRubyWrapper(upb_array* msg, TypeInfo type_info,
+                                   VALUE arena);
+
+// Gets the underlying upb_array for this Ruby RepeatedField object, which must
+// have a type that matches |f|. If this is not a repeated field or the type
+// doesn't match, raises an exception.
+const upb_array* RepeatedField_GetUpbArray(VALUE value, const upb_fielddef* f);
+
+// Implements #inspect for this repeated field by appending its contents to |b|.
+void RepeatedField_Inspect(StringBuilder* b, const upb_array* array,
+                           TypeInfo info);
+
+// Returns a deep copy of this RepeatedField object.
+VALUE RepeatedField_deep_copy(VALUE obj);
+
+// Ruby class of Google::Protobuf::RepeatedField.
+extern VALUE cRepeatedField;
+
+// Call at startup to register all types in this module.
+void RepeatedField_register(VALUE module);
+
+#endif  // RUBY_PROTOBUF_REPEATED_FIELD_H_
diff --git a/ruby/ext/google/protobuf_c/ruby-upb.c b/ruby/ext/google/protobuf_c/ruby-upb.c
new file mode 100755
index 0000000..9c048da
--- /dev/null
+++ b/ruby/ext/google/protobuf_c/ruby-upb.c
@@ -0,0 +1,8913 @@
+/* Amalgamated source file */
+#include "ruby-upb.h"
+/*
+* This is where we define macros used across upb.
+*
+* All of these macros are undef'd in port_undef.inc to avoid leaking them to
+* users.
+*
+* The correct usage is:
+*
+*   #include "upb/foobar.h"
+*   #include "upb/baz.h"
+*
+*   // MUST be last included header.
+*   #include "upb/port_def.inc"
+*
+*   // Code for this file.
+*   // <...>
+*
+*   // Can be omitted for .c files, required for .h.
+*   #include "upb/port_undef.inc"
+*
+* This file is private and must not be included by users!
+*/
+
+#if !((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
+      (defined(__cplusplus) && __cplusplus >= 201103L) ||           \
+      (defined(_MSC_VER) && _MSC_VER >= 1900))
+#error upb requires C99 or C++11 or MSVC >= 2015.
+#endif
+
+#include <stdint.h>
+#include <stddef.h>
+
+#if UINTPTR_MAX == 0xffffffff
+#define UPB_SIZE(size32, size64) size32
+#else
+#define UPB_SIZE(size32, size64) size64
+#endif
+
+/* If we always read/write as a consistent type to each address, this shouldn't
+ * violate aliasing.
+ */
+#define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs)))
+
+#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \
+  *UPB_PTR_AT(msg, case_offset, int) == case_val                              \
+      ? *UPB_PTR_AT(msg, offset, fieldtype)                                   \
+      : default
+
+#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \
+  *UPB_PTR_AT(msg, case_offset, int) = case_val;                             \
+  *UPB_PTR_AT(msg, offset, fieldtype) = value;
+
+#define UPB_MAPTYPE_STRING 0
+
+/* UPB_INLINE: inline if possible, emit standalone code if required. */
+#ifdef __cplusplus
+#define UPB_INLINE inline
+#elif defined (__GNUC__) || defined(__clang__)
+#define UPB_INLINE static __inline__
+#else
+#define UPB_INLINE static
+#endif
+
+#define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align))
+#define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align))
+#define UPB_ALIGN_MALLOC(size) UPB_ALIGN_UP(size, 16)
+#define UPB_ALIGN_OF(type) offsetof (struct { char c; type member; }, member)
+
+/* Hints to the compiler about likely/unlikely branches. */
+#if defined (__GNUC__) || defined(__clang__)
+#define UPB_LIKELY(x) __builtin_expect((x),1)
+#define UPB_UNLIKELY(x) __builtin_expect((x),0)
+#else
+#define UPB_LIKELY(x) (x)
+#define UPB_UNLIKELY(x) (x)
+#endif
+
+/* Macros for function attributes on compilers that support them. */
+#ifdef __GNUC__
+#define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
+#define UPB_NOINLINE __attribute__((noinline))
+#define UPB_NORETURN __attribute__((__noreturn__))
+#define UPB_PRINTF(str, first_vararg) __attribute__((format (printf, str, first_vararg)))
+#elif defined(_MSC_VER)
+#define UPB_NOINLINE
+#define UPB_FORCEINLINE
+#define UPB_NORETURN __declspec(noreturn)
+#define UPB_PRINTF(str, first_vararg)
+#else  /* !defined(__GNUC__) */
+#define UPB_FORCEINLINE
+#define UPB_NOINLINE
+#define UPB_NORETURN
+#define UPB_PRINTF(str, first_vararg)
+#endif
+
+#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
+#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
+
+#define UPB_UNUSED(var) (void)var
+
+/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true.
+ */
+#ifdef NDEBUG
+#ifdef __GNUC__
+#define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable()
+#elif defined _MSC_VER
+#define UPB_ASSUME(expr) if (!(expr)) __assume(0)
+#else
+#define UPB_ASSUME(expr) do {} while (false && (expr))
+#endif
+#else
+#define UPB_ASSUME(expr) assert(expr)
+#endif
+
+/* UPB_ASSERT(): in release mode, we use the expression without letting it be
+ * evaluated.  This prevents "unused variable" warnings. */
+#ifdef NDEBUG
+#define UPB_ASSERT(expr) do {} while (false && (expr))
+#else
+#define UPB_ASSERT(expr) assert(expr)
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0)
+#else
+#define UPB_UNREACHABLE() do { assert(0); } while(0)
+#endif
+
+/* UPB_SETJMP() / UPB_LONGJMP(): avoid setting/restoring signal mask. */
+#ifdef __APPLE__
+#define UPB_SETJMP(buf) _setjmp(buf)
+#define UPB_LONGJMP(buf, val) _longjmp(buf, val)
+#else
+#define UPB_SETJMP(buf) setjmp(buf)
+#define UPB_LONGJMP(buf, val) longjmp(buf, val)
+#endif
+
+/* Configure whether fasttable is switched on or not. *************************/
+
+#if defined(__x86_64__) && defined(__GNUC__)
+#define UPB_FASTTABLE_SUPPORTED 1
+#else
+#define UPB_FASTTABLE_SUPPORTED 0
+#endif
+
+/* define UPB_ENABLE_FASTTABLE to force fast table support.
+ * This is useful when we want to ensure we are really getting fasttable,
+ * for example for testing or benchmarking. */
+#if defined(UPB_ENABLE_FASTTABLE)
+#if !UPB_FASTTABLE_SUPPORTED
+#error fasttable is x86-64 + Clang/GCC only
+#endif
+#define UPB_FASTTABLE 1
+/* Define UPB_TRY_ENABLE_FASTTABLE to use fasttable if possible.
+ * This is useful for releasing code that might be used on multiple platforms,
+ * for example the PHP or Ruby C extensions. */
+#elif defined(UPB_TRY_ENABLE_FASTTABLE)
+#define UPB_FASTTABLE UPB_FASTTABLE_SUPPORTED
+#else
+#define UPB_FASTTABLE 0
+#endif
+
+/* UPB_FASTTABLE_INIT() allows protos compiled for fasttable to gracefully
+ * degrade to non-fasttable if we are using UPB_TRY_ENABLE_FASTTABLE. */
+#if !UPB_FASTTABLE && defined(UPB_TRY_ENABLE_FASTTABLE)
+#define UPB_FASTTABLE_INIT(...)
+#else
+#define UPB_FASTTABLE_INIT(...) __VA_ARGS__
+#endif
+
+#undef UPB_FASTTABLE_SUPPORTED
+
+/* ASAN poisoning (for arena) *************************************************/
+
+#if defined(__SANITIZE_ADDRESS__)
+#define UPB_ASAN 1
+#ifdef __cplusplus
+extern "C" {
+#endif
+void __asan_poison_memory_region(void const volatile *addr, size_t size);
+void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+#define UPB_POISON_MEMORY_REGION(addr, size) \
+  __asan_poison_memory_region((addr), (size))
+#define UPB_UNPOISON_MEMORY_REGION(addr, size) \
+  __asan_unpoison_memory_region((addr), (size))
+#else
+#define UPB_ASAN 0
+#define UPB_POISON_MEMORY_REGION(addr, size) \
+  ((void)(addr), (void)(size))
+#define UPB_UNPOISON_MEMORY_REGION(addr, size) \
+  ((void)(addr), (void)(size))
+#endif 
+
+
+#include <setjmp.h>
+#include <string.h>
+
+
+/* Must be last. */
+
+/* Maps descriptor type -> elem_size_lg2.  */
+static const uint8_t desctype_to_elem_size_lg2[] = {
+    -1,               /* invalid descriptor type */
+    3,  /* DOUBLE */
+    2,   /* FLOAT */
+    3,   /* INT64 */
+    3,  /* UINT64 */
+    2,   /* INT32 */
+    3,  /* FIXED64 */
+    2,  /* FIXED32 */
+    0,    /* BOOL */
+    UPB_SIZE(3, 4),  /* STRING */
+    UPB_SIZE(2, 3),  /* GROUP */
+    UPB_SIZE(2, 3),  /* MESSAGE */
+    UPB_SIZE(3, 4),  /* BYTES */
+    2,  /* UINT32 */
+    2,    /* ENUM */
+    2,   /* SFIXED32 */
+    3,   /* SFIXED64 */
+    2,   /* SINT32 */
+    3,   /* SINT64 */
+};
+
+/* Maps descriptor type -> upb map size.  */
+static const uint8_t desctype_to_mapsize[] = {
+    -1,                 /* invalid descriptor type */
+    8,                  /* DOUBLE */
+    4,                  /* FLOAT */
+    8,                  /* INT64 */
+    8,                  /* UINT64 */
+    4,                  /* INT32 */
+    8,                  /* FIXED64 */
+    4,                  /* FIXED32 */
+    1,                  /* BOOL */
+    UPB_MAPTYPE_STRING, /* STRING */
+    sizeof(void *),     /* GROUP */
+    sizeof(void *),     /* MESSAGE */
+    UPB_MAPTYPE_STRING, /* BYTES */
+    4,                  /* UINT32 */
+    4,                  /* ENUM */
+    4,                  /* SFIXED32 */
+    8,                  /* SFIXED64 */
+    4,                  /* SINT32 */
+    8,                  /* SINT64 */
+};
+
+static const unsigned fixed32_ok = (1 << UPB_DTYPE_FLOAT) |
+                                   (1 << UPB_DTYPE_FIXED32) |
+                                   (1 << UPB_DTYPE_SFIXED32);
+
+static const unsigned fixed64_ok = (1 << UPB_DTYPE_DOUBLE) |
+                                   (1 << UPB_DTYPE_FIXED64) |
+                                   (1 << UPB_DTYPE_SFIXED64);
+
+/* Op: an action to be performed for a wire-type/field-type combination. */
+#define OP_SCALAR_LG2(n) (n)      /* n in [0, 2, 3] => op in [0, 2, 3] */
+#define OP_STRING 4
+#define OP_BYTES 5
+#define OP_SUBMSG 6
+/* Ops above are scalar-only. Repeated fields can use any op.  */
+#define OP_FIXPCK_LG2(n) (n + 5)  /* n in [2, 3] => op in [7, 8] */
+#define OP_VARPCK_LG2(n) (n + 9)  /* n in [0, 2, 3] => op in [9, 11, 12] */
+
+static const int8_t varint_ops[19] = {
+    -1,               /* field not found */
+    -1,               /* DOUBLE */
+    -1,               /* FLOAT */
+    OP_SCALAR_LG2(3), /* INT64 */
+    OP_SCALAR_LG2(3), /* UINT64 */
+    OP_SCALAR_LG2(2), /* INT32 */
+    -1,               /* FIXED64 */
+    -1,               /* FIXED32 */
+    OP_SCALAR_LG2(0), /* BOOL */
+    -1,               /* STRING */
+    -1,               /* GROUP */
+    -1,               /* MESSAGE */
+    -1,               /* BYTES */
+    OP_SCALAR_LG2(2), /* UINT32 */
+    OP_SCALAR_LG2(2), /* ENUM */
+    -1,               /* SFIXED32 */
+    -1,               /* SFIXED64 */
+    OP_SCALAR_LG2(2), /* SINT32 */
+    OP_SCALAR_LG2(3), /* SINT64 */
+};
+
+static const int8_t delim_ops[37] = {
+    /* For non-repeated field type. */
+    -1,        /* field not found */
+    -1,        /* DOUBLE */
+    -1,        /* FLOAT */
+    -1,        /* INT64 */
+    -1,        /* UINT64 */
+    -1,        /* INT32 */
+    -1,        /* FIXED64 */
+    -1,        /* FIXED32 */
+    -1,        /* BOOL */
+    OP_STRING, /* STRING */
+    -1,        /* GROUP */
+    OP_SUBMSG, /* MESSAGE */
+    OP_BYTES,  /* BYTES */
+    -1,        /* UINT32 */
+    -1,        /* ENUM */
+    -1,        /* SFIXED32 */
+    -1,        /* SFIXED64 */
+    -1,        /* SINT32 */
+    -1,        /* SINT64 */
+    /* For repeated field type. */
+    OP_FIXPCK_LG2(3), /* REPEATED DOUBLE */
+    OP_FIXPCK_LG2(2), /* REPEATED FLOAT */
+    OP_VARPCK_LG2(3), /* REPEATED INT64 */
+    OP_VARPCK_LG2(3), /* REPEATED UINT64 */
+    OP_VARPCK_LG2(2), /* REPEATED INT32 */
+    OP_FIXPCK_LG2(3), /* REPEATED FIXED64 */
+    OP_FIXPCK_LG2(2), /* REPEATED FIXED32 */
+    OP_VARPCK_LG2(0), /* REPEATED BOOL */
+    OP_STRING,        /* REPEATED STRING */
+    OP_SUBMSG,        /* REPEATED GROUP */
+    OP_SUBMSG,        /* REPEATED MESSAGE */
+    OP_BYTES,         /* REPEATED BYTES */
+    OP_VARPCK_LG2(2), /* REPEATED UINT32 */
+    OP_VARPCK_LG2(2), /* REPEATED ENUM */
+    OP_FIXPCK_LG2(2), /* REPEATED SFIXED32 */
+    OP_FIXPCK_LG2(3), /* REPEATED SFIXED64 */
+    OP_VARPCK_LG2(2), /* REPEATED SINT32 */
+    OP_VARPCK_LG2(3), /* REPEATED SINT64 */
+};
+
+typedef union {
+  bool bool_val;
+  uint32_t uint32_val;
+  uint64_t uint64_val;
+  uint32_t size;
+} wireval;
+
+static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
+                              const upb_msglayout *layout);
+
+UPB_NORETURN static void decode_err(upb_decstate *d) { UPB_LONGJMP(d->err, 1); }
+
+// We don't want to mark this NORETURN, see comment in .h.
+// Unfortunately this code to suppress the warning doesn't appear to be working.
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-warning-option"
+#pragma clang diagnostic ignored "-Wsuggest-attribute"
+#endif
+
+const char *fastdecode_err(upb_decstate *d) {
+  longjmp(d->err, 1);
+  return NULL;
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+const uint8_t upb_utf8_offsets[] = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+    4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static void decode_verifyutf8(upb_decstate *d, const char *buf, int len) {
+  if (!decode_verifyutf8_inl(buf, len)) decode_err(d);
+}
+
+static bool decode_reserve(upb_decstate *d, upb_array *arr, size_t elem) {
+  bool need_realloc = arr->size - arr->len < elem;
+  if (need_realloc && !_upb_array_realloc(arr, arr->len + elem, &d->arena)) {
+    decode_err(d);
+  }
+  return need_realloc;
+}
+
+typedef struct {
+  const char *ptr;
+  uint64_t val;
+} decode_vret;
+
+UPB_NOINLINE
+static decode_vret decode_longvarint64(const char *ptr, uint64_t val) {
+  decode_vret ret = {NULL, 0};
+  uint64_t byte;
+  int i;
+  for (i = 1; i < 10; i++) {
+    byte = (uint8_t)ptr[i];
+    val += (byte - 1) << (i * 7);
+    if (!(byte & 0x80)) {
+      ret.ptr = ptr + i + 1;
+      ret.val = val;
+      return ret;
+    }
+  }
+  return ret;
+}
+
+UPB_FORCEINLINE
+static const char *decode_varint64(upb_decstate *d, const char *ptr,
+                                   uint64_t *val) {
+  uint64_t byte = (uint8_t)*ptr;
+  if (UPB_LIKELY((byte & 0x80) == 0)) {
+    *val = byte;
+    return ptr + 1;
+  } else {
+    decode_vret res = decode_longvarint64(ptr, byte);
+    if (!res.ptr) decode_err(d);
+    *val = res.val;
+    return res.ptr;
+  }
+}
+
+UPB_FORCEINLINE
+static const char *decode_tag(upb_decstate *d, const char *ptr,
+                                   uint32_t *val) {
+  uint64_t byte = (uint8_t)*ptr;
+  if (UPB_LIKELY((byte & 0x80) == 0)) {
+    *val = byte;
+    return ptr + 1;
+  } else {
+    const char *start = ptr;
+    decode_vret res = decode_longvarint64(ptr, byte);
+    ptr = res.ptr;
+    *val = res.val;
+    if (!ptr || *val > UINT32_MAX || ptr - start > 5) decode_err(d);
+    return ptr;
+  }
+}
+
+static void decode_munge(int type, wireval *val) {
+  switch (type) {
+    case UPB_DESCRIPTOR_TYPE_BOOL:
+      val->bool_val = val->uint64_val != 0;
+      break;
+    case UPB_DESCRIPTOR_TYPE_SINT32: {
+      uint32_t n = val->uint32_val;
+      val->uint32_val = (n >> 1) ^ -(int32_t)(n & 1);
+      break;
+    }
+    case UPB_DESCRIPTOR_TYPE_SINT64: {
+      uint64_t n = val->uint64_val;
+      val->uint64_val = (n >> 1) ^ -(int64_t)(n & 1);
+      break;
+    }
+    case UPB_DESCRIPTOR_TYPE_INT32:
+    case UPB_DESCRIPTOR_TYPE_UINT32:
+      if (!_upb_isle()) {
+        /* The next stage will memcpy(dst, &val, 4) */
+        val->uint32_val = val->uint64_val;
+      }
+      break;
+  }
+}
+
+static const upb_msglayout_field *upb_find_field(const upb_msglayout *l,
+                                                 uint32_t field_number) {
+  static upb_msglayout_field none = {0, 0, 0, 0, 0, 0};
+
+  /* Lots of optimization opportunities here. */
+  int i;
+  if (l == NULL) return &none;
+  for (i = 0; i < l->field_count; i++) {
+    if (l->fields[i].number == field_number) {
+      return &l->fields[i];
+    }
+  }
+
+  return &none; /* Unknown field. */
+}
+
+static upb_msg *decode_newsubmsg(upb_decstate *d, const upb_msglayout *layout,
+                                 const upb_msglayout_field *field) {
+  const upb_msglayout *subl = layout->submsgs[field->submsg_index];
+  return _upb_msg_new_inl(subl, &d->arena);
+}
+
+UPB_NOINLINE
+const char *decode_isdonefallback(upb_decstate *d, const char *ptr,
+                                  int overrun) {
+  ptr = decode_isdonefallback_inl(d, ptr, overrun);
+  if (ptr == NULL) {
+    decode_err(d);
+  }
+  return ptr;
+}
+
+static const char *decode_readstr(upb_decstate *d, const char *ptr, int size,
+                                  upb_strview *str) {
+  if (d->alias) {
+    str->data = ptr;
+  } else {
+    char *data =  upb_arena_malloc(&d->arena, size);
+    if (!data) decode_err(d);
+    memcpy(data, ptr, size);
+    str->data = data;
+  }
+  str->size = size;
+  return ptr + size;
+}
+
+UPB_FORCEINLINE
+static const char *decode_tosubmsg(upb_decstate *d, const char *ptr,
+                                   upb_msg *submsg, const upb_msglayout *layout,
+                                   const upb_msglayout_field *field, int size) {
+  const upb_msglayout *subl = layout->submsgs[field->submsg_index];
+  int saved_delta = decode_pushlimit(d, ptr, size);
+  if (--d->depth < 0) decode_err(d);
+  if (!decode_isdone(d, &ptr)) {
+    ptr = decode_msg(d, ptr, submsg, subl);
+  }
+  if (d->end_group != DECODE_NOGROUP) decode_err(d);
+  decode_poplimit(d, ptr, saved_delta);
+  d->depth++;
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static const char *decode_group(upb_decstate *d, const char *ptr,
+                                upb_msg *submsg, const upb_msglayout *subl,
+                                uint32_t number) {
+  if (--d->depth < 0) decode_err(d);
+  if (decode_isdone(d, &ptr)) {
+    decode_err(d);
+  }
+  ptr = decode_msg(d, ptr, submsg, subl);
+  if (d->end_group != number) decode_err(d);
+  d->end_group = DECODE_NOGROUP;
+  d->depth++;
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static const char *decode_togroup(upb_decstate *d, const char *ptr,
+                                  upb_msg *submsg, const upb_msglayout *layout,
+                                  const upb_msglayout_field *field) {
+  const upb_msglayout *subl = layout->submsgs[field->submsg_index];
+  return decode_group(d, ptr, submsg, subl, field->number);
+}
+
+static const char *decode_toarray(upb_decstate *d, const char *ptr,
+                                  upb_msg *msg, const upb_msglayout *layout,
+                                  const upb_msglayout_field *field, wireval val,
+                                  int op) {
+  upb_array **arrp = UPB_PTR_AT(msg, field->offset, void);
+  upb_array *arr = *arrp;
+  void *mem;
+
+  if (arr) {
+    decode_reserve(d, arr, 1);
+  } else {
+    size_t lg2 = desctype_to_elem_size_lg2[field->descriptortype];
+    arr = _upb_array_new(&d->arena, 4, lg2);
+    if (!arr) decode_err(d);
+    *arrp = arr;
+  }
+
+  switch (op) {
+    case OP_SCALAR_LG2(0):
+    case OP_SCALAR_LG2(2):
+    case OP_SCALAR_LG2(3):
+      /* Append scalar value. */
+      mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << op, void);
+      arr->len++;
+      memcpy(mem, &val, 1 << op);
+      return ptr;
+    case OP_STRING:
+      decode_verifyutf8(d, ptr, val.size);
+      /* Fallthrough. */
+    case OP_BYTES: {
+      /* Append bytes. */
+      upb_strview *str = (upb_strview*)_upb_array_ptr(arr) + arr->len;
+      arr->len++;
+      return decode_readstr(d, ptr, val.size, str);
+    }
+    case OP_SUBMSG: {
+      /* Append submessage / group. */
+      upb_msg *submsg = decode_newsubmsg(d, layout, field);
+      *UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(void *), upb_msg *) =
+          submsg;
+      arr->len++;
+      if (UPB_UNLIKELY(field->descriptortype == UPB_DTYPE_GROUP)) {
+        return decode_togroup(d, ptr, submsg, layout, field);
+      } else {
+        return decode_tosubmsg(d, ptr, submsg, layout, field, val.size);
+      }
+    }
+    case OP_FIXPCK_LG2(2):
+    case OP_FIXPCK_LG2(3): {
+      /* Fixed packed. */
+      int lg2 = op - OP_FIXPCK_LG2(0);
+      int mask = (1 << lg2) - 1;
+      size_t count = val.size >> lg2;
+      if ((val.size & mask) != 0) {
+        decode_err(d); /* Length isn't a round multiple of elem size. */
+      }
+      decode_reserve(d, arr, count);
+      mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
+      arr->len += count;
+      memcpy(mem, ptr, val.size);  /* XXX: ptr boundary. */
+      return ptr + val.size;
+    }
+    case OP_VARPCK_LG2(0):
+    case OP_VARPCK_LG2(2):
+    case OP_VARPCK_LG2(3): {
+      /* Varint packed. */
+      int lg2 = op - OP_VARPCK_LG2(0);
+      int scale = 1 << lg2;
+      int saved_limit = decode_pushlimit(d, ptr, val.size);
+      char *out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
+      while (!decode_isdone(d, &ptr)) {
+        wireval elem;
+        ptr = decode_varint64(d, ptr, &elem.uint64_val);
+        decode_munge(field->descriptortype, &elem);
+        if (decode_reserve(d, arr, 1)) {
+          out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
+        }
+        arr->len++;
+        memcpy(out, &elem, scale);
+        out += scale;
+      }
+      decode_poplimit(d, ptr, saved_limit);
+      return ptr;
+    }
+    default:
+      UPB_UNREACHABLE();
+  }
+}
+
+static const char *decode_tomap(upb_decstate *d, const char *ptr, upb_msg *msg,
+                                const upb_msglayout *layout,
+                                const upb_msglayout_field *field, wireval val) {
+  upb_map **map_p = UPB_PTR_AT(msg, field->offset, upb_map *);
+  upb_map *map = *map_p;
+  upb_map_entry ent;
+  const upb_msglayout *entry = layout->submsgs[field->submsg_index];
+
+  if (!map) {
+    /* Lazily create map. */
+    const upb_msglayout *entry = layout->submsgs[field->submsg_index];
+    const upb_msglayout_field *key_field = &entry->fields[0];
+    const upb_msglayout_field *val_field = &entry->fields[1];
+    char key_size = desctype_to_mapsize[key_field->descriptortype];
+    char val_size = desctype_to_mapsize[val_field->descriptortype];
+    UPB_ASSERT(key_field->offset == 0);
+    UPB_ASSERT(val_field->offset == sizeof(upb_strview));
+    map = _upb_map_new(&d->arena, key_size, val_size);
+    *map_p = map;
+  }
+
+  /* Parse map entry. */
+  memset(&ent, 0, sizeof(ent));
+
+  if (entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE ||
+      entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_GROUP) {
+    /* Create proactively to handle the case where it doesn't appear. */
+    ent.v.val = upb_value_ptr(_upb_msg_new(entry->submsgs[0], &d->arena));
+  }
+
+  ptr = decode_tosubmsg(d, ptr, &ent.k, layout, field, val.size);
+  _upb_map_set(map, &ent.k, map->key_size, &ent.v, map->val_size, &d->arena);
+  return ptr;
+}
+
+static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg,
+                                const upb_msglayout *layout,
+                                const upb_msglayout_field *field, wireval val,
+                                int op) {
+  void *mem = UPB_PTR_AT(msg, field->offset, void);
+  int type = field->descriptortype;
+
+  /* Set presence if necessary. */
+  if (field->presence < 0) {
+    /* Oneof case */
+    uint32_t *oneof_case = _upb_oneofcase_field(msg, field);
+    if (op == OP_SUBMSG && *oneof_case != field->number) {
+      memset(mem, 0, sizeof(void*));
+    }
+    *oneof_case = field->number;
+  } else if (field->presence > 0) {
+    _upb_sethas_field(msg, field);
+  }
+
+  /* Store into message. */
+  switch (op) {
+    case OP_SUBMSG: {
+      upb_msg **submsgp = mem;
+      upb_msg *submsg = *submsgp;
+      if (!submsg) {
+        submsg = decode_newsubmsg(d, layout, field);
+        *submsgp = submsg;
+      }
+      if (UPB_UNLIKELY(type == UPB_DTYPE_GROUP)) {
+        ptr = decode_togroup(d, ptr, submsg, layout, field);
+      } else {
+        ptr = decode_tosubmsg(d, ptr, submsg, layout, field, val.size);
+      }
+      break;
+    }
+    case OP_STRING:
+      decode_verifyutf8(d, ptr, val.size);
+      /* Fallthrough. */
+    case OP_BYTES:
+      return decode_readstr(d, ptr, val.size, mem);
+    case OP_SCALAR_LG2(3):
+      memcpy(mem, &val, 8);
+      break;
+    case OP_SCALAR_LG2(2):
+      memcpy(mem, &val, 4);
+      break;
+    case OP_SCALAR_LG2(0):
+      memcpy(mem, &val, 1);
+      break;
+    default:
+      UPB_UNREACHABLE();
+  }
+
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static bool decode_tryfastdispatch(upb_decstate *d, const char **ptr,
+                                   upb_msg *msg, const upb_msglayout *layout) {
+#if UPB_FASTTABLE
+  if (layout && layout->table_mask != (unsigned char)-1) {
+    uint16_t tag = fastdecode_loadtag(*ptr);
+    intptr_t table = decode_totable(layout);
+    *ptr = fastdecode_tagdispatch(d, *ptr, msg, table, 0, tag);
+    return true;
+  }
+#endif
+  return false;
+}
+
+UPB_NOINLINE
+static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
+                              const upb_msglayout *layout) {
+  while (true) {
+    uint32_t tag;
+    const upb_msglayout_field *field;
+    int field_number;
+    int wire_type;
+    const char *field_start = ptr;
+    wireval val;
+    int op;
+
+    UPB_ASSERT(ptr < d->limit_ptr);
+    ptr = decode_tag(d, ptr, &tag);
+    field_number = tag >> 3;
+    wire_type = tag & 7;
+
+    field = upb_find_field(layout, field_number);
+
+    switch (wire_type) {
+      case UPB_WIRE_TYPE_VARINT:
+        ptr = decode_varint64(d, ptr, &val.uint64_val);
+        op = varint_ops[field->descriptortype];
+        decode_munge(field->descriptortype, &val);
+        break;
+      case UPB_WIRE_TYPE_32BIT:
+        memcpy(&val.uint32_val, ptr, 4);
+        val.uint32_val = _upb_be_swap32(val.uint32_val);
+        ptr += 4;
+        op = OP_SCALAR_LG2(2);
+        if (((1 << field->descriptortype) & fixed32_ok) == 0) goto unknown;
+        break;
+      case UPB_WIRE_TYPE_64BIT:
+        memcpy(&val.uint64_val, ptr, 8);
+        val.uint64_val = _upb_be_swap64(val.uint64_val);
+        ptr += 8;
+        op = OP_SCALAR_LG2(3);
+        if (((1 << field->descriptortype) & fixed64_ok) == 0) goto unknown;
+        break;
+      case UPB_WIRE_TYPE_DELIMITED: {
+        int ndx = field->descriptortype;
+        uint64_t size;
+        if (_upb_isrepeated(field)) ndx += 18;
+        ptr = decode_varint64(d, ptr, &size);
+        if (size >= INT32_MAX ||
+            ptr - d->end + (int32_t)size > d->limit) {
+          decode_err(d); /* Length overflow. */
+        }
+        op = delim_ops[ndx];
+        val.size = size;
+        break;
+      }
+      case UPB_WIRE_TYPE_START_GROUP:
+        val.uint32_val = field_number;
+        op = OP_SUBMSG;
+        if (field->descriptortype != UPB_DTYPE_GROUP) goto unknown;
+        break;
+      case UPB_WIRE_TYPE_END_GROUP:
+        d->end_group = field_number;
+        return ptr;
+      default:
+        decode_err(d);
+    }
+
+    if (op >= 0) {
+      /* Parse, using op for dispatch. */
+      switch (field->label) {
+        case UPB_LABEL_REPEATED:
+        case _UPB_LABEL_PACKED:
+          ptr = decode_toarray(d, ptr, msg, layout, field, val, op);
+          break;
+        case _UPB_LABEL_MAP:
+          ptr = decode_tomap(d, ptr, msg, layout, field, val);
+          break;
+        default:
+          ptr = decode_tomsg(d, ptr, msg, layout, field, val, op);
+          break;
+      }
+    } else {
+    unknown:
+      /* Skip unknown field. */
+      if (field_number == 0) decode_err(d);
+      if (wire_type == UPB_WIRE_TYPE_DELIMITED) ptr += val.size;
+      if (msg) {
+        if (wire_type == UPB_WIRE_TYPE_START_GROUP) {
+          d->unknown = field_start;
+          d->unknown_msg = msg;
+          ptr = decode_group(d, ptr, NULL, NULL, field_number);
+          d->unknown_msg = NULL;
+          field_start = d->unknown;
+        }
+        if (!_upb_msg_addunknown(msg, field_start, ptr - field_start,
+                                 &d->arena)) {
+          decode_err(d);
+        }
+      } else if (wire_type == UPB_WIRE_TYPE_START_GROUP) {
+        ptr = decode_group(d, ptr, NULL, NULL, field_number);
+      }
+    }
+
+    if (decode_isdone(d, &ptr)) return ptr;
+    if (decode_tryfastdispatch(d, &ptr, msg, layout)) return ptr;
+  }
+}
+
+const char *fastdecode_generic(struct upb_decstate *d, const char *ptr,
+                               upb_msg *msg, intptr_t table, uint64_t hasbits,
+                               uint64_t data) {
+  (void)data;
+  *(uint32_t*)msg |= hasbits;
+  return decode_msg(d, ptr, msg, decode_totablep(table));
+}
+
+static bool decode_top(struct upb_decstate *d, const char *buf, void *msg,
+                       const upb_msglayout *l) {
+  if (!decode_tryfastdispatch(d, &buf, msg, l)) {
+    decode_msg(d, buf, msg, l);
+  }
+  return d->end_group == DECODE_NOGROUP;
+}
+
+bool _upb_decode(const char *buf, size_t size, void *msg,
+                 const upb_msglayout *l, upb_arena *arena, int options) {
+  bool ok;
+  upb_decstate state;
+  unsigned depth = (unsigned)options >> 16;
+
+  if (size == 0) {
+    return true;
+  } else if (size <= 16) {
+    memset(&state.patch, 0, 32);
+    memcpy(&state.patch, buf, size);
+    buf = state.patch;
+    state.end = buf + size;
+    state.limit = 0;
+    state.alias = false;
+  } else {
+    state.end = buf + size - 16;
+    state.limit = 16;
+    state.alias = options & UPB_DECODE_ALIAS;
+  }
+
+  state.limit_ptr = state.end;
+  state.unknown_msg = NULL;
+  state.depth = depth ? depth : 64;
+  state.end_group = DECODE_NOGROUP;
+  state.arena.head = arena->head;
+  state.arena.last_size = arena->last_size;
+  state.arena.cleanups = arena->cleanups;
+  state.arena.parent = arena;
+
+  if (UPB_UNLIKELY(UPB_SETJMP(state.err))) {
+    ok = false;
+  } else {
+    ok = decode_top(&state, buf, msg, l);
+  }
+
+  arena->head.ptr = state.arena.head.ptr;
+  arena->head.end = state.arena.head.end;
+  arena->cleanups = state.arena.cleanups;
+  return ok;
+}
+
+#undef OP_SCALAR_LG2
+#undef OP_FIXPCK_LG2
+#undef OP_VARPCK_LG2
+#undef OP_STRING
+#undef OP_SUBMSG
+/* We encode backwards, to avoid pre-computing lengths (one-pass encode). */
+
+
+#include <setjmp.h>
+#include <string.h>
+
+
+/* Must be last. */
+
+#define UPB_PB_VARINT_MAX_LEN 10
+
+UPB_NOINLINE
+static size_t encode_varint64(uint64_t val, char *buf) {
+  size_t i = 0;
+  do {
+    uint8_t byte = val & 0x7fU;
+    val >>= 7;
+    if (val) byte |= 0x80U;
+    buf[i++] = byte;
+  } while (val);
+  return i;
+}
+
+static uint32_t encode_zz32(int32_t n) { return ((uint32_t)n << 1) ^ (n >> 31); }
+static uint64_t encode_zz64(int64_t n) { return ((uint64_t)n << 1) ^ (n >> 63); }
+
+typedef struct {
+  jmp_buf err;
+  upb_alloc *alloc;
+  char *buf, *ptr, *limit;
+  int options;
+  int depth;
+  _upb_mapsorter sorter;
+} upb_encstate;
+
+static size_t upb_roundup_pow2(size_t bytes) {
+  size_t ret = 128;
+  while (ret < bytes) {
+    ret *= 2;
+  }
+  return ret;
+}
+
+UPB_NORETURN static void encode_err(upb_encstate *e) {
+  UPB_LONGJMP(e->err, 1);
+}
+
+UPB_NOINLINE
+static void encode_growbuffer(upb_encstate *e, size_t bytes) {
+  size_t old_size = e->limit - e->buf;
+  size_t new_size = upb_roundup_pow2(bytes + (e->limit - e->ptr));
+  char *new_buf = upb_realloc(e->alloc, e->buf, old_size, new_size);
+
+  if (!new_buf) encode_err(e);
+
+  /* We want previous data at the end, realloc() put it at the beginning. */
+  if (old_size > 0) {
+    memmove(new_buf + new_size - old_size, e->buf, old_size);
+  }
+
+  e->ptr = new_buf + new_size - (e->limit - e->ptr);
+  e->limit = new_buf + new_size;
+  e->buf = new_buf;
+
+  e->ptr -= bytes;
+}
+
+/* Call to ensure that at least "bytes" bytes are available for writing at
+ * e->ptr.  Returns false if the bytes could not be allocated. */
+UPB_FORCEINLINE
+static void encode_reserve(upb_encstate *e, size_t bytes) {
+  if ((size_t)(e->ptr - e->buf) < bytes) {
+    encode_growbuffer(e, bytes);
+    return;
+  }
+
+  e->ptr -= bytes;
+}
+
+/* Writes the given bytes to the buffer, handling reserve/advance. */
+static void encode_bytes(upb_encstate *e, const void *data, size_t len) {
+  if (len == 0) return;  /* memcpy() with zero size is UB */
+  encode_reserve(e, len);
+  memcpy(e->ptr, data, len);
+}
+
+static void encode_fixed64(upb_encstate *e, uint64_t val) {
+  val = _upb_be_swap64(val);
+  encode_bytes(e, &val, sizeof(uint64_t));
+}
+
+static void encode_fixed32(upb_encstate *e, uint32_t val) {
+  val = _upb_be_swap32(val);
+  encode_bytes(e, &val, sizeof(uint32_t));
+}
+
+UPB_NOINLINE
+static void encode_longvarint(upb_encstate *e, uint64_t val) {
+  size_t len;
+  char *start;
+
+  encode_reserve(e, UPB_PB_VARINT_MAX_LEN);
+  len = encode_varint64(val, e->ptr);
+  start = e->ptr + UPB_PB_VARINT_MAX_LEN - len;
+  memmove(start, e->ptr, len);
+  e->ptr = start;
+}
+
+UPB_FORCEINLINE
+static void encode_varint(upb_encstate *e, uint64_t val) {
+  if (val < 128 && e->ptr != e->buf) {
+    --e->ptr;
+    *e->ptr = val;
+  } else {
+    encode_longvarint(e, val);
+  }
+}
+
+static void encode_double(upb_encstate *e, double d) {
+  uint64_t u64;
+  UPB_ASSERT(sizeof(double) == sizeof(uint64_t));
+  memcpy(&u64, &d, sizeof(uint64_t));
+  encode_fixed64(e, u64);
+}
+
+static void encode_float(upb_encstate *e, float d) {
+  uint32_t u32;
+  UPB_ASSERT(sizeof(float) == sizeof(uint32_t));
+  memcpy(&u32, &d, sizeof(uint32_t));
+  encode_fixed32(e, u32);
+}
+
+static void encode_tag(upb_encstate *e, uint32_t field_number,
+                       uint8_t wire_type) {
+  encode_varint(e, (field_number << 3) | wire_type);
+}
+
+static void encode_fixedarray(upb_encstate *e, const upb_array *arr,
+                               size_t elem_size, uint32_t tag) {
+  size_t bytes = arr->len * elem_size;
+  const char* data = _upb_array_constptr(arr);
+  const char* ptr = data + bytes - elem_size;
+  if (tag) {
+    while (true) {
+      encode_bytes(e, ptr, elem_size);
+      encode_varint(e, tag);
+      if (ptr == data) break;
+      ptr -= elem_size;
+    }
+  } else {
+    encode_bytes(e, data, bytes);
+  }
+}
+
+static void encode_message(upb_encstate *e, const char *msg,
+                           const upb_msglayout *m, size_t *size);
+
+static void encode_scalar(upb_encstate *e, const void *_field_mem,
+                          const upb_msglayout *m, const upb_msglayout_field *f,
+                          bool skip_zero_value) {
+  const char *field_mem = _field_mem;
+  int wire_type;
+
+#define CASE(ctype, type, wtype, encodeval) \
+  {                                         \
+    ctype val = *(ctype *)field_mem;        \
+    if (skip_zero_value && val == 0) {      \
+      return;                               \
+    }                                       \
+    encode_##type(e, encodeval);            \
+    wire_type = wtype;                      \
+    break;                                  \
+  }
+
+  switch (f->descriptortype) {
+    case UPB_DESCRIPTOR_TYPE_DOUBLE:
+      CASE(double, double, UPB_WIRE_TYPE_64BIT, val);
+    case UPB_DESCRIPTOR_TYPE_FLOAT:
+      CASE(float, float, UPB_WIRE_TYPE_32BIT, val);
+    case UPB_DESCRIPTOR_TYPE_INT64:
+    case UPB_DESCRIPTOR_TYPE_UINT64:
+      CASE(uint64_t, varint, UPB_WIRE_TYPE_VARINT, val);
+    case UPB_DESCRIPTOR_TYPE_UINT32:
+      CASE(uint32_t, varint, UPB_WIRE_TYPE_VARINT, val);
+    case UPB_DESCRIPTOR_TYPE_INT32:
+    case UPB_DESCRIPTOR_TYPE_ENUM:
+      CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, (int64_t)val);
+    case UPB_DESCRIPTOR_TYPE_SFIXED64:
+    case UPB_DESCRIPTOR_TYPE_FIXED64:
+      CASE(uint64_t, fixed64, UPB_WIRE_TYPE_64BIT, val);
+    case UPB_DESCRIPTOR_TYPE_FIXED32:
+    case UPB_DESCRIPTOR_TYPE_SFIXED32:
+      CASE(uint32_t, fixed32, UPB_WIRE_TYPE_32BIT, val);
+    case UPB_DESCRIPTOR_TYPE_BOOL:
+      CASE(bool, varint, UPB_WIRE_TYPE_VARINT, val);
+    case UPB_DESCRIPTOR_TYPE_SINT32:
+      CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, encode_zz32(val));
+    case UPB_DESCRIPTOR_TYPE_SINT64:
+      CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, encode_zz64(val));
+    case UPB_DESCRIPTOR_TYPE_STRING:
+    case UPB_DESCRIPTOR_TYPE_BYTES: {
+      upb_strview view = *(upb_strview*)field_mem;
+      if (skip_zero_value && view.size == 0) {
+        return;
+      }
+      encode_bytes(e, view.data, view.size);
+      encode_varint(e, view.size);
+      wire_type = UPB_WIRE_TYPE_DELIMITED;
+      break;
+    }
+    case UPB_DESCRIPTOR_TYPE_GROUP: {
+      size_t size;
+      void *submsg = *(void **)field_mem;
+      const upb_msglayout *subm = m->submsgs[f->submsg_index];
+      if (submsg == NULL) {
+        return;
+      }
+      if (--e->depth == 0) encode_err(e);
+      encode_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP);
+      encode_message(e, submsg, subm, &size);
+      wire_type = UPB_WIRE_TYPE_START_GROUP;
+      e->depth++;
+      break;
+    }
+    case UPB_DESCRIPTOR_TYPE_MESSAGE: {
+      size_t size;
+      void *submsg = *(void **)field_mem;
+      const upb_msglayout *subm = m->submsgs[f->submsg_index];
+      if (submsg == NULL) {
+        return;
+      }
+      if (--e->depth == 0) encode_err(e);
+      encode_message(e, submsg, subm, &size);
+      encode_varint(e, size);
+      wire_type = UPB_WIRE_TYPE_DELIMITED;
+      e->depth++;
+      break;
+    }
+    default:
+      UPB_UNREACHABLE();
+  }
+#undef CASE
+
+  encode_tag(e, f->number, wire_type);
+}
+
+static void encode_array(upb_encstate *e, const char *field_mem,
+                         const upb_msglayout *m, const upb_msglayout_field *f) {
+  const upb_array *arr = *(const upb_array**)field_mem;
+  bool packed = f->label == _UPB_LABEL_PACKED;
+  size_t pre_len = e->limit - e->ptr;
+
+  if (arr == NULL || arr->len == 0) {
+    return;
+  }
+
+#define VARINT_CASE(ctype, encode)                                       \
+  {                                                                      \
+    const ctype *start = _upb_array_constptr(arr);                       \
+    const ctype *ptr = start + arr->len;                                 \
+    uint32_t tag = packed ? 0 : (f->number << 3) | UPB_WIRE_TYPE_VARINT; \
+    do {                                                                 \
+      ptr--;                                                             \
+      encode_varint(e, encode);                                          \
+      if (tag) encode_varint(e, tag);                                    \
+    } while (ptr != start);                                              \
+  }                                                                      \
+  break;
+
+#define TAG(wire_type) (packed ? 0 : (f->number << 3 | wire_type))
+
+  switch (f->descriptortype) {
+    case UPB_DESCRIPTOR_TYPE_DOUBLE:
+      encode_fixedarray(e, arr, sizeof(double), TAG(UPB_WIRE_TYPE_64BIT));
+      break;
+    case UPB_DESCRIPTOR_TYPE_FLOAT:
+      encode_fixedarray(e, arr, sizeof(float), TAG(UPB_WIRE_TYPE_32BIT));
+      break;
+    case UPB_DESCRIPTOR_TYPE_SFIXED64:
+    case UPB_DESCRIPTOR_TYPE_FIXED64:
+      encode_fixedarray(e, arr, sizeof(uint64_t), TAG(UPB_WIRE_TYPE_64BIT));
+      break;
+    case UPB_DESCRIPTOR_TYPE_FIXED32:
+    case UPB_DESCRIPTOR_TYPE_SFIXED32:
+      encode_fixedarray(e, arr, sizeof(uint32_t), TAG(UPB_WIRE_TYPE_32BIT));
+      break;
+    case UPB_DESCRIPTOR_TYPE_INT64:
+    case UPB_DESCRIPTOR_TYPE_UINT64:
+      VARINT_CASE(uint64_t, *ptr);
+    case UPB_DESCRIPTOR_TYPE_UINT32:
+      VARINT_CASE(uint32_t, *ptr);
+    case UPB_DESCRIPTOR_TYPE_INT32:
+    case UPB_DESCRIPTOR_TYPE_ENUM:
+      VARINT_CASE(int32_t, (int64_t)*ptr);
+    case UPB_DESCRIPTOR_TYPE_BOOL:
+      VARINT_CASE(bool, *ptr);
+    case UPB_DESCRIPTOR_TYPE_SINT32:
+      VARINT_CASE(int32_t, encode_zz32(*ptr));
+    case UPB_DESCRIPTOR_TYPE_SINT64:
+      VARINT_CASE(int64_t, encode_zz64(*ptr));
+    case UPB_DESCRIPTOR_TYPE_STRING:
+    case UPB_DESCRIPTOR_TYPE_BYTES: {
+      const upb_strview *start = _upb_array_constptr(arr);
+      const upb_strview *ptr = start + arr->len;
+      do {
+        ptr--;
+        encode_bytes(e, ptr->data, ptr->size);
+        encode_varint(e, ptr->size);
+        encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
+      } while (ptr != start);
+      return;
+    }
+    case UPB_DESCRIPTOR_TYPE_GROUP: {
+      const void *const*start = _upb_array_constptr(arr);
+      const void *const*ptr = start + arr->len;
+      const upb_msglayout *subm = m->submsgs[f->submsg_index];
+      if (--e->depth == 0) encode_err(e);
+      do {
+        size_t size;
+        ptr--;
+        encode_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP);
+        encode_message(e, *ptr, subm, &size);
+        encode_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP);
+      } while (ptr != start);
+      e->depth++;
+      return;
+    }
+    case UPB_DESCRIPTOR_TYPE_MESSAGE: {
+      const void *const*start = _upb_array_constptr(arr);
+      const void *const*ptr = start + arr->len;
+      const upb_msglayout *subm = m->submsgs[f->submsg_index];
+      if (--e->depth == 0) encode_err(e);
+      do {
+        size_t size;
+        ptr--;
+        encode_message(e, *ptr, subm, &size);
+        encode_varint(e, size);
+        encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
+      } while (ptr != start);
+      e->depth++;
+      return;
+    }
+  }
+#undef VARINT_CASE
+
+  if (packed) {
+    encode_varint(e, e->limit - e->ptr - pre_len);
+    encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
+  }
+}
+
+static void encode_mapentry(upb_encstate *e, uint32_t number,
+                            const upb_msglayout *layout,
+                            const upb_map_entry *ent) {
+  const upb_msglayout_field *key_field = &layout->fields[0];
+  const upb_msglayout_field *val_field = &layout->fields[1];
+  size_t pre_len = e->limit - e->ptr;
+  size_t size;
+  encode_scalar(e, &ent->v, layout, val_field, false);
+  encode_scalar(e, &ent->k, layout, key_field, false);
+  size = (e->limit - e->ptr) - pre_len;
+  encode_varint(e, size);
+  encode_tag(e, number, UPB_WIRE_TYPE_DELIMITED);
+}
+
+static void encode_map(upb_encstate *e, const char *field_mem,
+                       const upb_msglayout *m, const upb_msglayout_field *f) {
+  const upb_map *map = *(const upb_map**)field_mem;
+  const upb_msglayout *layout = m->submsgs[f->submsg_index];
+  UPB_ASSERT(layout->field_count == 2);
+
+  if (map == NULL) return;
+
+  if (e->options & UPB_ENCODE_DETERMINISTIC) {
+    _upb_sortedmap sorted;
+    _upb_mapsorter_pushmap(&e->sorter, layout->fields[0].descriptortype, map,
+                           &sorted);
+    upb_map_entry ent;
+    while (_upb_sortedmap_next(&e->sorter, map, &sorted, &ent)) {
+      encode_mapentry(e, f->number, layout, &ent);
+    }
+    _upb_mapsorter_popmap(&e->sorter, &sorted);
+  } else {
+    upb_strtable_iter i;
+    upb_strtable_begin(&i, &map->table);
+    for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
+      upb_strview key = upb_strtable_iter_key(&i);
+      const upb_value val = upb_strtable_iter_value(&i);
+      upb_map_entry ent;
+      _upb_map_fromkey(key, &ent.k, map->key_size);
+      _upb_map_fromvalue(val, &ent.v, map->val_size);
+      encode_mapentry(e, f->number, layout, &ent);
+    }
+  }
+}
+
+static void encode_scalarfield(upb_encstate *e, const char *msg,
+                               const upb_msglayout *m,
+                               const upb_msglayout_field *f) {
+  bool skip_empty = false;
+  if (f->presence == 0) {
+    /* Proto3 presence. */
+    skip_empty = true;
+  } else if (f->presence > 0) {
+    /* Proto2 presence: hasbit. */
+    if (!_upb_hasbit_field(msg, f)) return;
+  } else {
+    /* Field is in a oneof. */
+    if (_upb_getoneofcase_field(msg, f) != f->number) return;
+  }
+  encode_scalar(e, msg + f->offset, m, f, skip_empty);
+}
+
+static void encode_message(upb_encstate *e, const char *msg,
+                           const upb_msglayout *m, size_t *size) {
+  size_t pre_len = e->limit - e->ptr;
+  const upb_msglayout_field *f = &m->fields[m->field_count];
+  const upb_msglayout_field *first = &m->fields[0];
+
+  if ((e->options & UPB_ENCODE_SKIPUNKNOWN) == 0) {
+    size_t unknown_size;
+    const char *unknown = upb_msg_getunknown(msg, &unknown_size);
+
+    if (unknown) {
+      encode_bytes(e, unknown, unknown_size);
+    }
+  }
+
+  while (f != first) {
+    f--;
+    if (_upb_isrepeated(f)) {
+      encode_array(e, msg + f->offset, m, f);
+    } else if (f->label == _UPB_LABEL_MAP) {
+      encode_map(e, msg + f->offset, m, f);
+    } else {
+      encode_scalarfield(e, msg, m, f);
+    }
+  }
+
+  *size = (e->limit - e->ptr) - pre_len;
+}
+
+char *upb_encode_ex(const void *msg, const upb_msglayout *l, int options,
+                    upb_arena *arena, size_t *size) {
+  upb_encstate e;
+  unsigned depth = (unsigned)options >> 16;
+
+  e.alloc = upb_arena_alloc(arena);
+  e.buf = NULL;
+  e.limit = NULL;
+  e.ptr = NULL;
+  e.depth = depth ? depth : 64;
+  e.options = options;
+  _upb_mapsorter_init(&e.sorter);
+  char *ret = NULL;
+
+  if (UPB_SETJMP(e.err)) {
+    *size = 0;
+    ret = NULL;
+  } else {
+    encode_message(&e, msg, l, size);
+    *size = e.limit - e.ptr;
+    if (*size == 0) {
+      static char ch;
+      ret = &ch;
+    } else {
+      UPB_ASSERT(e.ptr);
+      ret = e.ptr;
+    }
+  }
+
+  _upb_mapsorter_destroy(&e.sorter);
+  return ret;
+}
+
+
+
+
+/** upb_msg *******************************************************************/
+
+static const size_t overhead = sizeof(upb_msg_internal);
+
+static const upb_msg_internal *upb_msg_getinternal_const(const upb_msg *msg) {
+  ptrdiff_t size = sizeof(upb_msg_internal);
+  return (upb_msg_internal*)((char*)msg - size);
+}
+
+upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a) {
+  return _upb_msg_new_inl(l, a);
+}
+
+void _upb_msg_clear(upb_msg *msg, const upb_msglayout *l) {
+  void *mem = UPB_PTR_AT(msg, -sizeof(upb_msg_internal), char);
+  memset(mem, 0, upb_msg_sizeof(l));
+}
+
+bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
+                         upb_arena *arena) {
+
+  upb_msg_internal *in = upb_msg_getinternal(msg);
+  if (!in->unknown) {
+    size_t size = 128;
+    while (size < len) size *= 2;
+    in->unknown = upb_arena_malloc(arena, size + overhead);
+    if (!in->unknown) return false;
+    in->unknown->size = size;
+    in->unknown->len = 0;
+  } else if (in->unknown->size - in->unknown->len < len) {
+    size_t need = in->unknown->len + len;
+    size_t size = in->unknown->size;
+    while (size < need)  size *= 2;
+    in->unknown = upb_arena_realloc(
+        arena, in->unknown, in->unknown->size + overhead, size + overhead);
+    if (!in->unknown) return false;
+    in->unknown->size = size;
+  }
+  memcpy(UPB_PTR_AT(in->unknown + 1, in->unknown->len, char), data, len);
+  in->unknown->len += len;
+  return true;
+}
+
+void _upb_msg_discardunknown_shallow(upb_msg *msg) {
+  upb_msg_internal *in = upb_msg_getinternal(msg);
+  if (in->unknown) {
+    in->unknown->len = 0;
+  }
+}
+
+const char *upb_msg_getunknown(const upb_msg *msg, size_t *len) {
+  const upb_msg_internal *in = upb_msg_getinternal_const(msg);
+  if (in->unknown) {
+    *len = in->unknown->len;
+    return (char*)(in->unknown + 1);
+  } else {
+    *len = 0;
+    return NULL;
+  }
+}
+
+/** upb_array *****************************************************************/
+
+bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena) {
+  size_t new_size = UPB_MAX(arr->size, 4);
+  int elem_size_lg2 = arr->data & 7;
+  size_t old_bytes = arr->size << elem_size_lg2;
+  size_t new_bytes;
+  void* ptr = _upb_array_ptr(arr);
+
+  /* Log2 ceiling of size. */
+  while (new_size < min_size) new_size *= 2;
+
+  new_bytes = new_size << elem_size_lg2;
+  ptr = upb_arena_realloc(arena, ptr, old_bytes, new_bytes);
+
+  if (!ptr) {
+    return false;
+  }
+
+  arr->data = _upb_tag_arrptr(ptr, elem_size_lg2);
+  arr->size = new_size;
+  return true;
+}
+
+static upb_array *getorcreate_array(upb_array **arr_ptr, int elem_size_lg2,
+                                    upb_arena *arena) {
+  upb_array *arr = *arr_ptr;
+  if (!arr) {
+    arr = _upb_array_new(arena, 4, elem_size_lg2);
+    if (!arr) return NULL;
+    *arr_ptr = arr;
+  }
+  return arr;
+}
+
+void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size,
+                                 int elem_size_lg2, upb_arena *arena) {
+  upb_array *arr = getorcreate_array(arr_ptr, elem_size_lg2, arena);
+  return arr && _upb_array_resize(arr, size, arena) ? _upb_array_ptr(arr)
+                                                    : NULL;
+}
+
+bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value,
+                                int elem_size_lg2, upb_arena *arena) {
+  upb_array *arr = getorcreate_array(arr_ptr, elem_size_lg2, arena);
+  if (!arr) return false;
+
+  size_t elems = arr->len;
+
+  if (!_upb_array_resize(arr, elems + 1, arena)) {
+    return false;
+  }
+
+  char *data = _upb_array_ptr(arr);
+  memcpy(data + (elems << elem_size_lg2), value, 1 << elem_size_lg2);
+  return true;
+}
+
+/** upb_map *******************************************************************/
+
+upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size) {
+  upb_map *map = upb_arena_malloc(a, sizeof(upb_map));
+
+  if (!map) {
+    return NULL;
+  }
+
+  upb_strtable_init2(&map->table, UPB_CTYPE_INT32, 4, upb_arena_alloc(a));
+  map->key_size = key_size;
+  map->val_size = value_size;
+
+  return map;
+}
+
+static void _upb_mapsorter_getkeys(const void *_a, const void *_b, void *a_key,
+                                   void *b_key, size_t size) {
+  const upb_tabent *const*a = _a;
+  const upb_tabent *const*b = _b;
+  upb_strview a_tabkey = upb_tabstrview((*a)->key);
+  upb_strview b_tabkey = upb_tabstrview((*b)->key);
+  _upb_map_fromkey(a_tabkey, a_key, size);
+  _upb_map_fromkey(b_tabkey, b_key, size);
+}
+
+static int _upb_mapsorter_cmpi64(const void *_a, const void *_b) {
+  int64_t a, b;
+  _upb_mapsorter_getkeys(_a, _b, &a, &b, 8);
+  return a - b;
+}
+
+static int _upb_mapsorter_cmpu64(const void *_a, const void *_b) {
+  uint64_t a, b;
+  _upb_mapsorter_getkeys(_a, _b, &a, &b, 8);
+  return a - b;
+}
+
+static int _upb_mapsorter_cmpi32(const void *_a, const void *_b) {
+  int32_t a, b;
+  _upb_mapsorter_getkeys(_a, _b, &a, &b, 4);
+  return a - b;
+}
+
+static int _upb_mapsorter_cmpu32(const void *_a, const void *_b) {
+  uint32_t a, b;
+  _upb_mapsorter_getkeys(_a, _b, &a, &b, 4);
+  return a - b;
+}
+
+static int _upb_mapsorter_cmpbool(const void *_a, const void *_b) {
+  bool a, b;
+  _upb_mapsorter_getkeys(_a, _b, &a, &b, 1);
+  return a - b;
+}
+
+static int _upb_mapsorter_cmpstr(const void *_a, const void *_b) {
+  upb_strview a, b;
+  _upb_mapsorter_getkeys(_a, _b, &a, &b, UPB_MAPTYPE_STRING);
+  size_t common_size = UPB_MIN(a.size, b.size);
+  int cmp = memcmp(a.data, b.data, common_size);
+  if (cmp) return cmp;
+  return a.size - b.size;
+}
+
+bool _upb_mapsorter_pushmap(_upb_mapsorter *s, upb_descriptortype_t key_type,
+                            const upb_map *map, _upb_sortedmap *sorted) {
+  int map_size = _upb_map_size(map);
+  sorted->start = s->size;
+  sorted->pos = sorted->start;
+  sorted->end = sorted->start + map_size;
+
+  /* Grow s->entries if necessary. */
+  if (sorted->end > s->cap) {
+    s->cap = _upb_lg2ceilsize(sorted->end);
+    s->entries = realloc(s->entries, s->cap * sizeof(*s->entries));
+    if (!s->entries) return false;
+  }
+
+  s->size = sorted->end;
+
+  /* Copy non-empty entries from the table to s->entries. */
+  upb_tabent const**dst = &s->entries[sorted->start];
+  const upb_tabent *src = map->table.t.entries;
+  const upb_tabent *end = src + upb_table_size(&map->table.t);
+  for (; src < end; src++) {
+    if (!upb_tabent_isempty(src)) {
+      *dst = src;
+      dst++;
+    }
+  }
+  UPB_ASSERT(dst == &s->entries[sorted->end]);
+
+  /* Sort entries according to the key type. */
+
+  int (*compar)(const void *, const void *);
+
+  switch (key_type) {
+    case UPB_DESCRIPTOR_TYPE_INT64:
+    case UPB_DESCRIPTOR_TYPE_SFIXED64:
+    case UPB_DESCRIPTOR_TYPE_SINT64:
+      compar = _upb_mapsorter_cmpi64;
+      break;
+    case UPB_DESCRIPTOR_TYPE_UINT64:
+    case UPB_DESCRIPTOR_TYPE_FIXED64:
+      compar = _upb_mapsorter_cmpu64;
+      break;
+    case UPB_DESCRIPTOR_TYPE_INT32:
+    case UPB_DESCRIPTOR_TYPE_SINT32:
+    case UPB_DESCRIPTOR_TYPE_SFIXED32:
+    case UPB_DESCRIPTOR_TYPE_ENUM:
+      compar = _upb_mapsorter_cmpi32;
+      break;
+    case UPB_DESCRIPTOR_TYPE_UINT32:
+    case UPB_DESCRIPTOR_TYPE_FIXED32:
+      compar = _upb_mapsorter_cmpu32;
+      break;
+    case UPB_DESCRIPTOR_TYPE_BOOL:
+      compar = _upb_mapsorter_cmpbool;
+      break;
+    case UPB_DESCRIPTOR_TYPE_STRING:
+      compar = _upb_mapsorter_cmpstr;
+      break;
+    default:
+      UPB_UNREACHABLE();
+  }
+
+  qsort(&s->entries[sorted->start], map_size, sizeof(*s->entries), compar);
+  return true;
+}
+/*
+** upb_table Implementation
+**
+** Implementation is heavily inspired by Lua's ltable.c.
+*/
+
+#include <string.h>
+
+#include "third_party/wyhash/wyhash.h"
+
+/* Must be last. */
+
+#define UPB_MAXARRSIZE 16  /* 64k. */
+
+/* From Chromium. */
+#define ARRAY_SIZE(x) \
+    ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
+
+static const double MAX_LOAD = 0.85;
+
+/* The minimum utilization of the array part of a mixed hash/array table.  This
+ * is a speed/memory-usage tradeoff (though it's not straightforward because of
+ * cache effects).  The lower this is, the more memory we'll use. */
+static const double MIN_DENSITY = 0.1;
+
+bool is_pow2(uint64_t v) { return v == 0 || (v & (v - 1)) == 0; }
+
+int log2ceil(uint64_t v) {
+  int ret = 0;
+  bool pow2 = is_pow2(v);
+  while (v >>= 1) ret++;
+  ret = pow2 ? ret : ret + 1;  /* Ceiling. */
+  return UPB_MIN(UPB_MAXARRSIZE, ret);
+}
+
+char *upb_strdup(const char *s, upb_alloc *a) {
+  return upb_strdup2(s, strlen(s), a);
+}
+
+char *upb_strdup2(const char *s, size_t len, upb_alloc *a) {
+  size_t n;
+  char *p;
+
+  /* Prevent overflow errors. */
+  if (len == SIZE_MAX) return NULL;
+  /* Always null-terminate, even if binary data; but don't rely on the input to
+   * have a null-terminating byte since it may be a raw binary buffer. */
+  n = len + 1;
+  p = upb_malloc(a, n);
+  if (p) {
+    memcpy(p, s, len);
+    p[len] = 0;
+  }
+  return p;
+}
+
+/* A type to represent the lookup key of either a strtable or an inttable. */
+typedef union {
+  uintptr_t num;
+  struct {
+    const char *str;
+    size_t len;
+  } str;
+} lookupkey_t;
+
+static lookupkey_t strkey2(const char *str, size_t len) {
+  lookupkey_t k;
+  k.str.str = str;
+  k.str.len = len;
+  return k;
+}
+
+static lookupkey_t intkey(uintptr_t key) {
+  lookupkey_t k;
+  k.num = key;
+  return k;
+}
+
+typedef uint32_t hashfunc_t(upb_tabkey key);
+typedef bool eqlfunc_t(upb_tabkey k1, lookupkey_t k2);
+
+/* Base table (shared code) ***************************************************/
+
+/* For when we need to cast away const. */
+static upb_tabent *mutable_entries(upb_table *t) {
+  return (upb_tabent*)t->entries;
+}
+
+static bool isfull(upb_table *t) {
+  return t->count == t->max_count;
+}
+
+static bool init(upb_table *t, uint8_t size_lg2, upb_alloc *a) {
+  size_t bytes;
+
+  t->count = 0;
+  t->size_lg2 = size_lg2;
+  t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0;
+  t->max_count = upb_table_size(t) * MAX_LOAD;
+  bytes = upb_table_size(t) * sizeof(upb_tabent);
+  if (bytes > 0) {
+    t->entries = upb_malloc(a, bytes);
+    if (!t->entries) return false;
+    memset(mutable_entries(t), 0, bytes);
+  } else {
+    t->entries = NULL;
+  }
+  return true;
+}
+
+static void uninit(upb_table *t, upb_alloc *a) {
+  upb_free(a, mutable_entries(t));
+}
+
+static upb_tabent *emptyent(upb_table *t, upb_tabent *e) {
+  upb_tabent *begin = mutable_entries(t);
+  upb_tabent *end = begin + upb_table_size(t);
+  for (e = e + 1; e < end; e++) {
+    if (upb_tabent_isempty(e)) return e;
+  }
+  for (e = begin; e < end; e++) {
+    if (upb_tabent_isempty(e)) return e;
+  }
+  UPB_ASSERT(false);
+  return NULL;
+}
+
+static upb_tabent *getentry_mutable(upb_table *t, uint32_t hash) {
+  return (upb_tabent*)upb_getentry(t, hash);
+}
+
+static const upb_tabent *findentry(const upb_table *t, lookupkey_t key,
+                                   uint32_t hash, eqlfunc_t *eql) {
+  const upb_tabent *e;
+
+  if (t->size_lg2 == 0) return NULL;
+  e = upb_getentry(t, hash);
+  if (upb_tabent_isempty(e)) return NULL;
+  while (1) {
+    if (eql(e->key, key)) return e;
+    if ((e = e->next) == NULL) return NULL;
+  }
+}
+
+static upb_tabent *findentry_mutable(upb_table *t, lookupkey_t key,
+                                     uint32_t hash, eqlfunc_t *eql) {
+  return (upb_tabent*)findentry(t, key, hash, eql);
+}
+
+static bool lookup(const upb_table *t, lookupkey_t key, upb_value *v,
+                   uint32_t hash, eqlfunc_t *eql) {
+  const upb_tabent *e = findentry(t, key, hash, eql);
+  if (e) {
+    if (v) {
+      _upb_value_setval(v, e->val.val);
+    }
+    return true;
+  } else {
+    return false;
+  }
+}
+
+/* The given key must not already exist in the table. */
+static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey,
+                   upb_value val, uint32_t hash,
+                   hashfunc_t *hashfunc, eqlfunc_t *eql) {
+  upb_tabent *mainpos_e;
+  upb_tabent *our_e;
+
+  UPB_ASSERT(findentry(t, key, hash, eql) == NULL);
+
+  t->count++;
+  mainpos_e = getentry_mutable(t, hash);
+  our_e = mainpos_e;
+
+  if (upb_tabent_isempty(mainpos_e)) {
+    /* Our main position is empty; use it. */
+    our_e->next = NULL;
+  } else {
+    /* Collision. */
+    upb_tabent *new_e = emptyent(t, mainpos_e);
+    /* Head of collider's chain. */
+    upb_tabent *chain = getentry_mutable(t, hashfunc(mainpos_e->key));
+    if (chain == mainpos_e) {
+      /* Existing ent is in its main position (it has the same hash as us, and
+       * is the head of our chain).  Insert to new ent and append to this chain. */
+      new_e->next = mainpos_e->next;
+      mainpos_e->next = new_e;
+      our_e = new_e;
+    } else {
+      /* Existing ent is not in its main position (it is a node in some other
+       * chain).  This implies that no existing ent in the table has our hash.
+       * Evict it (updating its chain) and use its ent for head of our chain. */
+      *new_e = *mainpos_e;  /* copies next. */
+      while (chain->next != mainpos_e) {
+        chain = (upb_tabent*)chain->next;
+        UPB_ASSERT(chain);
+      }
+      chain->next = new_e;
+      our_e = mainpos_e;
+      our_e->next = NULL;
+    }
+  }
+  our_e->key = tabkey;
+  our_e->val.val = val.val;
+  UPB_ASSERT(findentry(t, key, hash, eql) == our_e);
+}
+
+static bool rm(upb_table *t, lookupkey_t key, upb_value *val,
+               upb_tabkey *removed, uint32_t hash, eqlfunc_t *eql) {
+  upb_tabent *chain = getentry_mutable(t, hash);
+  if (upb_tabent_isempty(chain)) return false;
+  if (eql(chain->key, key)) {
+    /* Element to remove is at the head of its chain. */
+    t->count--;
+    if (val) _upb_value_setval(val, chain->val.val);
+    if (removed) *removed = chain->key;
+    if (chain->next) {
+      upb_tabent *move = (upb_tabent*)chain->next;
+      *chain = *move;
+      move->key = 0;  /* Make the slot empty. */
+    } else {
+      chain->key = 0;  /* Make the slot empty. */
+    }
+    return true;
+  } else {
+    /* Element to remove is either in a non-head position or not in the
+     * table. */
+    while (chain->next && !eql(chain->next->key, key)) {
+      chain = (upb_tabent*)chain->next;
+    }
+    if (chain->next) {
+      /* Found element to remove. */
+      upb_tabent *rm = (upb_tabent*)chain->next;
+      t->count--;
+      if (val) _upb_value_setval(val, chain->next->val.val);
+      if (removed) *removed = rm->key;
+      rm->key = 0;  /* Make the slot empty. */
+      chain->next = rm->next;
+      return true;
+    } else {
+      /* Element to remove is not in the table. */
+      return false;
+    }
+  }
+}
+
+static size_t next(const upb_table *t, size_t i) {
+  do {
+    if (++i >= upb_table_size(t))
+      return SIZE_MAX - 1;  /* Distinct from -1. */
+  } while(upb_tabent_isempty(&t->entries[i]));
+
+  return i;
+}
+
+static size_t begin(const upb_table *t) {
+  return next(t, -1);
+}
+
+
+/* upb_strtable ***************************************************************/
+
+/* A simple "subclass" of upb_table that only adds a hash function for strings. */
+
+static upb_tabkey strcopy(lookupkey_t k2, upb_alloc *a) {
+  uint32_t len = (uint32_t) k2.str.len;
+  char *str = upb_malloc(a, k2.str.len + sizeof(uint32_t) + 1);
+  if (str == NULL) return 0;
+  memcpy(str, &len, sizeof(uint32_t));
+  if (k2.str.len) memcpy(str + sizeof(uint32_t), k2.str.str, k2.str.len);
+  str[sizeof(uint32_t) + k2.str.len] = '\0';
+  return (uintptr_t)str;
+}
+
+static uint32_t table_hash(const char *p, size_t n) {
+  return wyhash(p, n, 0, _wyp);
+}
+
+static uint32_t strhash(upb_tabkey key) {
+  uint32_t len;
+  char *str = upb_tabstr(key, &len);
+  return table_hash(str, len);
+}
+
+static bool streql(upb_tabkey k1, lookupkey_t k2) {
+  uint32_t len;
+  char *str = upb_tabstr(k1, &len);
+  return len == k2.str.len && (len == 0 || memcmp(str, k2.str.str, len) == 0);
+}
+
+bool upb_strtable_init2(upb_strtable *t, upb_ctype_t ctype,
+                        size_t expected_size, upb_alloc *a) {
+  UPB_UNUSED(ctype);  /* TODO(haberman): rm */
+  // Multiply by approximate reciprocal of MAX_LOAD (0.85), with pow2 denominator.
+  size_t need_entries = (expected_size + 1) * 1204 / 1024;
+  UPB_ASSERT(need_entries >= expected_size * 0.85);
+  int size_lg2 = _upb_lg2ceil(need_entries);
+  return init(&t->t, size_lg2, a);
+}
+
+void upb_strtable_clear(upb_strtable *t) {
+  size_t bytes = upb_table_size(&t->t) * sizeof(upb_tabent);
+  t->t.count = 0;
+  memset((char*)t->t.entries, 0, bytes);
+}
+
+void upb_strtable_uninit2(upb_strtable *t, upb_alloc *a) {
+  size_t i;
+  for (i = 0; i < upb_table_size(&t->t); i++)
+    upb_free(a, (void*)t->t.entries[i].key);
+  uninit(&t->t, a);
+}
+
+bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a) {
+  upb_strtable new_table;
+  upb_strtable_iter i;
+
+  if (!init(&new_table.t, size_lg2, a))
+    return false;
+  upb_strtable_begin(&i, t);
+  for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) {
+    upb_strview key = upb_strtable_iter_key(&i);
+    upb_strtable_insert3(
+        &new_table, key.data, key.size,
+        upb_strtable_iter_value(&i), a);
+  }
+  upb_strtable_uninit2(t, a);
+  *t = new_table;
+  return true;
+}
+
+bool upb_strtable_insert3(upb_strtable *t, const char *k, size_t len,
+                          upb_value v, upb_alloc *a) {
+  lookupkey_t key;
+  upb_tabkey tabkey;
+  uint32_t hash;
+
+  if (isfull(&t->t)) {
+    /* Need to resize.  New table of double the size, add old elements to it. */
+    if (!upb_strtable_resize(t, t->t.size_lg2 + 1, a)) {
+      return false;
+    }
+  }
+
+  key = strkey2(k, len);
+  tabkey = strcopy(key, a);
+  if (tabkey == 0) return false;
+
+  hash = table_hash(key.str.str, key.str.len);
+  insert(&t->t, key, tabkey, v, hash, &strhash, &streql);
+  return true;
+}
+
+bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
+                          upb_value *v) {
+  uint32_t hash = table_hash(key, len);
+  return lookup(&t->t, strkey2(key, len), v, hash, &streql);
+}
+
+bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len,
+                         upb_value *val, upb_alloc *alloc) {
+  uint32_t hash = table_hash(key, len);
+  upb_tabkey tabkey;
+  if (rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql)) {
+    if (alloc) {
+      /* Arena-based allocs don't need to free and won't pass this. */
+      upb_free(alloc, (void*)tabkey);
+    }
+    return true;
+  } else {
+    return false;
+  }
+}
+
+/* Iteration */
+
+void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t) {
+  i->t = t;
+  i->index = begin(&t->t);
+}
+
+void upb_strtable_next(upb_strtable_iter *i) {
+  i->index = next(&i->t->t, i->index);
+}
+
+bool upb_strtable_done(const upb_strtable_iter *i) {
+  if (!i->t) return true;
+  return i->index >= upb_table_size(&i->t->t) ||
+         upb_tabent_isempty(str_tabent(i));
+}
+
+upb_strview upb_strtable_iter_key(const upb_strtable_iter *i) {
+  upb_strview key;
+  uint32_t len;
+  UPB_ASSERT(!upb_strtable_done(i));
+  key.data = upb_tabstr(str_tabent(i)->key, &len);
+  key.size = len;
+  return key;
+}
+
+upb_value upb_strtable_iter_value(const upb_strtable_iter *i) {
+  UPB_ASSERT(!upb_strtable_done(i));
+  return _upb_value_val(str_tabent(i)->val.val);
+}
+
+void upb_strtable_iter_setdone(upb_strtable_iter *i) {
+  i->t = NULL;
+  i->index = SIZE_MAX;
+}
+
+bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
+                               const upb_strtable_iter *i2) {
+  if (upb_strtable_done(i1) && upb_strtable_done(i2))
+    return true;
+  return i1->t == i2->t && i1->index == i2->index;
+}
+
+
+/* upb_inttable ***************************************************************/
+
+/* For inttables we use a hybrid structure where small keys are kept in an
+ * array and large keys are put in the hash table. */
+
+static uint32_t inthash(upb_tabkey key) { return upb_inthash(key); }
+
+static bool inteql(upb_tabkey k1, lookupkey_t k2) {
+  return k1 == k2.num;
+}
+
+static upb_tabval *mutable_array(upb_inttable *t) {
+  return (upb_tabval*)t->array;
+}
+
+static upb_tabval *inttable_val(upb_inttable *t, uintptr_t key) {
+  if (key < t->array_size) {
+    return upb_arrhas(t->array[key]) ? &(mutable_array(t)[key]) : NULL;
+  } else {
+    upb_tabent *e =
+        findentry_mutable(&t->t, intkey(key), upb_inthash(key), &inteql);
+    return e ? &e->val : NULL;
+  }
+}
+
+static const upb_tabval *inttable_val_const(const upb_inttable *t,
+                                            uintptr_t key) {
+  return inttable_val((upb_inttable*)t, key);
+}
+
+size_t upb_inttable_count(const upb_inttable *t) {
+  return t->t.count + t->array_count;
+}
+
+static void check(upb_inttable *t) {
+  UPB_UNUSED(t);
+#if defined(UPB_DEBUG_TABLE) && !defined(NDEBUG)
+  {
+    /* This check is very expensive (makes inserts/deletes O(N)). */
+    size_t count = 0;
+    upb_inttable_iter i;
+    upb_inttable_begin(&i, t);
+    for(; !upb_inttable_done(&i); upb_inttable_next(&i), count++) {
+      UPB_ASSERT(upb_inttable_lookup(t, upb_inttable_iter_key(&i), NULL));
+    }
+    UPB_ASSERT(count == upb_inttable_count(t));
+  }
+#endif
+}
+
+bool upb_inttable_sizedinit(upb_inttable *t, size_t asize, int hsize_lg2,
+                            upb_alloc *a) {
+  size_t array_bytes;
+
+  if (!init(&t->t, hsize_lg2, a)) return false;
+  /* Always make the array part at least 1 long, so that we know key 0
+   * won't be in the hash part, which simplifies things. */
+  t->array_size = UPB_MAX(1, asize);
+  t->array_count = 0;
+  array_bytes = t->array_size * sizeof(upb_value);
+  t->array = upb_malloc(a, array_bytes);
+  if (!t->array) {
+    uninit(&t->t, a);
+    return false;
+  }
+  memset(mutable_array(t), 0xff, array_bytes);
+  check(t);
+  return true;
+}
+
+bool upb_inttable_init2(upb_inttable *t, upb_ctype_t ctype, upb_alloc *a) {
+  UPB_UNUSED(ctype);  /* TODO(haberman): rm */
+  return upb_inttable_sizedinit(t, 0, 4, a);
+}
+
+void upb_inttable_uninit2(upb_inttable *t, upb_alloc *a) {
+  uninit(&t->t, a);
+  upb_free(a, mutable_array(t));
+}
+
+bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val,
+                          upb_alloc *a) {
+  upb_tabval tabval;
+  tabval.val = val.val;
+  UPB_ASSERT(upb_arrhas(tabval));  /* This will reject (uint64_t)-1.  Fix this. */
+
+  if (key < t->array_size) {
+    UPB_ASSERT(!upb_arrhas(t->array[key]));
+    t->array_count++;
+    mutable_array(t)[key].val = val.val;
+  } else {
+    if (isfull(&t->t)) {
+      /* Need to resize the hash part, but we re-use the array part. */
+      size_t i;
+      upb_table new_table;
+
+      if (!init(&new_table, t->t.size_lg2 + 1, a)) {
+        return false;
+      }
+
+      for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) {
+        const upb_tabent *e = &t->t.entries[i];
+        uint32_t hash;
+        upb_value v;
+
+        _upb_value_setval(&v, e->val.val);
+        hash = upb_inthash(e->key);
+        insert(&new_table, intkey(e->key), e->key, v, hash, &inthash, &inteql);
+      }
+
+      UPB_ASSERT(t->t.count == new_table.count);
+
+      uninit(&t->t, a);
+      t->t = new_table;
+    }
+    insert(&t->t, intkey(key), key, val, upb_inthash(key), &inthash, &inteql);
+  }
+  check(t);
+  return true;
+}
+
+bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v) {
+  const upb_tabval *table_v = inttable_val_const(t, key);
+  if (!table_v) return false;
+  if (v) _upb_value_setval(v, table_v->val);
+  return true;
+}
+
+bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val) {
+  upb_tabval *table_v = inttable_val(t, key);
+  if (!table_v) return false;
+  table_v->val = val.val;
+  return true;
+}
+
+bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) {
+  bool success;
+  if (key < t->array_size) {
+    if (upb_arrhas(t->array[key])) {
+      upb_tabval empty = UPB_TABVALUE_EMPTY_INIT;
+      t->array_count--;
+      if (val) {
+        _upb_value_setval(val, t->array[key].val);
+      }
+      mutable_array(t)[key] = empty;
+      success = true;
+    } else {
+      success = false;
+    }
+  } else {
+    success = rm(&t->t, intkey(key), val, NULL, upb_inthash(key), &inteql);
+  }
+  check(t);
+  return success;
+}
+
+bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val,
+                             upb_alloc *a) {
+  return upb_inttable_insert2(t, (uintptr_t)key, val, a);
+}
+
+bool upb_inttable_lookupptr(const upb_inttable *t, const void *key,
+                            upb_value *v) {
+  return upb_inttable_lookup(t, (uintptr_t)key, v);
+}
+
+bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val) {
+  return upb_inttable_remove(t, (uintptr_t)key, val);
+}
+
+void upb_inttable_compact2(upb_inttable *t, upb_alloc *a) {
+  /* A power-of-two histogram of the table keys. */
+  size_t counts[UPB_MAXARRSIZE + 1] = {0};
+
+  /* The max key in each bucket. */
+  uintptr_t max[UPB_MAXARRSIZE + 1] = {0};
+
+  upb_inttable_iter i;
+  size_t arr_count;
+  int size_lg2;
+  upb_inttable new_t;
+
+  upb_inttable_begin(&i, t);
+  for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+    uintptr_t key = upb_inttable_iter_key(&i);
+    int bucket = log2ceil(key);
+    max[bucket] = UPB_MAX(max[bucket], key);
+    counts[bucket]++;
+  }
+
+  /* Find the largest power of two that satisfies the MIN_DENSITY
+   * definition (while actually having some keys). */
+  arr_count = upb_inttable_count(t);
+
+  for (size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 0; size_lg2--) {
+    if (counts[size_lg2] == 0) {
+      /* We can halve again without losing any entries. */
+      continue;
+    } else if (arr_count >= (1 << size_lg2) * MIN_DENSITY) {
+      break;
+    }
+
+    arr_count -= counts[size_lg2];
+  }
+
+  UPB_ASSERT(arr_count <= upb_inttable_count(t));
+
+  {
+    /* Insert all elements into new, perfectly-sized table. */
+    size_t arr_size = max[size_lg2] + 1;  /* +1 so arr[max] will fit. */
+    size_t hash_count = upb_inttable_count(t) - arr_count;
+    size_t hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0;
+    int hashsize_lg2 = log2ceil(hash_size);
+
+    upb_inttable_sizedinit(&new_t, arr_size, hashsize_lg2, a);
+    upb_inttable_begin(&i, t);
+    for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+      uintptr_t k = upb_inttable_iter_key(&i);
+      upb_inttable_insert2(&new_t, k, upb_inttable_iter_value(&i), a);
+    }
+    UPB_ASSERT(new_t.array_size == arr_size);
+    UPB_ASSERT(new_t.t.size_lg2 == hashsize_lg2);
+  }
+  upb_inttable_uninit2(t, a);
+  *t = new_t;
+}
+
+/* Iteration. */
+
+static const upb_tabent *int_tabent(const upb_inttable_iter *i) {
+  UPB_ASSERT(!i->array_part);
+  return &i->t->t.entries[i->index];
+}
+
+static upb_tabval int_arrent(const upb_inttable_iter *i) {
+  UPB_ASSERT(i->array_part);
+  return i->t->array[i->index];
+}
+
+void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t) {
+  i->t = t;
+  i->index = -1;
+  i->array_part = true;
+  upb_inttable_next(i);
+}
+
+void upb_inttable_next(upb_inttable_iter *iter) {
+  const upb_inttable *t = iter->t;
+  if (iter->array_part) {
+    while (++iter->index < t->array_size) {
+      if (upb_arrhas(int_arrent(iter))) {
+        return;
+      }
+    }
+    iter->array_part = false;
+    iter->index = begin(&t->t);
+  } else {
+    iter->index = next(&t->t, iter->index);
+  }
+}
+
+bool upb_inttable_done(const upb_inttable_iter *i) {
+  if (!i->t) return true;
+  if (i->array_part) {
+    return i->index >= i->t->array_size ||
+           !upb_arrhas(int_arrent(i));
+  } else {
+    return i->index >= upb_table_size(&i->t->t) ||
+           upb_tabent_isempty(int_tabent(i));
+  }
+}
+
+uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) {
+  UPB_ASSERT(!upb_inttable_done(i));
+  return i->array_part ? i->index : int_tabent(i)->key;
+}
+
+upb_value upb_inttable_iter_value(const upb_inttable_iter *i) {
+  UPB_ASSERT(!upb_inttable_done(i));
+  return _upb_value_val(
+      i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val);
+}
+
+void upb_inttable_iter_setdone(upb_inttable_iter *i) {
+  i->t = NULL;
+  i->index = SIZE_MAX;
+  i->array_part = false;
+}
+
+bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
+                                          const upb_inttable_iter *i2) {
+  if (upb_inttable_done(i1) && upb_inttable_done(i2))
+    return true;
+  return i1->t == i2->t && i1->index == i2->index &&
+         i1->array_part == i2->array_part;
+}
+
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* upb_status *****************************************************************/
+
+void upb_status_clear(upb_status *status) {
+  if (!status) return;
+  status->ok = true;
+  status->msg[0] = '\0';
+}
+
+bool upb_ok(const upb_status *status) { return status->ok; }
+
+const char *upb_status_errmsg(const upb_status *status) { return status->msg; }
+
+void upb_status_seterrmsg(upb_status *status, const char *msg) {
+  if (!status) return;
+  status->ok = false;
+  strncpy(status->msg, msg, UPB_STATUS_MAX_MESSAGE - 1);
+  status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0';
+}
+
+void upb_status_seterrf(upb_status *status, const char *fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+  upb_status_vseterrf(status, fmt, args);
+  va_end(args);
+}
+
+void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) {
+  if (!status) return;
+  status->ok = false;
+  vsnprintf(status->msg, sizeof(status->msg), fmt, args);
+  status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0';
+}
+
+void upb_status_vappenderrf(upb_status *status, const char *fmt, va_list args) {
+  size_t len;
+  if (!status) return;
+  status->ok = false;
+  len = strlen(status->msg);
+  vsnprintf(status->msg + len, sizeof(status->msg) - len, fmt, args);
+  status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0';
+}
+
+/* upb_alloc ******************************************************************/
+
+static void *upb_global_allocfunc(upb_alloc *alloc, void *ptr, size_t oldsize,
+                                  size_t size) {
+  UPB_UNUSED(alloc);
+  UPB_UNUSED(oldsize);
+  if (size == 0) {
+    free(ptr);
+    return NULL;
+  } else {
+    return realloc(ptr, size);
+  }
+}
+
+upb_alloc upb_alloc_global = {&upb_global_allocfunc};
+
+/* upb_arena ******************************************************************/
+
+/* Be conservative and choose 16 in case anyone is using SSE. */
+
+struct mem_block {
+  struct mem_block *next;
+  uint32_t size;
+  uint32_t cleanups;
+  /* Data follows. */
+};
+
+typedef struct cleanup_ent {
+  upb_cleanup_func *cleanup;
+  void *ud;
+} cleanup_ent;
+
+static const size_t memblock_reserve = UPB_ALIGN_UP(sizeof(mem_block), 16);
+
+static upb_arena *arena_findroot(upb_arena *a) {
+  /* Path splitting keeps time complexity down, see:
+   *   https://en.wikipedia.org/wiki/Disjoint-set_data_structure */
+  while (a->parent != a) {
+    upb_arena *next = a->parent;
+    a->parent = next->parent;
+    a = next;
+  }
+  return a;
+}
+
+static void upb_arena_addblock(upb_arena *a, upb_arena *root, void *ptr,
+                               size_t size) {
+  mem_block *block = ptr;
+
+  /* The block is for arena |a|, but should appear in the freelist of |root|. */
+  block->next = root->freelist;
+  block->size = (uint32_t)size;
+  block->cleanups = 0;
+  root->freelist = block;
+  a->last_size = block->size;
+  if (!root->freelist_tail) root->freelist_tail = block;
+
+  a->head.ptr = UPB_PTR_AT(block, memblock_reserve, char);
+  a->head.end = UPB_PTR_AT(block, size, char);
+  a->cleanups = &block->cleanups;
+
+  UPB_POISON_MEMORY_REGION(a->head.ptr, a->head.end - a->head.ptr);
+}
+
+static bool upb_arena_allocblock(upb_arena *a, size_t size) {
+  upb_arena *root = arena_findroot(a);
+  size_t block_size = UPB_MAX(size, a->last_size * 2) + memblock_reserve;
+  mem_block *block = upb_malloc(root->block_alloc, block_size);
+
+  if (!block) return false;
+  upb_arena_addblock(a, root, block, block_size);
+  return true;
+}
+
+void *_upb_arena_slowmalloc(upb_arena *a, size_t size) {
+  if (!upb_arena_allocblock(a, size)) return NULL;  /* Out of memory. */
+  UPB_ASSERT(_upb_arenahas(a) >= size);
+  return upb_arena_malloc(a, size);
+}
+
+static void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize,
+                               size_t size) {
+  upb_arena *a = (upb_arena*)alloc;  /* upb_alloc is initial member. */
+  return upb_arena_realloc(a, ptr, oldsize, size);
+}
+
+/* Public Arena API ***********************************************************/
+
+upb_arena *arena_initslow(void *mem, size_t n, upb_alloc *alloc) {
+  const size_t first_block_overhead = sizeof(upb_arena) + memblock_reserve;
+  upb_arena *a;
+
+  /* We need to malloc the initial block. */
+  n = first_block_overhead + 256;
+  if (!alloc || !(mem = upb_malloc(alloc, n))) {
+    return NULL;
+  }
+
+  a = UPB_PTR_AT(mem, n - sizeof(*a), upb_arena);
+  n -= sizeof(*a);
+
+  a->head.alloc.func = &upb_arena_doalloc;
+  a->block_alloc = alloc;
+  a->parent = a;
+  a->refcount = 1;
+  a->freelist = NULL;
+  a->freelist_tail = NULL;
+
+  upb_arena_addblock(a, a, mem, n);
+
+  return a;
+}
+
+upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc) {
+  upb_arena *a;
+
+  /* Round block size down to alignof(*a) since we will allocate the arena
+   * itself at the end. */
+  n = UPB_ALIGN_DOWN(n, UPB_ALIGN_OF(upb_arena));
+
+  if (UPB_UNLIKELY(n < sizeof(upb_arena))) {
+    return arena_initslow(mem, n, alloc);
+  }
+
+  a = UPB_PTR_AT(mem, n - sizeof(*a), upb_arena);
+
+  a->head.alloc.func = &upb_arena_doalloc;
+  a->block_alloc = alloc;
+  a->parent = a;
+  a->refcount = 1;
+  a->last_size = UPB_MAX(128, n);
+  a->head.ptr = mem;
+  a->head.end = UPB_PTR_AT(mem, n - sizeof(*a), char);
+  a->freelist = NULL;
+  a->cleanups = NULL;
+
+  return a;
+}
+
+static void arena_dofree(upb_arena *a) {
+  mem_block *block = a->freelist;
+  UPB_ASSERT(a->parent == a);
+  UPB_ASSERT(a->refcount == 0);
+
+  while (block) {
+    /* Load first since we are deleting block. */
+    mem_block *next = block->next;
+
+    if (block->cleanups > 0) {
+      cleanup_ent *end = UPB_PTR_AT(block, block->size, void);
+      cleanup_ent *ptr = end - block->cleanups;
+
+      for (; ptr < end; ptr++) {
+        ptr->cleanup(ptr->ud);
+      }
+    }
+
+    upb_free(a->block_alloc, block);
+    block = next;
+  }
+}
+
+void upb_arena_free(upb_arena *a) {
+  a = arena_findroot(a);
+  if (--a->refcount == 0) arena_dofree(a);
+}
+
+bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func) {
+  cleanup_ent *ent;
+
+  if (!a->cleanups || _upb_arenahas(a) < sizeof(cleanup_ent)) {
+    if (!upb_arena_allocblock(a, 128)) return false;  /* Out of memory. */
+    UPB_ASSERT(_upb_arenahas(a) >= sizeof(cleanup_ent));
+  }
+
+  a->head.end -= sizeof(cleanup_ent);
+  ent = (cleanup_ent*)a->head.end;
+  (*a->cleanups)++;
+  UPB_UNPOISON_MEMORY_REGION(ent, sizeof(cleanup_ent));
+
+  ent->cleanup = func;
+  ent->ud = ud;
+
+  return true;
+}
+
+void upb_arena_fuse(upb_arena *a1, upb_arena *a2) {
+  upb_arena *r1 = arena_findroot(a1);
+  upb_arena *r2 = arena_findroot(a2);
+
+  if (r1 == r2) return;  /* Already fused. */
+
+  /* We want to join the smaller tree to the larger tree.
+   * So swap first if they are backwards. */
+  if (r1->refcount < r2->refcount) {
+    upb_arena *tmp = r1;
+    r1 = r2;
+    r2 = tmp;
+  }
+
+  /* r1 takes over r2's freelist and refcount. */
+  r1->refcount += r2->refcount;
+  if (r2->freelist_tail) {
+    UPB_ASSERT(r2->freelist_tail->next == NULL);
+    r2->freelist_tail->next = r1->freelist;
+    r1->freelist = r2->freelist;
+  }
+  r2->parent = r1;
+}
+// Fast decoder: ~3x the speed of decode.c, but x86-64 specific.
+// Also the table size grows by 2x.
+//
+// Could potentially be ported to ARM64 or other 64-bit archs that pass at
+// least six arguments in registers.
+//
+// The overall design is to create specialized functions for every possible
+// field type (eg. oneof boolean field with a 1 byte tag) and then dispatch
+// to the specialized function as quickly as possible.
+
+
+
+/* Must be last. */
+
+#if UPB_FASTTABLE
+
+// The standard set of arguments passed to each parsing function.
+// Thanks to x86-64 calling conventions, these will stay in registers.
+#define UPB_PARSE_PARAMS                                          \
+  upb_decstate *d, const char *ptr, upb_msg *msg, intptr_t table, \
+      uint64_t hasbits, uint64_t data
+
+#define UPB_PARSE_ARGS d, ptr, msg, table, hasbits, data
+
+#define RETURN_GENERIC(m)  \
+  /* fprintf(stderr, m); */ \
+  return fastdecode_generic(d, ptr, msg, table, hasbits, 0);
+
+typedef enum {
+  CARD_s = 0,  /* Singular (optional, non-repeated) */
+  CARD_o = 1,  /* Oneof */
+  CARD_r = 2,  /* Repeated */
+  CARD_p = 3   /* Packed Repeated */
+} upb_card;
+
+UPB_NOINLINE
+static const char *fastdecode_isdonefallback(upb_decstate *d, const char *ptr,
+                                             upb_msg *msg, intptr_t table,
+                                             uint64_t hasbits, int overrun) {
+  ptr = decode_isdonefallback_inl(d, ptr, overrun);
+  if (ptr == NULL) {
+    return fastdecode_err(d);
+  }
+  uint16_t tag = fastdecode_loadtag(ptr);
+  return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, tag);
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_dispatch(upb_decstate *d, const char *ptr,
+                                       upb_msg *msg, intptr_t table,
+                                       uint64_t hasbits) {
+  if (UPB_UNLIKELY(ptr >= d->limit_ptr)) {
+    int overrun = ptr - d->end;
+    if (UPB_LIKELY(overrun == d->limit)) {
+      // Parse is finished.
+      *(uint32_t*)msg |= hasbits;  // Sync hasbits.
+      return ptr;
+    } else {
+      return fastdecode_isdonefallback(d, ptr, msg, table, hasbits, overrun);
+    }
+  }
+
+  // Read two bytes of tag data (for a one-byte tag, the high byte is junk).
+  uint16_t tag = fastdecode_loadtag(ptr);
+  return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, tag);
+}
+
+UPB_FORCEINLINE
+static bool fastdecode_checktag(uint64_t data, int tagbytes) {
+  if (tagbytes == 1) {
+    return (data & 0xff) == 0;
+  } else {
+    return (data & 0xffff) == 0;
+  }
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_longsize(const char *ptr, int *size) {
+  int i;
+  UPB_ASSERT(*size & 0x80);
+  *size &= 0xff;
+  for (i = 0; i < 3; i++) {
+    ptr++;
+    size_t byte = (uint8_t)ptr[-1];
+    *size += (byte - 1) << (7 + 7 * i);
+    if (UPB_LIKELY((byte & 0x80) == 0)) return ptr;
+  }
+  ptr++;
+  size_t byte = (uint8_t)ptr[-1];
+  // len is limited by 2gb not 4gb, hence 8 and not 16 as normally expected
+  // for a 32 bit varint.
+  if (UPB_UNLIKELY(byte >= 8)) return NULL;
+  *size += (byte - 1) << 28;
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static bool fastdecode_boundscheck(const char *ptr, size_t len,
+                                   const char *end) {
+  uintptr_t uptr = (uintptr_t)ptr;
+  uintptr_t uend = (uintptr_t)end + 16;
+  uintptr_t res = uptr + len;
+  return res < uptr || res > uend;
+}
+
+UPB_FORCEINLINE
+static bool fastdecode_boundscheck2(const char *ptr, size_t len,
+                                    const char *end) {
+  // This is one extra branch compared to the more normal:
+  //   return (size_t)(end - ptr) < size;
+  // However it is one less computation if we are just about to use "ptr + len":
+  //   https://godbolt.org/z/35YGPz
+  // In microbenchmarks this shows an overall 4% improvement.
+  uintptr_t uptr = (uintptr_t)ptr;
+  uintptr_t uend = (uintptr_t)end;
+  uintptr_t res = uptr + len;
+  return res < uptr || res > uend;
+}
+
+typedef const char *fastdecode_delimfunc(upb_decstate *d, const char *ptr,
+                                         void *ctx);
+
+UPB_FORCEINLINE
+static const char *fastdecode_delimited(upb_decstate *d, const char *ptr,
+                                        fastdecode_delimfunc *func, void *ctx) {
+  ptr++;
+  int len = (int8_t)ptr[-1];
+  if (fastdecode_boundscheck2(ptr, len, d->limit_ptr)) {
+    // Slow case: Sub-message is >=128 bytes and/or exceeds the current buffer.
+    // If it exceeds the buffer limit, limit/limit_ptr will change during
+    // sub-message parsing, so we need to preserve delta, not limit.
+    if (UPB_UNLIKELY(len & 0x80)) {
+      // Size varint >1 byte (length >= 128).
+      ptr = fastdecode_longsize(ptr, &len);
+      if (!ptr) {
+        // Corrupt wire format: size exceeded INT_MAX.
+        return NULL;
+      }
+    }
+    if (ptr - d->end + (int)len > d->limit) {
+      // Corrupt wire format: invalid limit.
+      return NULL;
+    }
+    int delta = decode_pushlimit(d, ptr, len);
+    ptr = func(d, ptr, ctx);
+    decode_poplimit(d, ptr, delta);
+  } else {
+    // Fast case: Sub-message is <128 bytes and fits in the current buffer.
+    // This means we can preserve limit/limit_ptr verbatim.
+    const char *saved_limit_ptr = d->limit_ptr;
+    int saved_limit = d->limit;
+    d->limit_ptr = ptr + len;
+    d->limit = d->limit_ptr - d->end;
+    UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit));
+    ptr = func(d, ptr, ctx);
+    d->limit_ptr = saved_limit_ptr;
+    d->limit = saved_limit;
+    UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit));
+  }
+  return ptr;
+}
+
+/* singular, oneof, repeated field handling ***********************************/
+
+typedef struct {
+  upb_array *arr;
+  void *end;
+} fastdecode_arr;
+
+typedef enum {
+  FD_NEXT_ATLIMIT,
+  FD_NEXT_SAMEFIELD,
+  FD_NEXT_OTHERFIELD
+} fastdecode_next;
+
+typedef struct {
+  void *dst;
+  fastdecode_next next;
+  uint32_t tag;
+} fastdecode_nextret;
+
+UPB_FORCEINLINE
+static void *fastdecode_resizearr(upb_decstate *d, void *dst,
+                                  fastdecode_arr *farr, int valbytes) {
+  if (UPB_UNLIKELY(dst == farr->end)) {
+    size_t old_size = farr->arr->size;
+    size_t old_bytes = old_size * valbytes;
+    size_t new_size = old_size * 2;
+    size_t new_bytes = new_size * valbytes;
+    char *old_ptr = _upb_array_ptr(farr->arr);
+    char *new_ptr = upb_arena_realloc(&d->arena, old_ptr, old_bytes, new_bytes);
+    uint8_t elem_size_lg2 = __builtin_ctz(valbytes);
+    farr->arr->size = new_size;
+    farr->arr->data = _upb_array_tagptr(new_ptr, elem_size_lg2);
+    dst = (void*)(new_ptr + (old_size * valbytes));
+    farr->end = (void*)(new_ptr + (new_size * valbytes));
+  }
+  return dst;
+}
+
+UPB_FORCEINLINE
+static bool fastdecode_tagmatch(uint32_t tag, uint64_t data, int tagbytes) {
+  if (tagbytes == 1) {
+    return (uint8_t)tag == (uint8_t)data;
+  } else {
+    return (uint16_t)tag == (uint16_t)data;
+  }
+}
+
+UPB_FORCEINLINE
+static void fastdecode_commitarr(void *dst, fastdecode_arr *farr,
+                                 int valbytes) {
+  farr->arr->len =
+      (size_t)((char *)dst - (char *)_upb_array_ptr(farr->arr)) / valbytes;
+}
+
+UPB_FORCEINLINE
+static fastdecode_nextret fastdecode_nextrepeated(upb_decstate *d, void *dst,
+                                                  const char **ptr,
+                                                  fastdecode_arr *farr,
+                                                  uint64_t data, int tagbytes,
+                                                  int valbytes) {
+  fastdecode_nextret ret;
+  dst = (char *)dst + valbytes;
+
+  if (UPB_LIKELY(!decode_isdone(d, ptr))) {
+    ret.tag = fastdecode_loadtag(*ptr);
+    if (fastdecode_tagmatch(ret.tag, data, tagbytes)) {
+      ret.next = FD_NEXT_SAMEFIELD;
+    } else {
+      fastdecode_commitarr(dst, farr, valbytes);
+      ret.next = FD_NEXT_OTHERFIELD;
+    }
+  } else {
+    fastdecode_commitarr(dst, farr, valbytes);
+    ret.next = FD_NEXT_ATLIMIT;
+  }
+
+  ret.dst = dst;
+  return ret;
+}
+
+UPB_FORCEINLINE
+static void *fastdecode_fieldmem(upb_msg *msg, uint64_t data) {
+  size_t ofs = data >> 48;
+  return (char *)msg + ofs;
+}
+
+UPB_FORCEINLINE
+static void *fastdecode_getfield(upb_decstate *d, const char *ptr, upb_msg *msg,
+                                 uint64_t *data, uint64_t *hasbits,
+                                 fastdecode_arr *farr, int valbytes,
+                                 upb_card card) {
+  switch (card) {
+    case CARD_s: {
+      uint8_t hasbit_index = *data >> 24;
+      // Set hasbit and return pointer to scalar field.
+      *hasbits |= 1ull << hasbit_index;
+      return fastdecode_fieldmem(msg, *data);
+    }
+    case CARD_o: {
+      uint16_t case_ofs = *data >> 32;
+      uint32_t *oneof_case = UPB_PTR_AT(msg, case_ofs, uint32_t);
+      uint8_t field_number = *data >> 24;
+      *oneof_case = field_number;
+      return fastdecode_fieldmem(msg, *data);
+    }
+    case CARD_r: {
+      // Get pointer to upb_array and allocate/expand if necessary.
+      uint8_t elem_size_lg2 = __builtin_ctz(valbytes);
+      upb_array **arr_p = fastdecode_fieldmem(msg, *data);
+      char *begin;
+      *(uint32_t*)msg |= *hasbits;
+      *hasbits = 0;
+      if (UPB_LIKELY(!*arr_p)) {
+        farr->arr = _upb_array_new(&d->arena, 8, elem_size_lg2);
+        *arr_p = farr->arr;
+      } else {
+        farr->arr = *arr_p;
+      }
+      begin = _upb_array_ptr(farr->arr);
+      farr->end = begin + (farr->arr->size * valbytes);
+      *data = fastdecode_loadtag(ptr);
+      return begin + (farr->arr->len * valbytes);
+    }
+    default:
+      UPB_UNREACHABLE();
+  }
+}
+
+UPB_FORCEINLINE
+static bool fastdecode_flippacked(uint64_t *data, int tagbytes) {
+  *data ^= (0x2 ^ 0x0);  // Patch data to match packed wiretype.
+  return fastdecode_checktag(*data, tagbytes);
+}
+
+/* varint fields **************************************************************/
+
+UPB_FORCEINLINE
+static uint64_t fastdecode_munge(uint64_t val, int valbytes, bool zigzag) {
+  if (valbytes == 1) {
+    return val != 0;
+  } else if (zigzag) {
+    if (valbytes == 4) {
+      uint32_t n = val;
+      return (n >> 1) ^ -(int32_t)(n & 1);
+    } else if (valbytes == 8) {
+      return (val >> 1) ^ -(int64_t)(val & 1);
+    }
+    UPB_UNREACHABLE();
+  }
+  return val;
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_varint64(const char *ptr, uint64_t *val) {
+  ptr++;
+  *val = (uint8_t)ptr[-1];
+  if (UPB_UNLIKELY(*val & 0x80)) {
+    int i;
+    for (i = 0; i < 8; i++) {
+      ptr++;
+      uint64_t byte = (uint8_t)ptr[-1];
+      *val += (byte - 1) << (7 + 7 * i);
+      if (UPB_LIKELY((byte & 0x80) == 0)) goto done;
+    }
+    ptr++;
+    uint64_t byte = (uint8_t)ptr[-1];
+    if (byte > 1) {
+      return NULL;
+    }
+    *val += (byte - 1) << 63;
+  }
+done:
+  UPB_ASSUME(ptr != NULL);
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_unpackedvarint(UPB_PARSE_PARAMS, int tagbytes,
+                                             int valbytes, upb_card card,
+                                             bool zigzag,
+                                             _upb_field_parser *packed) {
+  uint64_t val;
+  void *dst;
+  fastdecode_arr farr;
+
+  if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {
+    if (card == CARD_r && fastdecode_flippacked(&data, tagbytes)) {
+      return packed(UPB_PARSE_ARGS);
+    }
+    RETURN_GENERIC("varint field tag mismatch\n");
+  }
+
+  dst =
+      fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes, card);
+  if (card == CARD_r) {
+    if (UPB_UNLIKELY(!dst)) {
+      RETURN_GENERIC("need array resize\n");
+    }
+  }
+
+again:
+  if (card == CARD_r) {
+    dst = fastdecode_resizearr(d, dst, &farr, valbytes);
+  }
+
+  ptr += tagbytes;
+  ptr = fastdecode_varint64(ptr, &val);
+  if (ptr == NULL) return fastdecode_err(d);
+  val = fastdecode_munge(val, valbytes, zigzag);
+  memcpy(dst, &val, valbytes);
+
+  if (card == CARD_r) {
+    fastdecode_nextret ret =
+        fastdecode_nextrepeated(d, dst, &ptr, &farr, data, tagbytes, valbytes);
+    switch (ret.next) {
+      case FD_NEXT_SAMEFIELD:
+        dst = ret.dst;
+        goto again;
+      case FD_NEXT_OTHERFIELD:
+        return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag);
+      case FD_NEXT_ATLIMIT:
+        return ptr;
+    }
+  }
+
+  return fastdecode_dispatch(d, ptr, msg, table, hasbits);
+}
+
+typedef struct {
+  uint8_t valbytes;
+  bool zigzag;
+  void *dst;
+  fastdecode_arr farr;
+} fastdecode_varintdata;
+
+UPB_FORCEINLINE
+static const char *fastdecode_topackedvarint(upb_decstate *d, const char *ptr,
+                                             void *ctx) {
+  fastdecode_varintdata *data = ctx;
+  void *dst = data->dst;
+  uint64_t val;
+
+  while (!decode_isdone(d, &ptr)) {
+    dst = fastdecode_resizearr(d, dst, &data->farr, data->valbytes);
+    ptr = fastdecode_varint64(ptr, &val);
+    if (ptr == NULL) return NULL;
+    val = fastdecode_munge(val, data->valbytes, data->zigzag);
+    memcpy(dst, &val, data->valbytes);
+    dst = (char *)dst + data->valbytes;
+  }
+
+  fastdecode_commitarr(dst, &data->farr, data->valbytes);
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_packedvarint(UPB_PARSE_PARAMS, int tagbytes,
+                                           int valbytes, bool zigzag,
+                                           _upb_field_parser *unpacked) {
+  fastdecode_varintdata ctx = {valbytes, zigzag};
+
+  if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {
+    if (fastdecode_flippacked(&data, tagbytes)) {
+      return unpacked(UPB_PARSE_ARGS);
+    } else {
+      RETURN_GENERIC("varint field tag mismatch\n");
+    }
+  }
+
+  ctx.dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &ctx.farr,
+                                valbytes, CARD_r);
+  if (UPB_UNLIKELY(!ctx.dst)) {
+    RETURN_GENERIC("need array resize\n");
+  }
+
+  ptr += tagbytes;
+  ptr = fastdecode_delimited(d, ptr, &fastdecode_topackedvarint, &ctx);
+
+  if (UPB_UNLIKELY(ptr == NULL)) {
+    return fastdecode_err(d);
+  }
+
+  return fastdecode_dispatch(d, ptr, msg, table, hasbits);
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_varint(UPB_PARSE_PARAMS, int tagbytes,
+                                     int valbytes, upb_card card, bool zigzag,
+                                     _upb_field_parser *unpacked,
+                                     _upb_field_parser *packed) {
+  if (card == CARD_p) {
+    return fastdecode_packedvarint(UPB_PARSE_ARGS, tagbytes, valbytes, zigzag,
+                                   unpacked);
+  } else {
+    return fastdecode_unpackedvarint(UPB_PARSE_ARGS, tagbytes, valbytes, card,
+                                     zigzag, packed);
+  }
+}
+
+#define z_ZZ true
+#define b_ZZ false
+#define v_ZZ false
+
+/* Generate all combinations:
+ * {s,o,r,p} x {b1,v4,z4,v8,z8} x {1bt,2bt} */
+
+#define F(card, type, valbytes, tagbytes)                                      \
+  UPB_NOINLINE                                                                 \
+  const char *upb_p##card##type##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
+    return fastdecode_varint(UPB_PARSE_ARGS, tagbytes, valbytes, CARD_##card,  \
+                             type##_ZZ,                                        \
+                             &upb_pr##type##valbytes##_##tagbytes##bt,         \
+                             &upb_pp##type##valbytes##_##tagbytes##bt);        \
+  }
+
+#define TYPES(card, tagbytes) \
+  F(card, b, 1, tagbytes)     \
+  F(card, v, 4, tagbytes)     \
+  F(card, v, 8, tagbytes)     \
+  F(card, z, 4, tagbytes)     \
+  F(card, z, 8, tagbytes)
+
+#define TAGBYTES(card) \
+  TYPES(card, 1)       \
+  TYPES(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+TAGBYTES(p)
+
+#undef z_ZZ
+#undef b_ZZ
+#undef v_ZZ
+#undef o_ONEOF
+#undef s_ONEOF
+#undef r_ONEOF
+#undef F
+#undef TYPES
+#undef TAGBYTES
+
+
+/* fixed fields ***************************************************************/
+
+UPB_FORCEINLINE
+static const char *fastdecode_unpackedfixed(UPB_PARSE_PARAMS, int tagbytes,
+                                            int valbytes, upb_card card,
+                                            _upb_field_parser *packed) {
+  void *dst;
+  fastdecode_arr farr;
+
+  if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {
+    if (card == CARD_r && fastdecode_flippacked(&data, tagbytes)) {
+      return packed(UPB_PARSE_ARGS);
+    }
+    RETURN_GENERIC("fixed field tag mismatch\n");
+  }
+
+  dst =
+      fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes, card);
+  if (card == CARD_r) {
+    if (UPB_UNLIKELY(!dst)) {
+      RETURN_GENERIC("couldn't allocate array in arena\n");
+    }
+  }
+
+
+again:
+  if (card == CARD_r) {
+    dst = fastdecode_resizearr(d, dst, &farr, valbytes);
+  }
+
+  ptr += tagbytes;
+  memcpy(dst, ptr, valbytes);
+  ptr += valbytes;
+
+  if (card == CARD_r) {
+    fastdecode_nextret ret =
+        fastdecode_nextrepeated(d, dst, &ptr, &farr, data, tagbytes, valbytes);
+    switch (ret.next) {
+      case FD_NEXT_SAMEFIELD:
+        dst = ret.dst;
+        goto again;
+      case FD_NEXT_OTHERFIELD:
+        return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag);
+      case FD_NEXT_ATLIMIT:
+        return ptr;
+    }
+  }
+
+  return fastdecode_dispatch(d, ptr, msg, table, hasbits);
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_packedfixed(UPB_PARSE_PARAMS, int tagbytes,
+                                          int valbytes,
+                                          _upb_field_parser *unpacked) {
+  if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {
+    if (fastdecode_flippacked(&data, tagbytes)) {
+      return unpacked(UPB_PARSE_ARGS);
+    } else {
+      RETURN_GENERIC("varint field tag mismatch\n");
+    }
+  }
+
+  ptr += tagbytes;
+  int size = (uint8_t)ptr[0];
+  ptr++;
+  if (size & 0x80) {
+    ptr = fastdecode_longsize(ptr, &size);
+  }
+
+  if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr)) ||
+      (size % valbytes) != 0) {
+    return fastdecode_err(d);
+  }
+
+  upb_array **arr_p = fastdecode_fieldmem(msg, data);
+  upb_array *arr = *arr_p;
+  uint8_t elem_size_lg2 = __builtin_ctz(valbytes);
+  int elems = size / valbytes;
+
+  if (UPB_LIKELY(!arr)) {
+    *arr_p = arr = _upb_array_new(&d->arena, elems, elem_size_lg2);
+    if (!arr) {
+      return fastdecode_err(d);
+    }
+  } else {
+    _upb_array_resize(arr, elems, &d->arena);
+  }
+
+  char *dst = _upb_array_ptr(arr);
+  memcpy(dst, ptr, size);
+  arr->len = elems;
+
+  return fastdecode_dispatch(d, ptr + size, msg, table, hasbits);
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_fixed(UPB_PARSE_PARAMS, int tagbytes,
+                                    int valbytes, upb_card card,
+                                    _upb_field_parser *unpacked,
+                                    _upb_field_parser *packed) {
+  if (card == CARD_p) {
+    return fastdecode_packedfixed(UPB_PARSE_ARGS, tagbytes, valbytes, unpacked);
+  } else {
+    return fastdecode_unpackedfixed(UPB_PARSE_ARGS, tagbytes, valbytes, card,
+                                    packed);
+  }
+}
+
+/* Generate all combinations:
+ * {s,o,r,p} x {f4,f8} x {1bt,2bt} */
+
+#define F(card, valbytes, tagbytes)                                          \
+  UPB_NOINLINE                                                               \
+  const char *upb_p##card##f##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS) {  \
+    return fastdecode_fixed(UPB_PARSE_ARGS, tagbytes, valbytes, CARD_##card, \
+                            &upb_ppf##valbytes##_##tagbytes##bt,             \
+                            &upb_prf##valbytes##_##tagbytes##bt);            \
+  }
+
+#define TYPES(card, tagbytes) \
+  F(card, 4, tagbytes)        \
+  F(card, 8, tagbytes)
+
+#define TAGBYTES(card) \
+  TYPES(card, 1)       \
+  TYPES(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+TAGBYTES(p)
+
+#undef F
+#undef TYPES
+#undef TAGBYTES
+
+/* string fields **************************************************************/
+
+typedef const char *fastdecode_copystr_func(struct upb_decstate *d,
+                                            const char *ptr, upb_msg *msg,
+                                            const upb_msglayout *table,
+                                            uint64_t hasbits, upb_strview *dst);
+
+UPB_NOINLINE
+static const char *fastdecode_verifyutf8(upb_decstate *d, const char *ptr,
+                                         upb_msg *msg, intptr_t table,
+                                         uint64_t hasbits, upb_strview *dst) {
+  if (!decode_verifyutf8_inl(dst->data, dst->size)) {
+    return fastdecode_err(d);
+  }
+  return fastdecode_dispatch(d, ptr, msg, table, hasbits);
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_longstring(struct upb_decstate *d,
+                                         const char *ptr, upb_msg *msg,
+                                         intptr_t table, uint64_t hasbits,
+                                         upb_strview *dst,
+                                         bool validate_utf8) {
+  int size = (uint8_t)ptr[0];  // Could plumb through hasbits.
+  ptr++;
+  if (size & 0x80) {
+    ptr = fastdecode_longsize(ptr, &size);
+  }
+
+  if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr))) {
+    dst->size = 0;
+    return fastdecode_err(d);
+  }
+
+  if (d->alias) {
+    dst->data = ptr;
+    dst->size = size;
+  } else {
+    char *data = upb_arena_malloc(&d->arena, size);
+    if (!data) {
+      return fastdecode_err(d);
+    }
+    memcpy(data, ptr, size);
+    dst->data = data;
+    dst->size = size;
+  }
+
+  if (validate_utf8) {
+    return fastdecode_verifyutf8(d, ptr + size, msg, table, hasbits, dst);
+  } else {
+    return fastdecode_dispatch(d, ptr + size, msg, table, hasbits);
+  }
+}
+
+UPB_NOINLINE
+static const char *fastdecode_longstring_utf8(struct upb_decstate *d,
+                                         const char *ptr, upb_msg *msg,
+                                         intptr_t table, uint64_t hasbits,
+                                         upb_strview *dst) {
+  return fastdecode_longstring(d, ptr, msg, table, hasbits, dst, true);
+}
+
+UPB_NOINLINE
+static const char *fastdecode_longstring_noutf8(struct upb_decstate *d,
+                                                const char *ptr, upb_msg *msg,
+                                                intptr_t table,
+                                                uint64_t hasbits,
+                                                upb_strview *dst) {
+  return fastdecode_longstring(d, ptr, msg, table, hasbits, dst, false);
+}
+
+UPB_FORCEINLINE
+static void fastdecode_docopy(upb_decstate *d, const char *ptr, uint32_t size,
+                              int copy, char *data, upb_strview *dst) {
+  d->arena.head.ptr += copy;
+  dst->data = data;
+  UPB_UNPOISON_MEMORY_REGION(data, copy);
+  memcpy(data, ptr, copy);
+  UPB_POISON_MEMORY_REGION(data + size, copy - size);
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_copystring(UPB_PARSE_PARAMS, int tagbytes,
+                                         upb_card card, bool validate_utf8) {
+  upb_strview *dst;
+  fastdecode_arr farr;
+  int64_t size;
+  size_t arena_has;
+  size_t common_has;
+  char *buf;
+
+  UPB_ASSERT(!d->alias);
+  UPB_ASSERT(fastdecode_checktag(data, tagbytes));
+
+  dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,
+                            sizeof(upb_strview), card);
+
+again:
+  if (card == CARD_r) {
+    dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_strview));
+  }
+
+  size = (uint8_t)ptr[tagbytes];
+  ptr += tagbytes + 1;
+  dst->size = size;
+
+  buf = d->arena.head.ptr;
+  arena_has = _upb_arenahas(&d->arena);
+  common_has = UPB_MIN(arena_has, (d->end - ptr) + 16);
+
+  if (UPB_LIKELY(size <= 15 - tagbytes)) {
+    if (arena_has < 16) goto longstr;
+    d->arena.head.ptr += 16;
+    memcpy(buf, ptr - tagbytes - 1, 16);
+    dst->data = buf + tagbytes + 1;
+  } else if (UPB_LIKELY(size <= 32)) {
+    if (UPB_UNLIKELY(common_has < 32)) goto longstr;
+    fastdecode_docopy(d, ptr, size, 32, buf, dst);
+  } else if (UPB_LIKELY(size <= 64)) {
+    if (UPB_UNLIKELY(common_has < 64)) goto longstr;
+    fastdecode_docopy(d, ptr, size, 64, buf, dst);
+  } else if (UPB_LIKELY(size < 128)) {
+    if (UPB_UNLIKELY(common_has < 128)) goto longstr;
+    fastdecode_docopy(d, ptr, size, 128, buf, dst);
+  } else {
+    goto longstr;
+  }
+
+  ptr += size;
+
+  if (card == CARD_r) {
+    if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) {
+      return fastdecode_err(d);
+    }
+    fastdecode_nextret ret = fastdecode_nextrepeated(
+        d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_strview));
+    switch (ret.next) {
+      case FD_NEXT_SAMEFIELD:
+        dst = ret.dst;
+        goto again;
+      case FD_NEXT_OTHERFIELD:
+        return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag);
+      case FD_NEXT_ATLIMIT:
+        return ptr;
+    }
+  }
+
+  if (card != CARD_r && validate_utf8) {
+    return fastdecode_verifyutf8(d, ptr, msg, table, hasbits, dst);
+  }
+
+  return fastdecode_dispatch(d, ptr, msg, table, hasbits);
+
+longstr:
+  ptr--;
+  if (validate_utf8) {
+    return fastdecode_longstring_utf8(d, ptr, msg, table, hasbits, dst);
+  } else {
+    return fastdecode_longstring_noutf8(d, ptr, msg, table, hasbits, dst);
+  }
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_string(UPB_PARSE_PARAMS, int tagbytes,
+                                     upb_card card, _upb_field_parser *copyfunc,
+                                     bool validate_utf8) {
+  upb_strview *dst;
+  fastdecode_arr farr;
+  int64_t size;
+
+  if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {
+    RETURN_GENERIC("string field tag mismatch\n");
+  }
+
+  if (UPB_UNLIKELY(!d->alias)) {
+    return copyfunc(UPB_PARSE_ARGS);
+  }
+
+  dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,
+                            sizeof(upb_strview), card);
+
+again:
+  if (card == CARD_r) {
+    dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_strview));
+  }
+
+  size = (int8_t)ptr[tagbytes];
+  ptr += tagbytes + 1;
+  dst->data = ptr;
+  dst->size = size;
+
+  if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->end))) {
+    ptr--;
+    if (validate_utf8) {
+      return fastdecode_longstring_utf8(d, ptr, msg, table, hasbits, dst);
+    } else {
+      return fastdecode_longstring_noutf8(d, ptr, msg, table, hasbits, dst);
+    }
+  }
+
+  ptr += size;
+
+  if (card == CARD_r) {
+    if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) {
+      return fastdecode_err(d);
+    }
+    fastdecode_nextret ret = fastdecode_nextrepeated(
+        d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_strview));
+    switch (ret.next) {
+      case FD_NEXT_SAMEFIELD:
+        dst = ret.dst;
+        if (UPB_UNLIKELY(!d->alias)) {
+          // Buffer flipped and we can't alias any more. Bounce to copyfunc(),
+          // but via dispatch since we need to reload table data also.
+          fastdecode_commitarr(dst, &farr, sizeof(upb_strview));
+          return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag);
+        }
+        goto again;
+      case FD_NEXT_OTHERFIELD:
+        return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag);
+      case FD_NEXT_ATLIMIT:
+        return ptr;
+    }
+  }
+
+  if (card != CARD_r && validate_utf8) {
+    return fastdecode_verifyutf8(d, ptr, msg, table, hasbits, dst);
+  }
+
+  return fastdecode_dispatch(d, ptr, msg, table, hasbits);
+}
+
+/* Generate all combinations:
+ * {p,c} x {s,o,r} x {s, b} x {1bt,2bt} */
+
+#define s_VALIDATE true
+#define b_VALIDATE false
+
+#define F(card, tagbytes, type)                                         \
+  UPB_NOINLINE                                                          \
+  const char *upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) {    \
+    return fastdecode_copystring(UPB_PARSE_ARGS, tagbytes, CARD_##card, \
+                                 type##_VALIDATE);                      \
+  }                                                                     \
+  const char *upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) {    \
+    return fastdecode_string(UPB_PARSE_ARGS, tagbytes, CARD_##card,     \
+                             &upb_c##card##type##_##tagbytes##bt,       \
+                             type##_VALIDATE);                          \
+  }
+
+#define UTF8(card, tagbytes) \
+  F(card, tagbytes, s)       \
+  F(card, tagbytes, b)
+
+#define TAGBYTES(card) \
+  UTF8(card, 1)        \
+  UTF8(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+
+#undef s_VALIDATE
+#undef b_VALIDATE
+#undef F
+#undef TAGBYTES
+
+/* message fields *************************************************************/
+
+UPB_INLINE
+upb_msg *decode_newmsg_ceil(upb_decstate *d, const upb_msglayout *l,
+                            int msg_ceil_bytes) {
+  size_t size = l->size + sizeof(upb_msg_internal);
+  char *msg_data;
+  if (UPB_LIKELY(msg_ceil_bytes > 0 &&
+                 _upb_arenahas(&d->arena) >= msg_ceil_bytes)) {
+    UPB_ASSERT(size <= (size_t)msg_ceil_bytes);
+    msg_data = d->arena.head.ptr;
+    d->arena.head.ptr += size;
+    UPB_UNPOISON_MEMORY_REGION(msg_data, msg_ceil_bytes);
+    memset(msg_data, 0, msg_ceil_bytes);
+    UPB_POISON_MEMORY_REGION(msg_data + size, msg_ceil_bytes - size);
+  } else {
+    msg_data = (char*)upb_arena_malloc(&d->arena, size);
+    memset(msg_data, 0, size);
+  }
+  return msg_data + sizeof(upb_msg_internal);
+}
+
+typedef struct {
+  intptr_t table;
+  upb_msg *msg;
+} fastdecode_submsgdata;
+
+UPB_FORCEINLINE
+static const char *fastdecode_tosubmsg(upb_decstate *d, const char *ptr,
+                                       void *ctx) {
+  fastdecode_submsgdata *submsg = ctx;
+  ptr = fastdecode_dispatch(d, ptr, submsg->msg, submsg->table, 0);
+  UPB_ASSUME(ptr != NULL);
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static const char *fastdecode_submsg(UPB_PARSE_PARAMS, int tagbytes,
+                                     int msg_ceil_bytes, upb_card card) {
+
+  if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {
+    RETURN_GENERIC("submessage field tag mismatch\n");
+  }
+
+  if (--d->depth == 0) return fastdecode_err(d);
+
+  upb_msg **dst;
+  uint32_t submsg_idx = (data >> 16) & 0xff;
+  const upb_msglayout *tablep = decode_totablep(table);
+  const upb_msglayout *subtablep = tablep->submsgs[submsg_idx];
+  fastdecode_submsgdata submsg = {decode_totable(subtablep)};
+  fastdecode_arr farr;
+
+  if (subtablep->table_mask == (uint8_t)-1) {
+    RETURN_GENERIC("submessage doesn't have fast tables.");
+  }
+
+  dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,
+                            sizeof(upb_msg *), card);
+
+  if (card == CARD_s) {
+    *(uint32_t*)msg |= hasbits;
+    hasbits = 0;
+  }
+
+again:
+  if (card == CARD_r) {
+    dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_msg*));
+  }
+
+  submsg.msg = *dst;
+
+  if (card == CARD_r || UPB_LIKELY(!submsg.msg)) {
+    *dst = submsg.msg = decode_newmsg_ceil(d, subtablep, msg_ceil_bytes);
+  }
+
+  ptr += tagbytes;
+  ptr = fastdecode_delimited(d, ptr, fastdecode_tosubmsg, &submsg);
+
+  if (UPB_UNLIKELY(ptr == NULL || d->end_group != DECODE_NOGROUP)) {
+    return fastdecode_err(d);
+  }
+
+  if (card == CARD_r) {
+    fastdecode_nextret ret = fastdecode_nextrepeated(
+        d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_msg *));
+    switch (ret.next) {
+      case FD_NEXT_SAMEFIELD:
+        dst = ret.dst;
+        goto again;
+      case FD_NEXT_OTHERFIELD:
+        d->depth++;
+        return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag);
+      case FD_NEXT_ATLIMIT:
+        d->depth++;
+        return ptr;
+    }
+  }
+
+  d->depth++;
+  return fastdecode_dispatch(d, ptr, msg, table, hasbits);
+}
+
+#define F(card, tagbytes, size_ceil, ceil_arg)                                 \
+  const char *upb_p##card##m_##tagbytes##bt_max##size_ceil##b(                 \
+      UPB_PARSE_PARAMS) {                                                      \
+    return fastdecode_submsg(UPB_PARSE_ARGS, tagbytes, ceil_arg, CARD_##card); \
+  }
+
+#define SIZES(card, tagbytes) \
+  F(card, tagbytes, 64, 64) \
+  F(card, tagbytes, 128, 128) \
+  F(card, tagbytes, 192, 192) \
+  F(card, tagbytes, 256, 256) \
+  F(card, tagbytes, max, -1)
+
+#define TAGBYTES(card) \
+  SIZES(card, 1) \
+  SIZES(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+
+#undef TAGBYTES
+#undef SIZES
+#undef F
+
+#endif  /* UPB_FASTTABLE */
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     google/protobuf/descriptor.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#include <stddef.h>
+
+
+static const upb_msglayout *const google_protobuf_FileDescriptorSet_submsgs[1] = {
+  &google_protobuf_FileDescriptorProto_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_FileDescriptorSet__fields[1] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_FileDescriptorSet_msginit = {
+  &google_protobuf_FileDescriptorSet_submsgs[0],
+  &google_protobuf_FileDescriptorSet__fields[0],
+  UPB_SIZE(8, 8), 1, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_FileDescriptorProto_submsgs[6] = {
+  &google_protobuf_DescriptorProto_msginit,
+  &google_protobuf_EnumDescriptorProto_msginit,
+  &google_protobuf_FieldDescriptorProto_msginit,
+  &google_protobuf_FileOptions_msginit,
+  &google_protobuf_ServiceDescriptorProto_msginit,
+  &google_protobuf_SourceCodeInfo_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_FileDescriptorProto__fields[12] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(12, 24), 2, 0, 12, 1},
+  {3, UPB_SIZE(36, 72), 0, 0, 12, 3},
+  {4, UPB_SIZE(40, 80), 0, 0, 11, 3},
+  {5, UPB_SIZE(44, 88), 0, 1, 11, 3},
+  {6, UPB_SIZE(48, 96), 0, 4, 11, 3},
+  {7, UPB_SIZE(52, 104), 0, 2, 11, 3},
+  {8, UPB_SIZE(28, 56), 3, 3, 11, 1},
+  {9, UPB_SIZE(32, 64), 4, 5, 11, 1},
+  {10, UPB_SIZE(56, 112), 0, 0, 5, 3},
+  {11, UPB_SIZE(60, 120), 0, 0, 5, 3},
+  {12, UPB_SIZE(20, 40), 5, 0, 12, 1},
+};
+
+const upb_msglayout google_protobuf_FileDescriptorProto_msginit = {
+  &google_protobuf_FileDescriptorProto_submsgs[0],
+  &google_protobuf_FileDescriptorProto__fields[0],
+  UPB_SIZE(64, 128), 12, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_DescriptorProto_submsgs[7] = {
+  &google_protobuf_DescriptorProto_msginit,
+  &google_protobuf_DescriptorProto_ExtensionRange_msginit,
+  &google_protobuf_DescriptorProto_ReservedRange_msginit,
+  &google_protobuf_EnumDescriptorProto_msginit,
+  &google_protobuf_FieldDescriptorProto_msginit,
+  &google_protobuf_MessageOptions_msginit,
+  &google_protobuf_OneofDescriptorProto_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_DescriptorProto__fields[10] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(16, 32), 0, 4, 11, 3},
+  {3, UPB_SIZE(20, 40), 0, 0, 11, 3},
+  {4, UPB_SIZE(24, 48), 0, 3, 11, 3},
+  {5, UPB_SIZE(28, 56), 0, 1, 11, 3},
+  {6, UPB_SIZE(32, 64), 0, 4, 11, 3},
+  {7, UPB_SIZE(12, 24), 2, 5, 11, 1},
+  {8, UPB_SIZE(36, 72), 0, 6, 11, 3},
+  {9, UPB_SIZE(40, 80), 0, 2, 11, 3},
+  {10, UPB_SIZE(44, 88), 0, 0, 12, 3},
+};
+
+const upb_msglayout google_protobuf_DescriptorProto_msginit = {
+  &google_protobuf_DescriptorProto_submsgs[0],
+  &google_protobuf_DescriptorProto__fields[0],
+  UPB_SIZE(48, 96), 10, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_DescriptorProto_ExtensionRange_submsgs[1] = {
+  &google_protobuf_ExtensionRangeOptions_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_DescriptorProto_ExtensionRange__fields[3] = {
+  {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
+  {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
+  {3, UPB_SIZE(12, 16), 3, 0, 11, 1},
+};
+
+const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit = {
+  &google_protobuf_DescriptorProto_ExtensionRange_submsgs[0],
+  &google_protobuf_DescriptorProto_ExtensionRange__fields[0],
+  UPB_SIZE(16, 24), 3, false, 255,
+};
+
+static const upb_msglayout_field google_protobuf_DescriptorProto_ReservedRange__fields[2] = {
+  {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
+  {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
+};
+
+const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit = {
+  NULL,
+  &google_protobuf_DescriptorProto_ReservedRange__fields[0],
+  UPB_SIZE(16, 16), 2, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_ExtensionRangeOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_ExtensionRangeOptions__fields[1] = {
+  {999, UPB_SIZE(0, 0), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit = {
+  &google_protobuf_ExtensionRangeOptions_submsgs[0],
+  &google_protobuf_ExtensionRangeOptions__fields[0],
+  UPB_SIZE(8, 8), 1, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_FieldDescriptorProto_submsgs[1] = {
+  &google_protobuf_FieldOptions_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_FieldDescriptorProto__fields[11] = {
+  {1, UPB_SIZE(24, 24), 1, 0, 12, 1},
+  {2, UPB_SIZE(32, 40), 2, 0, 12, 1},
+  {3, UPB_SIZE(12, 12), 3, 0, 5, 1},
+  {4, UPB_SIZE(4, 4), 4, 0, 14, 1},
+  {5, UPB_SIZE(8, 8), 5, 0, 14, 1},
+  {6, UPB_SIZE(40, 56), 6, 0, 12, 1},
+  {7, UPB_SIZE(48, 72), 7, 0, 12, 1},
+  {8, UPB_SIZE(64, 104), 8, 0, 11, 1},
+  {9, UPB_SIZE(16, 16), 9, 0, 5, 1},
+  {10, UPB_SIZE(56, 88), 10, 0, 12, 1},
+  {17, UPB_SIZE(20, 20), 11, 0, 8, 1},
+};
+
+const upb_msglayout google_protobuf_FieldDescriptorProto_msginit = {
+  &google_protobuf_FieldDescriptorProto_submsgs[0],
+  &google_protobuf_FieldDescriptorProto__fields[0],
+  UPB_SIZE(72, 112), 11, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_OneofDescriptorProto_submsgs[1] = {
+  &google_protobuf_OneofOptions_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_OneofDescriptorProto__fields[2] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(12, 24), 2, 0, 11, 1},
+};
+
+const upb_msglayout google_protobuf_OneofDescriptorProto_msginit = {
+  &google_protobuf_OneofDescriptorProto_submsgs[0],
+  &google_protobuf_OneofDescriptorProto__fields[0],
+  UPB_SIZE(16, 32), 2, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_EnumDescriptorProto_submsgs[3] = {
+  &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit,
+  &google_protobuf_EnumOptions_msginit,
+  &google_protobuf_EnumValueDescriptorProto_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_EnumDescriptorProto__fields[5] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(16, 32), 0, 2, 11, 3},
+  {3, UPB_SIZE(12, 24), 2, 1, 11, 1},
+  {4, UPB_SIZE(20, 40), 0, 0, 11, 3},
+  {5, UPB_SIZE(24, 48), 0, 0, 12, 3},
+};
+
+const upb_msglayout google_protobuf_EnumDescriptorProto_msginit = {
+  &google_protobuf_EnumDescriptorProto_submsgs[0],
+  &google_protobuf_EnumDescriptorProto__fields[0],
+  UPB_SIZE(32, 64), 5, false, 255,
+};
+
+static const upb_msglayout_field google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = {
+  {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
+  {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
+};
+
+const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit = {
+  NULL,
+  &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0],
+  UPB_SIZE(16, 16), 2, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_EnumValueDescriptorProto_submsgs[1] = {
+  &google_protobuf_EnumValueOptions_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_EnumValueDescriptorProto__fields[3] = {
+  {1, UPB_SIZE(8, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(4, 4), 2, 0, 5, 1},
+  {3, UPB_SIZE(16, 24), 3, 0, 11, 1},
+};
+
+const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit = {
+  &google_protobuf_EnumValueDescriptorProto_submsgs[0],
+  &google_protobuf_EnumValueDescriptorProto__fields[0],
+  UPB_SIZE(24, 32), 3, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_ServiceDescriptorProto_submsgs[2] = {
+  &google_protobuf_MethodDescriptorProto_msginit,
+  &google_protobuf_ServiceOptions_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_ServiceDescriptorProto__fields[3] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(16, 32), 0, 0, 11, 3},
+  {3, UPB_SIZE(12, 24), 2, 1, 11, 1},
+};
+
+const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit = {
+  &google_protobuf_ServiceDescriptorProto_submsgs[0],
+  &google_protobuf_ServiceDescriptorProto__fields[0],
+  UPB_SIZE(24, 48), 3, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_MethodDescriptorProto_submsgs[1] = {
+  &google_protobuf_MethodOptions_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_MethodDescriptorProto__fields[6] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {2, UPB_SIZE(12, 24), 2, 0, 12, 1},
+  {3, UPB_SIZE(20, 40), 3, 0, 12, 1},
+  {4, UPB_SIZE(28, 56), 4, 0, 11, 1},
+  {5, UPB_SIZE(1, 1), 5, 0, 8, 1},
+  {6, UPB_SIZE(2, 2), 6, 0, 8, 1},
+};
+
+const upb_msglayout google_protobuf_MethodDescriptorProto_msginit = {
+  &google_protobuf_MethodDescriptorProto_submsgs[0],
+  &google_protobuf_MethodDescriptorProto__fields[0],
+  UPB_SIZE(32, 64), 6, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_FileOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_FileOptions__fields[21] = {
+  {1, UPB_SIZE(20, 24), 1, 0, 12, 1},
+  {8, UPB_SIZE(28, 40), 2, 0, 12, 1},
+  {9, UPB_SIZE(4, 4), 3, 0, 14, 1},
+  {10, UPB_SIZE(8, 8), 4, 0, 8, 1},
+  {11, UPB_SIZE(36, 56), 5, 0, 12, 1},
+  {16, UPB_SIZE(9, 9), 6, 0, 8, 1},
+  {17, UPB_SIZE(10, 10), 7, 0, 8, 1},
+  {18, UPB_SIZE(11, 11), 8, 0, 8, 1},
+  {20, UPB_SIZE(12, 12), 9, 0, 8, 1},
+  {23, UPB_SIZE(13, 13), 10, 0, 8, 1},
+  {27, UPB_SIZE(14, 14), 11, 0, 8, 1},
+  {31, UPB_SIZE(15, 15), 12, 0, 8, 1},
+  {36, UPB_SIZE(44, 72), 13, 0, 12, 1},
+  {37, UPB_SIZE(52, 88), 14, 0, 12, 1},
+  {39, UPB_SIZE(60, 104), 15, 0, 12, 1},
+  {40, UPB_SIZE(68, 120), 16, 0, 12, 1},
+  {41, UPB_SIZE(76, 136), 17, 0, 12, 1},
+  {42, UPB_SIZE(16, 16), 18, 0, 8, 1},
+  {44, UPB_SIZE(84, 152), 19, 0, 12, 1},
+  {45, UPB_SIZE(92, 168), 20, 0, 12, 1},
+  {999, UPB_SIZE(100, 184), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_FileOptions_msginit = {
+  &google_protobuf_FileOptions_submsgs[0],
+  &google_protobuf_FileOptions__fields[0],
+  UPB_SIZE(104, 192), 21, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_MessageOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_MessageOptions__fields[5] = {
+  {1, UPB_SIZE(1, 1), 1, 0, 8, 1},
+  {2, UPB_SIZE(2, 2), 2, 0, 8, 1},
+  {3, UPB_SIZE(3, 3), 3, 0, 8, 1},
+  {7, UPB_SIZE(4, 4), 4, 0, 8, 1},
+  {999, UPB_SIZE(8, 8), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_MessageOptions_msginit = {
+  &google_protobuf_MessageOptions_submsgs[0],
+  &google_protobuf_MessageOptions__fields[0],
+  UPB_SIZE(16, 16), 5, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_FieldOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_FieldOptions__fields[7] = {
+  {1, UPB_SIZE(4, 4), 1, 0, 14, 1},
+  {2, UPB_SIZE(12, 12), 2, 0, 8, 1},
+  {3, UPB_SIZE(13, 13), 3, 0, 8, 1},
+  {5, UPB_SIZE(14, 14), 4, 0, 8, 1},
+  {6, UPB_SIZE(8, 8), 5, 0, 14, 1},
+  {10, UPB_SIZE(15, 15), 6, 0, 8, 1},
+  {999, UPB_SIZE(16, 16), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_FieldOptions_msginit = {
+  &google_protobuf_FieldOptions_submsgs[0],
+  &google_protobuf_FieldOptions__fields[0],
+  UPB_SIZE(24, 24), 7, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_OneofOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_OneofOptions__fields[1] = {
+  {999, UPB_SIZE(0, 0), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_OneofOptions_msginit = {
+  &google_protobuf_OneofOptions_submsgs[0],
+  &google_protobuf_OneofOptions__fields[0],
+  UPB_SIZE(8, 8), 1, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_EnumOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_EnumOptions__fields[3] = {
+  {2, UPB_SIZE(1, 1), 1, 0, 8, 1},
+  {3, UPB_SIZE(2, 2), 2, 0, 8, 1},
+  {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_EnumOptions_msginit = {
+  &google_protobuf_EnumOptions_submsgs[0],
+  &google_protobuf_EnumOptions__fields[0],
+  UPB_SIZE(8, 16), 3, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_EnumValueOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_EnumValueOptions__fields[2] = {
+  {1, UPB_SIZE(1, 1), 1, 0, 8, 1},
+  {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_EnumValueOptions_msginit = {
+  &google_protobuf_EnumValueOptions_submsgs[0],
+  &google_protobuf_EnumValueOptions__fields[0],
+  UPB_SIZE(8, 16), 2, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_ServiceOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_ServiceOptions__fields[2] = {
+  {33, UPB_SIZE(1, 1), 1, 0, 8, 1},
+  {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_ServiceOptions_msginit = {
+  &google_protobuf_ServiceOptions_submsgs[0],
+  &google_protobuf_ServiceOptions__fields[0],
+  UPB_SIZE(8, 16), 2, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_MethodOptions_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_MethodOptions__fields[3] = {
+  {33, UPB_SIZE(8, 8), 1, 0, 8, 1},
+  {34, UPB_SIZE(4, 4), 2, 0, 14, 1},
+  {999, UPB_SIZE(12, 16), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_MethodOptions_msginit = {
+  &google_protobuf_MethodOptions_submsgs[0],
+  &google_protobuf_MethodOptions__fields[0],
+  UPB_SIZE(16, 24), 3, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_UninterpretedOption_submsgs[1] = {
+  &google_protobuf_UninterpretedOption_NamePart_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_UninterpretedOption__fields[7] = {
+  {2, UPB_SIZE(56, 80), 0, 0, 11, 3},
+  {3, UPB_SIZE(32, 32), 1, 0, 12, 1},
+  {4, UPB_SIZE(8, 8), 2, 0, 4, 1},
+  {5, UPB_SIZE(16, 16), 3, 0, 3, 1},
+  {6, UPB_SIZE(24, 24), 4, 0, 1, 1},
+  {7, UPB_SIZE(40, 48), 5, 0, 12, 1},
+  {8, UPB_SIZE(48, 64), 6, 0, 12, 1},
+};
+
+const upb_msglayout google_protobuf_UninterpretedOption_msginit = {
+  &google_protobuf_UninterpretedOption_submsgs[0],
+  &google_protobuf_UninterpretedOption__fields[0],
+  UPB_SIZE(64, 96), 7, false, 255,
+};
+
+static const upb_msglayout_field google_protobuf_UninterpretedOption_NamePart__fields[2] = {
+  {1, UPB_SIZE(4, 8), 1, 0, 12, 2},
+  {2, UPB_SIZE(1, 1), 2, 0, 8, 2},
+};
+
+const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit = {
+  NULL,
+  &google_protobuf_UninterpretedOption_NamePart__fields[0],
+  UPB_SIZE(16, 32), 2, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_SourceCodeInfo_submsgs[1] = {
+  &google_protobuf_SourceCodeInfo_Location_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_SourceCodeInfo__fields[1] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_SourceCodeInfo_msginit = {
+  &google_protobuf_SourceCodeInfo_submsgs[0],
+  &google_protobuf_SourceCodeInfo__fields[0],
+  UPB_SIZE(8, 8), 1, false, 255,
+};
+
+static const upb_msglayout_field google_protobuf_SourceCodeInfo_Location__fields[5] = {
+  {1, UPB_SIZE(20, 40), 0, 0, 5, _UPB_LABEL_PACKED},
+  {2, UPB_SIZE(24, 48), 0, 0, 5, _UPB_LABEL_PACKED},
+  {3, UPB_SIZE(4, 8), 1, 0, 12, 1},
+  {4, UPB_SIZE(12, 24), 2, 0, 12, 1},
+  {6, UPB_SIZE(28, 56), 0, 0, 12, 3},
+};
+
+const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit = {
+  NULL,
+  &google_protobuf_SourceCodeInfo_Location__fields[0],
+  UPB_SIZE(32, 64), 5, false, 255,
+};
+
+static const upb_msglayout *const google_protobuf_GeneratedCodeInfo_submsgs[1] = {
+  &google_protobuf_GeneratedCodeInfo_Annotation_msginit,
+};
+
+static const upb_msglayout_field google_protobuf_GeneratedCodeInfo__fields[1] = {
+  {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
+};
+
+const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit = {
+  &google_protobuf_GeneratedCodeInfo_submsgs[0],
+  &google_protobuf_GeneratedCodeInfo__fields[0],
+  UPB_SIZE(8, 8), 1, false, 255,
+};
+
+static const upb_msglayout_field google_protobuf_GeneratedCodeInfo_Annotation__fields[4] = {
+  {1, UPB_SIZE(20, 32), 0, 0, 5, _UPB_LABEL_PACKED},
+  {2, UPB_SIZE(12, 16), 1, 0, 12, 1},
+  {3, UPB_SIZE(4, 4), 2, 0, 5, 1},
+  {4, UPB_SIZE(8, 8), 3, 0, 5, 1},
+};
+
+const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit = {
+  NULL,
+  &google_protobuf_GeneratedCodeInfo_Annotation__fields[0],
+  UPB_SIZE(24, 48), 4, false, 255,
+};
+
+
+
+
+#include <ctype.h>
+#include <errno.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Must be last. */
+
+typedef struct {
+  size_t len;
+  char str[1];  /* Null-terminated string data follows. */
+} str_t;
+
+struct upb_fielddef {
+  const upb_filedef *file;
+  const upb_msgdef *msgdef;
+  const char *full_name;
+  const char *json_name;
+  union {
+    int64_t sint;
+    uint64_t uint;
+    double dbl;
+    float flt;
+    bool boolean;
+    str_t *str;
+  } defaultval;
+  const upb_oneofdef *oneof;
+  union {
+    const upb_msgdef *msgdef;
+    const upb_enumdef *enumdef;
+    const google_protobuf_FieldDescriptorProto *unresolved;
+  } sub;
+  uint32_t number_;
+  uint16_t index_;
+  uint16_t layout_index;
+  uint32_t selector_base;  /* Used to index into a upb::Handlers table. */
+  bool is_extension_;
+  bool lazy_;
+  bool packed_;
+  bool proto3_optional_;
+  upb_descriptortype_t type_;
+  upb_label_t label_;
+};
+
+struct upb_msgdef {
+  const upb_msglayout *layout;
+  const upb_filedef *file;
+  const char *full_name;
+  uint32_t selector_count;
+  uint32_t submsg_field_count;
+
+  /* Tables for looking up fields by number and name. */
+  upb_inttable itof;
+  upb_strtable ntof;
+
+  const upb_fielddef *fields;
+  const upb_oneofdef *oneofs;
+  int field_count;
+  int oneof_count;
+  int real_oneof_count;
+
+  /* Is this a map-entry message? */
+  bool map_entry;
+  upb_wellknowntype_t well_known_type;
+
+  /* TODO(haberman): proper extension ranges (there can be multiple). */
+};
+
+struct upb_enumdef {
+  const upb_filedef *file;
+  const char *full_name;
+  upb_strtable ntoi;
+  upb_inttable iton;
+  int32_t defaultval;
+};
+
+struct upb_oneofdef {
+  const upb_msgdef *parent;
+  const char *full_name;
+  int field_count;
+  bool synthetic;
+  const upb_fielddef **fields;
+  upb_strtable ntof;
+  upb_inttable itof;
+};
+
+struct upb_filedef {
+  const char *name;
+  const char *package;
+  const char *phpprefix;
+  const char *phpnamespace;
+
+  const upb_filedef **deps;
+  const upb_msgdef *msgs;
+  const upb_enumdef *enums;
+  const upb_fielddef *exts;
+  const upb_symtab *symtab;
+
+  int dep_count;
+  int msg_count;
+  int enum_count;
+  int ext_count;
+  upb_syntax_t syntax;
+};
+
+struct upb_symtab {
+  upb_arena *arena;
+  upb_strtable syms;  /* full_name -> packed def ptr */
+  upb_strtable files;  /* file_name -> upb_filedef* */
+  size_t bytes_loaded;
+};
+
+/* Inside a symtab we store tagged pointers to specific def types. */
+typedef enum {
+  UPB_DEFTYPE_FIELD = 0,
+
+  /* Only inside symtab table. */
+  UPB_DEFTYPE_MSG = 1,
+  UPB_DEFTYPE_ENUM = 2,
+
+  /* Only inside message table. */
+  UPB_DEFTYPE_ONEOF = 1,
+  UPB_DEFTYPE_FIELD_JSONNAME = 2
+} upb_deftype_t;
+
+static const void *unpack_def(upb_value v, upb_deftype_t type) {
+  uintptr_t num = (uintptr_t)upb_value_getconstptr(v);
+  return (num & 3) == type ? (const void*)(num & ~3) : NULL;
+}
+
+static upb_value pack_def(const void *ptr, upb_deftype_t type) {
+  uintptr_t num = (uintptr_t)ptr | type;
+  return upb_value_constptr((const void*)num);
+}
+
+/* isalpha() etc. from <ctype.h> are locale-dependent, which we don't want. */
+static bool upb_isbetween(char c, char low, char high) {
+  return c >= low && c <= high;
+}
+
+static bool upb_isletter(char c) {
+  return upb_isbetween(c, 'A', 'Z') || upb_isbetween(c, 'a', 'z') || c == '_';
+}
+
+static bool upb_isalphanum(char c) {
+  return upb_isletter(c) || upb_isbetween(c, '0', '9');
+}
+
+static const char *shortdefname(const char *fullname) {
+  const char *p;
+
+  if (fullname == NULL) {
+    return NULL;
+  } else if ((p = strrchr(fullname, '.')) == NULL) {
+    /* No '.' in the name, return the full string. */
+    return fullname;
+  } else {
+    /* Return one past the last '.'. */
+    return p + 1;
+  }
+}
+
+/* All submessage fields are lower than all other fields.
+ * Secondly, fields are increasing in order. */
+uint32_t field_rank(const upb_fielddef *f) {
+  uint32_t ret = upb_fielddef_number(f);
+  const uint32_t high_bit = 1 << 30;
+  UPB_ASSERT(ret < high_bit);
+  if (!upb_fielddef_issubmsg(f))
+    ret |= high_bit;
+  return ret;
+}
+
+int cmp_fields(const void *p1, const void *p2) {
+  const upb_fielddef *f1 = *(upb_fielddef*const*)p1;
+  const upb_fielddef *f2 = *(upb_fielddef*const*)p2;
+  return field_rank(f1) - field_rank(f2);
+}
+
+/* A few implementation details of handlers.  We put these here to avoid
+ * a def -> handlers dependency. */
+
+#define UPB_STATIC_SELECTOR_COUNT 3  /* Warning: also in upb/handlers.h. */
+
+static uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) {
+  return upb_fielddef_isseq(f) ? 2 : 0;
+}
+
+static uint32_t upb_handlers_selectorcount(const upb_fielddef *f) {
+  uint32_t ret = 1;
+  if (upb_fielddef_isseq(f)) ret += 2;    /* STARTSEQ/ENDSEQ */
+  if (upb_fielddef_isstring(f)) ret += 2; /* [STRING]/STARTSTR/ENDSTR */
+  if (upb_fielddef_issubmsg(f)) {
+    /* ENDSUBMSG (STARTSUBMSG is at table beginning) */
+    ret += 0;
+    if (upb_fielddef_lazy(f)) {
+      /* STARTSTR/ENDSTR/STRING (for lazy) */
+      ret += 3;
+    }
+  }
+  return ret;
+}
+
+static void upb_status_setoom(upb_status *status) {
+  upb_status_seterrmsg(status, "out of memory");
+}
+
+static void assign_msg_wellknowntype(upb_msgdef *m) {
+  const char *name = upb_msgdef_fullname(m);
+  if (name == NULL) {
+    m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED;
+    return;
+  }
+  if (!strcmp(name, "google.protobuf.Any")) {
+    m->well_known_type = UPB_WELLKNOWN_ANY;
+  } else if (!strcmp(name, "google.protobuf.FieldMask")) {
+    m->well_known_type = UPB_WELLKNOWN_FIELDMASK;
+  } else if (!strcmp(name, "google.protobuf.Duration")) {
+    m->well_known_type = UPB_WELLKNOWN_DURATION;
+  } else if (!strcmp(name, "google.protobuf.Timestamp")) {
+    m->well_known_type = UPB_WELLKNOWN_TIMESTAMP;
+  } else if (!strcmp(name, "google.protobuf.DoubleValue")) {
+    m->well_known_type = UPB_WELLKNOWN_DOUBLEVALUE;
+  } else if (!strcmp(name, "google.protobuf.FloatValue")) {
+    m->well_known_type = UPB_WELLKNOWN_FLOATVALUE;
+  } else if (!strcmp(name, "google.protobuf.Int64Value")) {
+    m->well_known_type = UPB_WELLKNOWN_INT64VALUE;
+  } else if (!strcmp(name, "google.protobuf.UInt64Value")) {
+    m->well_known_type = UPB_WELLKNOWN_UINT64VALUE;
+  } else if (!strcmp(name, "google.protobuf.Int32Value")) {
+    m->well_known_type = UPB_WELLKNOWN_INT32VALUE;
+  } else if (!strcmp(name, "google.protobuf.UInt32Value")) {
+    m->well_known_type = UPB_WELLKNOWN_UINT32VALUE;
+  } else if (!strcmp(name, "google.protobuf.BoolValue")) {
+    m->well_known_type = UPB_WELLKNOWN_BOOLVALUE;
+  } else if (!strcmp(name, "google.protobuf.StringValue")) {
+    m->well_known_type = UPB_WELLKNOWN_STRINGVALUE;
+  } else if (!strcmp(name, "google.protobuf.BytesValue")) {
+    m->well_known_type = UPB_WELLKNOWN_BYTESVALUE;
+  } else if (!strcmp(name, "google.protobuf.Value")) {
+    m->well_known_type = UPB_WELLKNOWN_VALUE;
+  } else if (!strcmp(name, "google.protobuf.ListValue")) {
+    m->well_known_type = UPB_WELLKNOWN_LISTVALUE;
+  } else if (!strcmp(name, "google.protobuf.Struct")) {
+    m->well_known_type = UPB_WELLKNOWN_STRUCT;
+  } else {
+    m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED;
+  }
+}
+
+
+/* upb_enumdef ****************************************************************/
+
+const char *upb_enumdef_fullname(const upb_enumdef *e) {
+  return e->full_name;
+}
+
+const char *upb_enumdef_name(const upb_enumdef *e) {
+  return shortdefname(e->full_name);
+}
+
+const upb_filedef *upb_enumdef_file(const upb_enumdef *e) {
+  return e->file;
+}
+
+int32_t upb_enumdef_default(const upb_enumdef *e) {
+  UPB_ASSERT(upb_enumdef_iton(e, e->defaultval));
+  return e->defaultval;
+}
+
+int upb_enumdef_numvals(const upb_enumdef *e) {
+  return (int)upb_strtable_count(&e->ntoi);
+}
+
+void upb_enum_begin(upb_enum_iter *i, const upb_enumdef *e) {
+  /* We iterate over the ntoi table, to account for duplicate numbers. */
+  upb_strtable_begin(i, &e->ntoi);
+}
+
+void upb_enum_next(upb_enum_iter *iter) { upb_strtable_next(iter); }
+bool upb_enum_done(upb_enum_iter *iter) { return upb_strtable_done(iter); }
+
+bool upb_enumdef_ntoi(const upb_enumdef *def, const char *name,
+                      size_t len, int32_t *num) {
+  upb_value v;
+  if (!upb_strtable_lookup2(&def->ntoi, name, len, &v)) {
+    return false;
+  }
+  if (num) *num = upb_value_getint32(v);
+  return true;
+}
+
+const char *upb_enumdef_iton(const upb_enumdef *def, int32_t num) {
+  upb_value v;
+  return upb_inttable_lookup32(&def->iton, num, &v) ?
+      upb_value_getcstr(v) : NULL;
+}
+
+const char *upb_enum_iter_name(upb_enum_iter *iter) {
+  return upb_strtable_iter_key(iter).data;
+}
+
+int32_t upb_enum_iter_number(upb_enum_iter *iter) {
+  return upb_value_getint32(upb_strtable_iter_value(iter));
+}
+
+
+/* upb_fielddef ***************************************************************/
+
+const char *upb_fielddef_fullname(const upb_fielddef *f) {
+  return f->full_name;
+}
+
+upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f) {
+  switch (f->type_) {
+    case UPB_DESCRIPTOR_TYPE_DOUBLE:
+      return UPB_TYPE_DOUBLE;
+    case UPB_DESCRIPTOR_TYPE_FLOAT:
+      return UPB_TYPE_FLOAT;
+    case UPB_DESCRIPTOR_TYPE_INT64:
+    case UPB_DESCRIPTOR_TYPE_SINT64:
+    case UPB_DESCRIPTOR_TYPE_SFIXED64:
+      return UPB_TYPE_INT64;
+    case UPB_DESCRIPTOR_TYPE_INT32:
+    case UPB_DESCRIPTOR_TYPE_SFIXED32:
+    case UPB_DESCRIPTOR_TYPE_SINT32:
+      return UPB_TYPE_INT32;
+    case UPB_DESCRIPTOR_TYPE_UINT64:
+    case UPB_DESCRIPTOR_TYPE_FIXED64:
+      return UPB_TYPE_UINT64;
+    case UPB_DESCRIPTOR_TYPE_UINT32:
+    case UPB_DESCRIPTOR_TYPE_FIXED32:
+      return UPB_TYPE_UINT32;
+    case UPB_DESCRIPTOR_TYPE_ENUM:
+      return UPB_TYPE_ENUM;
+    case UPB_DESCRIPTOR_TYPE_BOOL:
+      return UPB_TYPE_BOOL;
+    case UPB_DESCRIPTOR_TYPE_STRING:
+      return UPB_TYPE_STRING;
+    case UPB_DESCRIPTOR_TYPE_BYTES:
+      return UPB_TYPE_BYTES;
+    case UPB_DESCRIPTOR_TYPE_GROUP:
+    case UPB_DESCRIPTOR_TYPE_MESSAGE:
+      return UPB_TYPE_MESSAGE;
+  }
+  UPB_UNREACHABLE();
+}
+
+upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f) {
+  return f->type_;
+}
+
+uint32_t upb_fielddef_index(const upb_fielddef *f) {
+  return f->index_;
+}
+
+upb_label_t upb_fielddef_label(const upb_fielddef *f) {
+  return f->label_;
+}
+
+uint32_t upb_fielddef_number(const upb_fielddef *f) {
+  return f->number_;
+}
+
+bool upb_fielddef_isextension(const upb_fielddef *f) {
+  return f->is_extension_;
+}
+
+bool upb_fielddef_lazy(const upb_fielddef *f) {
+  return f->lazy_;
+}
+
+bool upb_fielddef_packed(const upb_fielddef *f) {
+  return f->packed_;
+}
+
+const char *upb_fielddef_name(const upb_fielddef *f) {
+  return shortdefname(f->full_name);
+}
+
+const char *upb_fielddef_jsonname(const upb_fielddef *f) {
+  return f->json_name;
+}
+
+uint32_t upb_fielddef_selectorbase(const upb_fielddef *f) {
+  return f->selector_base;
+}
+
+const upb_filedef *upb_fielddef_file(const upb_fielddef *f) {
+  return f->file;
+}
+
+const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) {
+  return f->msgdef;
+}
+
+const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f) {
+  return f->oneof;
+}
+
+const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f) {
+  if (!f->oneof || upb_oneofdef_issynthetic(f->oneof)) return NULL;
+  return f->oneof;
+}
+
+upb_msgval upb_fielddef_default(const upb_fielddef *f) {
+  UPB_ASSERT(!upb_fielddef_issubmsg(f));
+  upb_msgval ret;
+  if (upb_fielddef_isstring(f)) {
+    str_t *str = f->defaultval.str;
+    if (str) {
+      ret.str_val.data = str->str;
+      ret.str_val.size = str->len;
+    } else {
+      ret.str_val.size = 0;
+    }
+  } else {
+    memcpy(&ret, &f->defaultval, 8);
+  }
+  return ret;
+}
+
+static void chkdefaulttype(const upb_fielddef *f, int ctype) {
+  UPB_UNUSED(f);
+  UPB_UNUSED(ctype);
+}
+
+int64_t upb_fielddef_defaultint64(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_INT64);
+  return f->defaultval.sint;
+}
+
+int32_t upb_fielddef_defaultint32(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_INT32);
+  return (int32_t)f->defaultval.sint;
+}
+
+uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_UINT64);
+  return f->defaultval.uint;
+}
+
+uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_UINT32);
+  return (uint32_t)f->defaultval.uint;
+}
+
+bool upb_fielddef_defaultbool(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_BOOL);
+  return f->defaultval.boolean;
+}
+
+float upb_fielddef_defaultfloat(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_FLOAT);
+  return f->defaultval.flt;
+}
+
+double upb_fielddef_defaultdouble(const upb_fielddef *f) {
+  chkdefaulttype(f, UPB_TYPE_DOUBLE);
+  return f->defaultval.dbl;
+}
+
+const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) {
+  str_t *str = f->defaultval.str;
+  UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_STRING ||
+         upb_fielddef_type(f) == UPB_TYPE_BYTES ||
+         upb_fielddef_type(f) == UPB_TYPE_ENUM);
+  if (str) {
+    if (len) *len = str->len;
+    return str->str;
+  } else {
+    if (len) *len = 0;
+    return NULL;
+  }
+}
+
+const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f) {
+  return upb_fielddef_type(f) == UPB_TYPE_MESSAGE ? f->sub.msgdef : NULL;
+}
+
+const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f) {
+  return upb_fielddef_type(f) == UPB_TYPE_ENUM ? f->sub.enumdef : NULL;
+}
+
+const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f) {
+  return &f->msgdef->layout->fields[f->layout_index];
+}
+
+bool upb_fielddef_issubmsg(const upb_fielddef *f) {
+  return upb_fielddef_type(f) == UPB_TYPE_MESSAGE;
+}
+
+bool upb_fielddef_isstring(const upb_fielddef *f) {
+  return upb_fielddef_type(f) == UPB_TYPE_STRING ||
+         upb_fielddef_type(f) == UPB_TYPE_BYTES;
+}
+
+bool upb_fielddef_isseq(const upb_fielddef *f) {
+  return upb_fielddef_label(f) == UPB_LABEL_REPEATED;
+}
+
+bool upb_fielddef_isprimitive(const upb_fielddef *f) {
+  return !upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f);
+}
+
+bool upb_fielddef_ismap(const upb_fielddef *f) {
+  return upb_fielddef_isseq(f) && upb_fielddef_issubmsg(f) &&
+         upb_msgdef_mapentry(upb_fielddef_msgsubdef(f));
+}
+
+bool upb_fielddef_hassubdef(const upb_fielddef *f) {
+  return upb_fielddef_issubmsg(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM;
+}
+
+bool upb_fielddef_haspresence(const upb_fielddef *f) {
+  if (upb_fielddef_isseq(f)) return false;
+  return upb_fielddef_issubmsg(f) || upb_fielddef_containingoneof(f) ||
+         f->file->syntax == UPB_SYNTAX_PROTO2;
+}
+
+static bool between(int32_t x, int32_t low, int32_t high) {
+  return x >= low && x <= high;
+}
+
+bool upb_fielddef_checklabel(int32_t label) { return between(label, 1, 3); }
+bool upb_fielddef_checktype(int32_t type) { return between(type, 1, 11); }
+bool upb_fielddef_checkintfmt(int32_t fmt) { return between(fmt, 1, 3); }
+
+bool upb_fielddef_checkdescriptortype(int32_t type) {
+  return between(type, 1, 18);
+}
+
+/* upb_msgdef *****************************************************************/
+
+const char *upb_msgdef_fullname(const upb_msgdef *m) {
+  return m->full_name;
+}
+
+const upb_filedef *upb_msgdef_file(const upb_msgdef *m) {
+  return m->file;
+}
+
+const char *upb_msgdef_name(const upb_msgdef *m) {
+  return shortdefname(m->full_name);
+}
+
+upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m) {
+  return m->file->syntax;
+}
+
+size_t upb_msgdef_selectorcount(const upb_msgdef *m) {
+  return m->selector_count;
+}
+
+uint32_t upb_msgdef_submsgfieldcount(const upb_msgdef *m) {
+  return m->submsg_field_count;
+}
+
+const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) {
+  upb_value val;
+  return upb_inttable_lookup32(&m->itof, i, &val) ?
+      upb_value_getconstptr(val) : NULL;
+}
+
+const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
+                                    size_t len) {
+  upb_value val;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+    return NULL;
+  }
+
+  return unpack_def(val, UPB_DEFTYPE_FIELD);
+}
+
+const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
+                                    size_t len) {
+  upb_value val;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+    return NULL;
+  }
+
+  return unpack_def(val, UPB_DEFTYPE_ONEOF);
+}
+
+bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
+                           const upb_fielddef **f, const upb_oneofdef **o) {
+  upb_value val;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+    return false;
+  }
+
+  *o = unpack_def(val, UPB_DEFTYPE_ONEOF);
+  *f = unpack_def(val, UPB_DEFTYPE_FIELD);
+  return *o || *f;  /* False if this was a JSON name. */
+}
+
+const upb_fielddef *upb_msgdef_lookupjsonname(const upb_msgdef *m,
+                                              const char *name, size_t len) {
+  upb_value val;
+  const upb_fielddef* f;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+    return NULL;
+  }
+
+  f = unpack_def(val, UPB_DEFTYPE_FIELD);
+  if (!f) f = unpack_def(val, UPB_DEFTYPE_FIELD_JSONNAME);
+
+  return f;
+}
+
+int upb_msgdef_numfields(const upb_msgdef *m) {
+  return m->field_count;
+}
+
+int upb_msgdef_numoneofs(const upb_msgdef *m) {
+  return m->oneof_count;
+}
+
+int upb_msgdef_numrealoneofs(const upb_msgdef *m) {
+  return m->real_oneof_count;
+}
+
+int upb_msgdef_fieldcount(const upb_msgdef *m) {
+  return m->field_count;
+}
+
+int upb_msgdef_oneofcount(const upb_msgdef *m) {
+  return m->oneof_count;
+}
+
+int upb_msgdef_realoneofcount(const upb_msgdef *m) {
+  return m->real_oneof_count;
+}
+
+const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m) {
+  return m->layout;
+}
+
+const upb_fielddef *upb_msgdef_field(const upb_msgdef *m, int i) {
+  UPB_ASSERT(i >= 0 && i < m->field_count);
+  return &m->fields[i];
+}
+
+const upb_oneofdef *upb_msgdef_oneof(const upb_msgdef *m, int i) {
+  UPB_ASSERT(i >= 0 && i < m->oneof_count);
+  return &m->oneofs[i];
+}
+
+bool upb_msgdef_mapentry(const upb_msgdef *m) {
+  return m->map_entry;
+}
+
+upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m) {
+  return m->well_known_type;
+}
+
+bool upb_msgdef_isnumberwrapper(const upb_msgdef *m) {
+  upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
+  return type >= UPB_WELLKNOWN_DOUBLEVALUE &&
+         type <= UPB_WELLKNOWN_UINT32VALUE;
+}
+
+bool upb_msgdef_iswrapper(const upb_msgdef *m) {
+  upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
+  return type >= UPB_WELLKNOWN_DOUBLEVALUE &&
+         type <= UPB_WELLKNOWN_BOOLVALUE;
+}
+
+void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m) {
+  upb_inttable_begin(iter, &m->itof);
+}
+
+void upb_msg_field_next(upb_msg_field_iter *iter) { upb_inttable_next(iter); }
+
+bool upb_msg_field_done(const upb_msg_field_iter *iter) {
+  return upb_inttable_done(iter);
+}
+
+upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter) {
+  return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter));
+}
+
+void upb_msg_field_iter_setdone(upb_msg_field_iter *iter) {
+  upb_inttable_iter_setdone(iter);
+}
+
+bool upb_msg_field_iter_isequal(const upb_msg_field_iter * iter1,
+                                const upb_msg_field_iter * iter2) {
+  return upb_inttable_iter_isequal(iter1, iter2);
+}
+
+void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) {
+  upb_strtable_begin(iter, &m->ntof);
+  /* We need to skip past any initial fields. */
+  while (!upb_strtable_done(iter) &&
+         !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF)) {
+    upb_strtable_next(iter);
+  }
+}
+
+void upb_msg_oneof_next(upb_msg_oneof_iter *iter) {
+  /* We need to skip past fields to return only oneofs. */
+  do {
+    upb_strtable_next(iter);
+  } while (!upb_strtable_done(iter) &&
+           !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF));
+}
+
+bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) {
+  return upb_strtable_done(iter);
+}
+
+const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter) {
+  return unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF);
+}
+
+void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter) {
+  upb_strtable_iter_setdone(iter);
+}
+
+bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1,
+                                const upb_msg_oneof_iter *iter2) {
+  return upb_strtable_iter_isequal(iter1, iter2);
+}
+
+/* upb_oneofdef ***************************************************************/
+
+const char *upb_oneofdef_name(const upb_oneofdef *o) {
+  return shortdefname(o->full_name);
+}
+
+const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) {
+  return o->parent;
+}
+
+int upb_oneofdef_fieldcount(const upb_oneofdef *o) {
+  return o->field_count;
+}
+
+const upb_fielddef *upb_oneofdef_field(const upb_oneofdef *o, int i) {
+  UPB_ASSERT(i < o->field_count);
+  return o->fields[i];
+}
+
+int upb_oneofdef_numfields(const upb_oneofdef *o) {
+  return o->field_count;
+}
+
+uint32_t upb_oneofdef_index(const upb_oneofdef *o) {
+  return o - o->parent->oneofs;
+}
+
+bool upb_oneofdef_issynthetic(const upb_oneofdef *o) {
+  return o->synthetic;
+}
+
+const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
+                                      const char *name, size_t length) {
+  upb_value val;
+  return upb_strtable_lookup2(&o->ntof, name, length, &val) ?
+      upb_value_getptr(val) : NULL;
+}
+
+const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num) {
+  upb_value val;
+  return upb_inttable_lookup32(&o->itof, num, &val) ?
+      upb_value_getptr(val) : NULL;
+}
+
+void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o) {
+  upb_inttable_begin(iter, &o->itof);
+}
+
+void upb_oneof_next(upb_oneof_iter *iter) {
+  upb_inttable_next(iter);
+}
+
+bool upb_oneof_done(upb_oneof_iter *iter) {
+  return upb_inttable_done(iter);
+}
+
+upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) {
+  return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter));
+}
+
+void upb_oneof_iter_setdone(upb_oneof_iter *iter) {
+  upb_inttable_iter_setdone(iter);
+}
+
+/* upb_filedef ****************************************************************/
+
+const char *upb_filedef_name(const upb_filedef *f) {
+  return f->name;
+}
+
+const char *upb_filedef_package(const upb_filedef *f) {
+  return f->package;
+}
+
+const char *upb_filedef_phpprefix(const upb_filedef *f) {
+  return f->phpprefix;
+}
+
+const char *upb_filedef_phpnamespace(const upb_filedef *f) {
+  return f->phpnamespace;
+}
+
+upb_syntax_t upb_filedef_syntax(const upb_filedef *f) {
+  return f->syntax;
+}
+
+int upb_filedef_msgcount(const upb_filedef *f) {
+  return f->msg_count;
+}
+
+int upb_filedef_depcount(const upb_filedef *f) {
+  return f->dep_count;
+}
+
+int upb_filedef_enumcount(const upb_filedef *f) {
+  return f->enum_count;
+}
+
+const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i) {
+  return i < 0 || i >= f->dep_count ? NULL : f->deps[i];
+}
+
+const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i) {
+  return i < 0 || i >= f->msg_count ? NULL : &f->msgs[i];
+}
+
+const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i) {
+  return i < 0 || i >= f->enum_count ? NULL : &f->enums[i];
+}
+
+const upb_symtab *upb_filedef_symtab(const upb_filedef *f) {
+  return f->symtab;
+}
+
+void upb_symtab_free(upb_symtab *s) {
+  upb_arena_free(s->arena);
+  upb_gfree(s);
+}
+
+upb_symtab *upb_symtab_new(void) {
+  upb_symtab *s = upb_gmalloc(sizeof(*s));
+  upb_alloc *alloc;
+
+  if (!s) {
+    return NULL;
+  }
+
+  s->arena = upb_arena_new();
+  s->bytes_loaded = 0;
+  alloc = upb_arena_alloc(s->arena);
+
+  if (!upb_strtable_init2(&s->syms, UPB_CTYPE_CONSTPTR, 32, alloc) ||
+      !upb_strtable_init2(&s->files, UPB_CTYPE_CONSTPTR, 4, alloc)) {
+    upb_arena_free(s->arena);
+    upb_gfree(s);
+    s = NULL;
+  }
+  return s;
+}
+
+const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym) {
+  upb_value v;
+  return upb_strtable_lookup(&s->syms, sym, &v) ?
+      unpack_def(v, UPB_DEFTYPE_MSG) : NULL;
+}
+
+const upb_msgdef *upb_symtab_lookupmsg2(const upb_symtab *s, const char *sym,
+                                        size_t len) {
+  upb_value v;
+  return upb_strtable_lookup2(&s->syms, sym, len, &v) ?
+      unpack_def(v, UPB_DEFTYPE_MSG) : NULL;
+}
+
+const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym) {
+  upb_value v;
+  return upb_strtable_lookup(&s->syms, sym, &v) ?
+      unpack_def(v, UPB_DEFTYPE_ENUM) : NULL;
+}
+
+const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name) {
+  upb_value v;
+  return upb_strtable_lookup(&s->files, name, &v) ? upb_value_getconstptr(v)
+                                                  : NULL;
+}
+
+const upb_filedef *upb_symtab_lookupfile2(
+    const upb_symtab *s, const char *name, size_t len) {
+  upb_value v;
+  return upb_strtable_lookup2(&s->files, name, len, &v) ?
+      upb_value_getconstptr(v) : NULL;
+}
+
+int upb_symtab_filecount(const upb_symtab *s) {
+  return (int)upb_strtable_count(&s->files);
+}
+
+/* Code to build defs from descriptor protos. *********************************/
+
+/* There is a question of how much validation to do here.  It will be difficult
+ * to perfectly match the amount of validation performed by proto2.  But since
+ * this code is used to directly build defs from Ruby (for example) we do need
+ * to validate important constraints like uniqueness of names and numbers. */
+
+#define CHK_OOM(x) if (!(x)) { symtab_oomerr(ctx); }
+
+typedef struct {
+  upb_symtab *symtab;
+  upb_filedef *file;              /* File we are building. */
+  upb_arena *file_arena;          /* Allocate defs here. */
+  upb_alloc *alloc;               /* Alloc of file_arena, for tables. */
+  const upb_msglayout **layouts;  /* NULL if we should build layouts. */
+  upb_status *status;             /* Record errors here. */
+  jmp_buf err;                    /* longjmp() on error. */
+} symtab_addctx;
+
+UPB_NORETURN UPB_NOINLINE UPB_PRINTF(2, 3)
+static void symtab_errf(symtab_addctx *ctx, const char *fmt, ...) {
+  va_list argp;
+  va_start(argp, fmt);
+  upb_status_vseterrf(ctx->status, fmt, argp);
+  va_end(argp);
+  UPB_LONGJMP(ctx->err, 1);
+}
+
+UPB_NORETURN UPB_NOINLINE
+static void symtab_oomerr(symtab_addctx *ctx) {
+  upb_status_setoom(ctx->status);
+  UPB_LONGJMP(ctx->err, 1);
+}
+
+void *symtab_alloc(symtab_addctx *ctx, size_t bytes) {
+  void *ret = upb_arena_malloc(ctx->file_arena, bytes);
+  if (!ret) symtab_oomerr(ctx);
+  return ret;
+}
+
+static void check_ident(symtab_addctx *ctx, upb_strview name, bool full) {
+  const char *str = name.data;
+  size_t len = name.size;
+  bool start = true;
+  size_t i;
+  for (i = 0; i < len; i++) {
+    char c = str[i];
+    if (c == '.') {
+      if (start || !full) {
+        symtab_errf(ctx, "invalid name: unexpected '.' (%.*s)", (int)len, str);
+      }
+      start = true;
+    } else if (start) {
+      if (!upb_isletter(c)) {
+        symtab_errf(
+            ctx,
+            "invalid name: path components must start with a letter (%.*s)",
+            (int)len, str);
+      }
+      start = false;
+    } else {
+      if (!upb_isalphanum(c)) {
+        symtab_errf(ctx, "invalid name: non-alphanumeric character (%.*s)",
+                    (int)len, str);
+      }
+    }
+  }
+  if (start) {
+    symtab_errf(ctx, "invalid name: empty part (%.*s)", (int)len, str);
+  }
+}
+
+static size_t div_round_up(size_t n, size_t d) {
+  return (n + d - 1) / d;
+}
+
+static size_t upb_msgval_sizeof(upb_fieldtype_t type) {
+  switch (type) {
+    case UPB_TYPE_DOUBLE:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT64:
+      return 8;
+    case UPB_TYPE_ENUM:
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_FLOAT:
+      return 4;
+    case UPB_TYPE_BOOL:
+      return 1;
+    case UPB_TYPE_MESSAGE:
+      return sizeof(void*);
+    case UPB_TYPE_BYTES:
+    case UPB_TYPE_STRING:
+      return sizeof(upb_strview);
+  }
+  UPB_UNREACHABLE();
+}
+
+static uint8_t upb_msg_fielddefsize(const upb_fielddef *f) {
+  if (upb_msgdef_mapentry(upb_fielddef_containingtype(f))) {
+    upb_map_entry ent;
+    UPB_ASSERT(sizeof(ent.k) == sizeof(ent.v));
+    return sizeof(ent.k);
+  } else if (upb_fielddef_isseq(f)) {
+    return sizeof(void*);
+  } else {
+    return upb_msgval_sizeof(upb_fielddef_type(f));
+  }
+}
+
+static uint32_t upb_msglayout_place(upb_msglayout *l, size_t size) {
+  uint32_t ret;
+
+  l->size = UPB_ALIGN_UP(l->size, size);
+  ret = l->size;
+  l->size += size;
+  return ret;
+}
+
+static int field_number_cmp(const void *p1, const void *p2) {
+  const upb_msglayout_field *f1 = p1;
+  const upb_msglayout_field *f2 = p2;
+  return f1->number - f2->number;
+}
+
+static void assign_layout_indices(const upb_msgdef *m, upb_msglayout_field *fields) {
+  int i;
+  int n = upb_msgdef_numfields(m);
+  for (i = 0; i < n; i++) {
+    upb_fielddef *f = (upb_fielddef*)upb_msgdef_itof(m, fields[i].number);
+    UPB_ASSERT(f);
+    f->layout_index = i;
+  }
+}
+
+/* This function is the dynamic equivalent of message_layout.{cc,h} in upbc.
+ * It computes a dynamic layout for all of the fields in |m|. */
+static void make_layout(symtab_addctx *ctx, const upb_msgdef *m) {
+  upb_msglayout *l = (upb_msglayout*)m->layout;
+  upb_msg_field_iter it;
+  upb_msg_oneof_iter oit;
+  size_t hasbit;
+  size_t submsg_count = m->submsg_field_count;
+  const upb_msglayout **submsgs;
+  upb_msglayout_field *fields;
+
+  memset(l, 0, sizeof(*l) + sizeof(_upb_fasttable_entry));
+
+  fields = symtab_alloc(ctx, upb_msgdef_numfields(m) * sizeof(*fields));
+  submsgs = symtab_alloc(ctx, submsg_count * sizeof(*submsgs));
+
+  l->field_count = upb_msgdef_numfields(m);
+  l->fields = fields;
+  l->submsgs = submsgs;
+  l->table_mask = 0;
+
+  /* TODO(haberman): initialize fast tables so that reflection-based parsing
+   * can get the same speeds as linked-in types. */
+  l->fasttable[0].field_parser = &fastdecode_generic;
+  l->fasttable[0].field_data = 0;
+
+  if (upb_msgdef_mapentry(m)) {
+    /* TODO(haberman): refactor this method so this special case is more
+     * elegant. */
+    const upb_fielddef *key = upb_msgdef_itof(m, 1);
+    const upb_fielddef *val = upb_msgdef_itof(m, 2);
+    fields[0].number = 1;
+    fields[1].number = 2;
+    fields[0].label = UPB_LABEL_OPTIONAL;
+    fields[1].label = UPB_LABEL_OPTIONAL;
+    fields[0].presence = 0;
+    fields[1].presence = 0;
+    fields[0].descriptortype = upb_fielddef_descriptortype(key);
+    fields[1].descriptortype = upb_fielddef_descriptortype(val);
+    fields[0].offset = 0;
+    fields[1].offset = sizeof(upb_strview);
+    fields[1].submsg_index = 0;
+
+    if (upb_fielddef_type(val) == UPB_TYPE_MESSAGE) {
+      submsgs[0] = upb_fielddef_msgsubdef(val)->layout;
+    }
+
+    l->field_count = 2;
+    l->size = 2 * sizeof(upb_strview);
+    l->size = UPB_ALIGN_UP(l->size, 8);
+    return;
+  }
+
+  /* Allocate data offsets in three stages:
+   *
+   * 1. hasbits.
+   * 2. regular fields.
+   * 3. oneof fields.
+   *
+   * OPT: There is a lot of room for optimization here to minimize the size.
+   */
+
+  /* Allocate hasbits and set basic field attributes. */
+  submsg_count = 0;
+  for (upb_msg_field_begin(&it, m), hasbit = 0;
+       !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    upb_fielddef* f = upb_msg_iter_field(&it);
+    upb_msglayout_field *field = &fields[upb_fielddef_index(f)];
+
+    field->number = upb_fielddef_number(f);
+    field->descriptortype = upb_fielddef_descriptortype(f);
+    field->label = upb_fielddef_label(f);
+
+    if (field->descriptortype == UPB_DTYPE_STRING &&
+        f->file->syntax == UPB_SYNTAX_PROTO2) {
+      /* See TableDescriptorType() in upbc/generator.cc for details and
+       * rationale. */
+      field->descriptortype = UPB_DTYPE_BYTES;
+    }
+
+    if (upb_fielddef_ismap(f)) {
+      field->label = _UPB_LABEL_MAP;
+    } else if (upb_fielddef_packed(f)) {
+      field->label = _UPB_LABEL_PACKED;
+    }
+
+    if (upb_fielddef_issubmsg(f)) {
+      const upb_msgdef *subm = upb_fielddef_msgsubdef(f);
+      field->submsg_index = submsg_count++;
+      submsgs[field->submsg_index] = subm->layout;
+    }
+
+    if (upb_fielddef_haspresence(f) && !upb_fielddef_realcontainingoneof(f)) {
+      /* We don't use hasbit 0, so that 0 can indicate "no presence" in the
+       * table. This wastes one hasbit, but we don't worry about it for now. */
+      field->presence = ++hasbit;
+    } else {
+      field->presence = 0;
+    }
+  }
+
+  /* Account for space used by hasbits. */
+  l->size = div_round_up(hasbit, 8);
+
+  /* Allocate non-oneof fields. */
+  for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it);
+       upb_msg_field_next(&it)) {
+    const upb_fielddef* f = upb_msg_iter_field(&it);
+    size_t field_size = upb_msg_fielddefsize(f);
+    size_t index = upb_fielddef_index(f);
+
+    if (upb_fielddef_realcontainingoneof(f)) {
+      /* Oneofs are handled separately below. */
+      continue;
+    }
+
+    fields[index].offset = upb_msglayout_place(l, field_size);
+  }
+
+  /* Allocate oneof fields.  Each oneof field consists of a uint32 for the case
+   * and space for the actual data. */
+  for (upb_msg_oneof_begin(&oit, m); !upb_msg_oneof_done(&oit);
+       upb_msg_oneof_next(&oit)) {
+    const upb_oneofdef* o = upb_msg_iter_oneof(&oit);
+    upb_oneof_iter fit;
+
+    size_t case_size = sizeof(uint32_t);  /* Could potentially optimize this. */
+    size_t field_size = 0;
+    uint32_t case_offset;
+    uint32_t data_offset;
+
+    if (upb_oneofdef_issynthetic(o)) continue;
+
+    /* Calculate field size: the max of all field sizes. */
+    for (upb_oneof_begin(&fit, o);
+         !upb_oneof_done(&fit);
+         upb_oneof_next(&fit)) {
+      const upb_fielddef* f = upb_oneof_iter_field(&fit);
+      field_size = UPB_MAX(field_size, upb_msg_fielddefsize(f));
+    }
+
+    /* Align and allocate case offset. */
+    case_offset = upb_msglayout_place(l, case_size);
+    data_offset = upb_msglayout_place(l, field_size);
+
+    for (upb_oneof_begin(&fit, o);
+         !upb_oneof_done(&fit);
+         upb_oneof_next(&fit)) {
+      const upb_fielddef* f = upb_oneof_iter_field(&fit);
+      fields[upb_fielddef_index(f)].offset = data_offset;
+      fields[upb_fielddef_index(f)].presence = ~case_offset;
+    }
+  }
+
+  /* Size of the entire structure should be a multiple of its greatest
+   * alignment.  TODO: track overall alignment for real? */
+  l->size = UPB_ALIGN_UP(l->size, 8);
+
+  /* Sort fields by number. */
+  qsort(fields, upb_msgdef_numfields(m), sizeof(*fields), field_number_cmp);
+  assign_layout_indices(m, fields);
+}
+
+static void assign_msg_indices(symtab_addctx *ctx, upb_msgdef *m) {
+  /* Sort fields.  upb internally relies on UPB_TYPE_MESSAGE fields having the
+   * lowest indexes, but we do not publicly guarantee this. */
+  upb_msg_field_iter j;
+  int i;
+  uint32_t selector;
+  int n = upb_msgdef_numfields(m);
+  upb_fielddef **fields;
+
+  if (n == 0) {
+    m->selector_count = UPB_STATIC_SELECTOR_COUNT;
+    m->submsg_field_count = 0;
+    return;
+  }
+
+  fields = upb_gmalloc(n * sizeof(*fields));
+
+  m->submsg_field_count = 0;
+  for(i = 0, upb_msg_field_begin(&j, m);
+      !upb_msg_field_done(&j);
+      upb_msg_field_next(&j), i++) {
+    upb_fielddef *f = upb_msg_iter_field(&j);
+    UPB_ASSERT(f->msgdef == m);
+    if (upb_fielddef_issubmsg(f)) {
+      m->submsg_field_count++;
+    }
+    fields[i] = f;
+  }
+
+  qsort(fields, n, sizeof(*fields), cmp_fields);
+
+  selector = UPB_STATIC_SELECTOR_COUNT + m->submsg_field_count;
+  for (i = 0; i < n; i++) {
+    upb_fielddef *f = fields[i];
+    f->index_ = i;
+    f->selector_base = selector + upb_handlers_selectorbaseoffset(f);
+    selector += upb_handlers_selectorcount(f);
+  }
+  m->selector_count = selector;
+
+  upb_gfree(fields);
+}
+
+static char *strviewdup(symtab_addctx *ctx, upb_strview view) {
+  return upb_strdup2(view.data, view.size, ctx->alloc);
+}
+
+static bool streql2(const char *a, size_t n, const char *b) {
+  return n == strlen(b) && memcmp(a, b, n) == 0;
+}
+
+static bool streql_view(upb_strview view, const char *b) {
+  return streql2(view.data, view.size, b);
+}
+
+static const char *makefullname(symtab_addctx *ctx, const char *prefix,
+                                upb_strview name) {
+  if (prefix) {
+    /* ret = prefix + '.' + name; */
+    size_t n = strlen(prefix);
+    char *ret = symtab_alloc(ctx, n + name.size + 2);
+    strcpy(ret, prefix);
+    ret[n] = '.';
+    memcpy(&ret[n + 1], name.data, name.size);
+    ret[n + 1 + name.size] = '\0';
+    return ret;
+  } else {
+    return strviewdup(ctx, name);
+  }
+}
+
+static void finalize_oneofs(symtab_addctx *ctx, upb_msgdef *m) {
+  int i;
+  int synthetic_count = 0;
+  upb_oneofdef *mutable_oneofs = (upb_oneofdef*)m->oneofs;
+
+  for (i = 0; i < m->oneof_count; i++) {
+    upb_oneofdef *o = &mutable_oneofs[i];
+
+    if (o->synthetic && o->field_count != 1) {
+      symtab_errf(ctx, "Synthetic oneofs must have one field, not %d: %s",
+                  o->field_count, upb_oneofdef_name(o));
+    }
+
+    if (o->synthetic) {
+      synthetic_count++;
+    } else if (synthetic_count != 0) {
+      symtab_errf(ctx, "Synthetic oneofs must be after all other oneofs: %s",
+                  upb_oneofdef_name(o));
+    }
+
+    o->fields = symtab_alloc(ctx, sizeof(upb_fielddef *) * o->field_count);
+    o->field_count = 0;
+  }
+
+  for (i = 0; i < m->field_count; i++) {
+    const upb_fielddef *f = &m->fields[i];
+    upb_oneofdef *o = (upb_oneofdef*)f->oneof;
+    if (o) {
+      o->fields[o->field_count++] = f;
+    }
+  }
+
+  m->real_oneof_count = m->oneof_count - synthetic_count;
+}
+
+size_t getjsonname(const char *name, char *buf, size_t len) {
+  size_t src, dst = 0;
+  bool ucase_next = false;
+
+#define WRITE(byte) \
+  ++dst; \
+  if (dst < len) buf[dst - 1] = byte; \
+  else if (dst == len) buf[dst - 1] = '\0'
+
+  if (!name) {
+    WRITE('\0');
+    return 0;
+  }
+
+  /* Implement the transformation as described in the spec:
+   *   1. upper case all letters after an underscore.
+   *   2. remove all underscores.
+   */
+  for (src = 0; name[src]; src++) {
+    if (name[src] == '_') {
+      ucase_next = true;
+      continue;
+    }
+
+    if (ucase_next) {
+      WRITE(toupper(name[src]));
+      ucase_next = false;
+    } else {
+      WRITE(name[src]);
+    }
+  }
+
+  WRITE('\0');
+  return dst;
+
+#undef WRITE
+}
+
+static char* makejsonname(symtab_addctx *ctx, const char* name) {
+  size_t size = getjsonname(name, NULL, 0);
+  char* json_name = symtab_alloc(ctx, size);
+  getjsonname(name, json_name, size);
+  return json_name;
+}
+
+static void symtab_add(symtab_addctx *ctx, const char *name, upb_value v) {
+  if (upb_strtable_lookup(&ctx->symtab->syms, name, NULL)) {
+    symtab_errf(ctx, "duplicate symbol '%s'", name);
+  }
+  upb_alloc *alloc = upb_arena_alloc(ctx->symtab->arena);
+  size_t len = strlen(name);
+  CHK_OOM(upb_strtable_insert3(&ctx->symtab->syms, name, len, v, alloc));
+}
+
+/* Given a symbol and the base symbol inside which it is defined, find the
+ * symbol's definition in t. */
+static const void *symtab_resolve(symtab_addctx *ctx, const upb_fielddef *f,
+                                  const char *base, upb_strview sym,
+                                  upb_deftype_t type) {
+  const upb_strtable *t = &ctx->symtab->syms;
+  if(sym.size == 0) goto notfound;
+  if(sym.data[0] == '.') {
+    /* Symbols starting with '.' are absolute, so we do a single lookup.
+     * Slice to omit the leading '.' */
+    upb_value v;
+    if (!upb_strtable_lookup2(t, sym.data + 1, sym.size - 1, &v)) {
+      goto notfound;
+    }
+
+    const void *ret = unpack_def(v, type);
+    if (!ret) {
+      symtab_errf(ctx, "type mismatch when resolving field %s, name %s",
+                  f->full_name, sym.data);
+    }
+    return ret;
+  } else {
+    /* Remove components from base until we find an entry or run out.
+     * TODO: This branch is totally broken, but currently not used. */
+    (void)base;
+    UPB_ASSERT(false);
+    goto notfound;
+  }
+
+notfound:
+  symtab_errf(ctx, "couldn't resolve name '%s'", sym.data);
+}
+
+static void create_oneofdef(
+    symtab_addctx *ctx, upb_msgdef *m,
+    const google_protobuf_OneofDescriptorProto *oneof_proto) {
+  upb_oneofdef *o;
+  upb_strview name = google_protobuf_OneofDescriptorProto_name(oneof_proto);
+  upb_value v;
+
+  o = (upb_oneofdef*)&m->oneofs[m->oneof_count++];
+  o->parent = m;
+  o->full_name = makefullname(ctx, m->full_name, name);
+  o->field_count = 0;
+  o->synthetic = false;
+
+  v = pack_def(o, UPB_DEFTYPE_ONEOF);
+  symtab_add(ctx, o->full_name, v);
+  CHK_OOM(upb_strtable_insert3(&m->ntof, name.data, name.size, v, ctx->alloc));
+
+  CHK_OOM(upb_inttable_init2(&o->itof, UPB_CTYPE_CONSTPTR, ctx->alloc));
+  CHK_OOM(upb_strtable_init2(&o->ntof, UPB_CTYPE_CONSTPTR, 4, ctx->alloc));
+}
+
+static str_t *newstr(symtab_addctx *ctx, const char *data, size_t len) {
+  str_t *ret = symtab_alloc(ctx, sizeof(*ret) + len);
+  if (!ret) return NULL;
+  ret->len = len;
+  if (len) memcpy(ret->str, data, len);
+  ret->str[len] = '\0';
+  return ret;
+}
+
+static void parse_default(symtab_addctx *ctx, const char *str, size_t len,
+                          upb_fielddef *f) {
+  char *end;
+  char nullz[64];
+  errno = 0;
+
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_UINT64:
+    case UPB_TYPE_DOUBLE:
+    case UPB_TYPE_FLOAT:
+      /* Standard C number parsing functions expect null-terminated strings. */
+      if (len >= sizeof(nullz) - 1) {
+        symtab_errf(ctx, "Default too long: %.*s", (int)len, str);
+      }
+      memcpy(nullz, str, len);
+      nullz[len] = '\0';
+      str = nullz;
+      break;
+    default:
+      break;
+  }
+
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_INT32: {
+      long val = strtol(str, &end, 0);
+      if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.sint = val;
+      break;
+    }
+    case UPB_TYPE_ENUM: {
+      const upb_enumdef *e = f->sub.enumdef;
+      int32_t val;
+      if (!upb_enumdef_ntoi(e, str, len, &val)) {
+        goto invalid;
+      }
+      f->defaultval.sint = val;
+      break;
+    }
+    case UPB_TYPE_INT64: {
+      /* XXX: Need to write our own strtoll, since it's not available in c89. */
+      int64_t val = strtol(str, &end, 0);
+      if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.sint = val;
+      break;
+    }
+    case UPB_TYPE_UINT32: {
+      unsigned long val = strtoul(str, &end, 0);
+      if (val > UINT32_MAX || errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.uint = val;
+      break;
+    }
+    case UPB_TYPE_UINT64: {
+      /* XXX: Need to write our own strtoull, since it's not available in c89. */
+      uint64_t val = strtoul(str, &end, 0);
+      if (val > UINT64_MAX || errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.uint = val;
+      break;
+    }
+    case UPB_TYPE_DOUBLE: {
+      double val = strtod(str, &end);
+      if (errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.dbl = val;
+      break;
+    }
+    case UPB_TYPE_FLOAT: {
+      /* XXX: Need to write our own strtof, since it's not available in c89. */
+      float val = strtod(str, &end);
+      if (errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.flt = val;
+      break;
+    }
+    case UPB_TYPE_BOOL: {
+      if (streql2(str, len, "false")) {
+        f->defaultval.boolean = false;
+      } else if (streql2(str, len, "true")) {
+        f->defaultval.boolean = true;
+      } else {
+      }
+      break;
+    }
+    case UPB_TYPE_STRING:
+      f->defaultval.str = newstr(ctx, str, len);
+      break;
+    case UPB_TYPE_BYTES:
+      /* XXX: need to interpret the C-escaped value. */
+      f->defaultval.str = newstr(ctx, str, len);
+      break;
+    case UPB_TYPE_MESSAGE:
+      /* Should not have a default value. */
+      symtab_errf(ctx, "Message should not have a default (%s)",
+                  upb_fielddef_fullname(f));
+  }
+
+  return;
+
+invalid:
+  symtab_errf(ctx, "Invalid default '%.*s' for field %s", (int)len, str,
+              upb_fielddef_fullname(f));
+}
+
+static void set_default_default(symtab_addctx *ctx, upb_fielddef *f) {
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_ENUM:
+      f->defaultval.sint = 0;
+      break;
+    case UPB_TYPE_UINT64:
+    case UPB_TYPE_UINT32:
+      f->defaultval.uint = 0;
+      break;
+    case UPB_TYPE_DOUBLE:
+    case UPB_TYPE_FLOAT:
+      f->defaultval.dbl = 0;
+      break;
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+      f->defaultval.str = newstr(ctx, NULL, 0);
+      break;
+    case UPB_TYPE_BOOL:
+      f->defaultval.boolean = false;
+      break;
+    case UPB_TYPE_MESSAGE:
+      break;
+  }
+}
+
+static void create_fielddef(
+    symtab_addctx *ctx, const char *prefix, upb_msgdef *m,
+    const google_protobuf_FieldDescriptorProto *field_proto) {
+  upb_alloc *alloc = ctx->alloc;
+  upb_fielddef *f;
+  const google_protobuf_FieldOptions *options;
+  upb_strview name;
+  const char *full_name;
+  const char *json_name;
+  const char *shortname;
+  uint32_t field_number;
+
+  if (!google_protobuf_FieldDescriptorProto_has_name(field_proto)) {
+    symtab_errf(ctx, "field has no name (%s)", upb_msgdef_fullname(m));
+  }
+
+  name = google_protobuf_FieldDescriptorProto_name(field_proto);
+  check_ident(ctx, name, false);
+  full_name = makefullname(ctx, prefix, name);
+  shortname = shortdefname(full_name);
+
+  if (google_protobuf_FieldDescriptorProto_has_json_name(field_proto)) {
+    json_name = strviewdup(
+        ctx, google_protobuf_FieldDescriptorProto_json_name(field_proto));
+  } else {
+    json_name = makejsonname(ctx, shortname);
+  }
+
+  field_number = google_protobuf_FieldDescriptorProto_number(field_proto);
+
+  if (field_number == 0 || field_number > UPB_MAX_FIELDNUMBER) {
+    symtab_errf(ctx, "invalid field number (%u)", field_number);
+  }
+
+  if (m) {
+    /* direct message field. */
+    upb_value v, field_v, json_v;
+    size_t json_size;
+
+    f = (upb_fielddef*)&m->fields[m->field_count++];
+    f->msgdef = m;
+    f->is_extension_ = false;
+
+    if (upb_strtable_lookup(&m->ntof, shortname, NULL)) {
+      symtab_errf(ctx, "duplicate field name (%s)", shortname);
+    }
+
+    if (upb_strtable_lookup(&m->ntof, json_name, NULL)) {
+      symtab_errf(ctx, "duplicate json_name (%s)", json_name);
+    }
+
+    if (upb_inttable_lookup(&m->itof, field_number, NULL)) {
+      symtab_errf(ctx, "duplicate field number (%u)", field_number);
+    }
+
+    field_v = pack_def(f, UPB_DEFTYPE_FIELD);
+    json_v = pack_def(f, UPB_DEFTYPE_FIELD_JSONNAME);
+    v = upb_value_constptr(f);
+    json_size = strlen(json_name);
+
+    CHK_OOM(
+        upb_strtable_insert3(&m->ntof, name.data, name.size, field_v, alloc));
+    CHK_OOM(upb_inttable_insert2(&m->itof, field_number, v, alloc));
+
+    if (strcmp(shortname, json_name) != 0) {
+      upb_strtable_insert3(&m->ntof, json_name, json_size, json_v, alloc);
+    }
+
+    if (ctx->layouts) {
+      const upb_msglayout_field *fields = m->layout->fields;
+      int count = m->layout->field_count;
+      bool found = false;
+      int i;
+      for (i = 0; i < count; i++) {
+        if (fields[i].number == field_number) {
+          f->layout_index = i;
+          found = true;
+          break;
+        }
+      }
+      UPB_ASSERT(found);
+    }
+  } else {
+    /* extension field. */
+    f = (upb_fielddef*)&ctx->file->exts[ctx->file->ext_count++];
+    f->is_extension_ = true;
+    symtab_add(ctx, full_name, pack_def(f, UPB_DEFTYPE_FIELD));
+  }
+
+  f->full_name = full_name;
+  f->json_name = json_name;
+  f->file = ctx->file;
+  f->type_ = (int)google_protobuf_FieldDescriptorProto_type(field_proto);
+  f->label_ = (int)google_protobuf_FieldDescriptorProto_label(field_proto);
+  f->number_ = field_number;
+  f->oneof = NULL;
+  f->proto3_optional_ =
+      google_protobuf_FieldDescriptorProto_proto3_optional(field_proto);
+
+  /* We can't resolve the subdef or (in the case of extensions) the containing
+   * message yet, because it may not have been defined yet.  We stash a pointer
+   * to the field_proto until later when we can properly resolve it. */
+  f->sub.unresolved = field_proto;
+
+  if (f->label_ == UPB_LABEL_REQUIRED && f->file->syntax == UPB_SYNTAX_PROTO3) {
+    symtab_errf(ctx, "proto3 fields cannot be required (%s)", f->full_name);
+  }
+
+  if (google_protobuf_FieldDescriptorProto_has_oneof_index(field_proto)) {
+    int oneof_index =
+        google_protobuf_FieldDescriptorProto_oneof_index(field_proto);
+    upb_oneofdef *oneof;
+    upb_value v = upb_value_constptr(f);
+
+    if (upb_fielddef_label(f) != UPB_LABEL_OPTIONAL) {
+      symtab_errf(ctx, "fields in oneof must have OPTIONAL label (%s)",
+                  f->full_name);
+    }
+
+    if (!m) {
+      symtab_errf(ctx, "oneof_index provided for extension field (%s)",
+                  f->full_name);
+    }
+
+    if (oneof_index >= m->oneof_count) {
+      symtab_errf(ctx, "oneof_index out of range (%s)", f->full_name);
+    }
+
+    oneof = (upb_oneofdef*)&m->oneofs[oneof_index];
+    f->oneof = oneof;
+
+    oneof->field_count++;
+    if (f->proto3_optional_) {
+      oneof->synthetic = true;
+    }
+    CHK_OOM(upb_inttable_insert2(&oneof->itof, f->number_, v, alloc));
+    CHK_OOM(upb_strtable_insert3(&oneof->ntof, name.data, name.size, v, alloc));
+  } else {
+    f->oneof = NULL;
+    if (f->proto3_optional_) {
+      symtab_errf(ctx, "field with proto3_optional was not in a oneof (%s)",
+                  f->full_name);
+    }
+  }
+
+  options = google_protobuf_FieldDescriptorProto_has_options(field_proto) ?
+    google_protobuf_FieldDescriptorProto_options(field_proto) : NULL;
+
+  if (options && google_protobuf_FieldOptions_has_packed(options)) {
+    f->packed_ = google_protobuf_FieldOptions_packed(options);
+  } else {
+    /* Repeated fields default to packed for proto3 only. */
+    f->packed_ = upb_fielddef_isprimitive(f) &&
+        f->label_ == UPB_LABEL_REPEATED && f->file->syntax == UPB_SYNTAX_PROTO3;
+  }
+
+  if (options) {
+    f->lazy_ = google_protobuf_FieldOptions_lazy(options);
+  } else {
+    f->lazy_ = false;
+  }
+}
+
+static void create_enumdef(
+    symtab_addctx *ctx, const char *prefix,
+    const google_protobuf_EnumDescriptorProto *enum_proto) {
+  upb_enumdef *e;
+  const google_protobuf_EnumValueDescriptorProto *const *values;
+  upb_strview name;
+  size_t i, n;
+
+  name = google_protobuf_EnumDescriptorProto_name(enum_proto);
+  check_ident(ctx, name, false);
+
+  e = (upb_enumdef*)&ctx->file->enums[ctx->file->enum_count++];
+  e->full_name = makefullname(ctx, prefix, name);
+  symtab_add(ctx, e->full_name, pack_def(e, UPB_DEFTYPE_ENUM));
+
+  values = google_protobuf_EnumDescriptorProto_value(enum_proto, &n);
+  CHK_OOM(upb_strtable_init2(&e->ntoi, UPB_CTYPE_INT32, n, ctx->alloc));
+  CHK_OOM(upb_inttable_init2(&e->iton, UPB_CTYPE_CSTR, ctx->alloc));
+
+  e->file = ctx->file;
+  e->defaultval = 0;
+
+  if (n == 0) {
+    symtab_errf(ctx, "enums must contain at least one value (%s)",
+                e->full_name);
+  }
+
+  for (i = 0; i < n; i++) {
+    const google_protobuf_EnumValueDescriptorProto *value = values[i];
+    upb_strview name = google_protobuf_EnumValueDescriptorProto_name(value);
+    char *name2 = strviewdup(ctx, name);
+    int32_t num = google_protobuf_EnumValueDescriptorProto_number(value);
+    upb_value v = upb_value_int32(num);
+
+    if (i == 0 && e->file->syntax == UPB_SYNTAX_PROTO3 && num != 0) {
+      symtab_errf(ctx, "for proto3, the first enum value must be zero (%s)",
+                  e->full_name);
+    }
+
+    if (upb_strtable_lookup(&e->ntoi, name2, NULL)) {
+      symtab_errf(ctx, "duplicate enum label '%s'", name2);
+    }
+
+    CHK_OOM(name2)
+    CHK_OOM(
+        upb_strtable_insert3(&e->ntoi, name2, strlen(name2), v, ctx->alloc));
+
+    if (!upb_inttable_lookup(&e->iton, num, NULL)) {
+      upb_value v = upb_value_cstr(name2);
+      CHK_OOM(upb_inttable_insert2(&e->iton, num, v, ctx->alloc));
+    }
+  }
+
+  upb_inttable_compact2(&e->iton, ctx->alloc);
+}
+
+static void create_msgdef(symtab_addctx *ctx, const char *prefix,
+                          const google_protobuf_DescriptorProto *msg_proto) {
+  upb_msgdef *m;
+  const google_protobuf_MessageOptions *options;
+  const google_protobuf_OneofDescriptorProto *const *oneofs;
+  const google_protobuf_FieldDescriptorProto *const *fields;
+  const google_protobuf_EnumDescriptorProto *const *enums;
+  const google_protobuf_DescriptorProto *const *msgs;
+  size_t i, n_oneof, n_field, n;
+  upb_strview name;
+
+  name = google_protobuf_DescriptorProto_name(msg_proto);
+  check_ident(ctx, name, false);
+
+  m = (upb_msgdef*)&ctx->file->msgs[ctx->file->msg_count++];
+  m->full_name = makefullname(ctx, prefix, name);
+  symtab_add(ctx, m->full_name, pack_def(m, UPB_DEFTYPE_MSG));
+
+  oneofs = google_protobuf_DescriptorProto_oneof_decl(msg_proto, &n_oneof);
+  fields = google_protobuf_DescriptorProto_field(msg_proto, &n_field);
+
+  CHK_OOM(upb_inttable_init2(&m->itof, UPB_CTYPE_CONSTPTR, ctx->alloc));
+  CHK_OOM(upb_strtable_init2(&m->ntof, UPB_CTYPE_CONSTPTR, n_oneof + n_field,
+                             ctx->alloc));
+
+  m->file = ctx->file;
+  m->map_entry = false;
+
+  options = google_protobuf_DescriptorProto_options(msg_proto);
+
+  if (options) {
+    m->map_entry = google_protobuf_MessageOptions_map_entry(options);
+  }
+
+  if (ctx->layouts) {
+    m->layout = *ctx->layouts;
+    ctx->layouts++;
+  } else {
+    /* Allocate now (to allow cross-linking), populate later. */
+    m->layout = symtab_alloc(
+        ctx, sizeof(*m->layout) + sizeof(_upb_fasttable_entry));
+  }
+
+  m->oneof_count = 0;
+  m->oneofs = symtab_alloc(ctx, sizeof(*m->oneofs) * n_oneof);
+  for (i = 0; i < n_oneof; i++) {
+    create_oneofdef(ctx, m, oneofs[i]);
+  }
+
+  m->field_count = 0;
+  m->fields = symtab_alloc(ctx, sizeof(*m->fields) * n_field);
+  for (i = 0; i < n_field; i++) {
+    create_fielddef(ctx, m->full_name, m, fields[i]);
+  }
+
+  assign_msg_indices(ctx, m);
+  finalize_oneofs(ctx, m);
+  assign_msg_wellknowntype(m);
+  upb_inttable_compact2(&m->itof, ctx->alloc);
+
+  /* This message is built.  Now build nested messages and enums. */
+
+  enums = google_protobuf_DescriptorProto_enum_type(msg_proto, &n);
+  for (i = 0; i < n; i++) {
+    create_enumdef(ctx, m->full_name, enums[i]);
+  }
+
+  msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
+  for (i = 0; i < n; i++) {
+    create_msgdef(ctx, m->full_name, msgs[i]);
+  }
+}
+
+static void count_types_in_msg(const google_protobuf_DescriptorProto *msg_proto,
+                               upb_filedef *file) {
+  const google_protobuf_DescriptorProto *const *msgs;
+  size_t i, n;
+
+  file->msg_count++;
+
+  msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
+  for (i = 0; i < n; i++) {
+    count_types_in_msg(msgs[i], file);
+  }
+
+  google_protobuf_DescriptorProto_enum_type(msg_proto, &n);
+  file->enum_count += n;
+
+  google_protobuf_DescriptorProto_extension(msg_proto, &n);
+  file->ext_count += n;
+}
+
+static void count_types_in_file(
+    const google_protobuf_FileDescriptorProto *file_proto,
+    upb_filedef *file) {
+  const google_protobuf_DescriptorProto *const *msgs;
+  size_t i, n;
+
+  msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
+  for (i = 0; i < n; i++) {
+    count_types_in_msg(msgs[i], file);
+  }
+
+  google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
+  file->enum_count += n;
+
+  google_protobuf_FileDescriptorProto_extension(file_proto, &n);
+  file->ext_count += n;
+}
+
+static void resolve_fielddef(symtab_addctx *ctx, const char *prefix,
+                             upb_fielddef *f) {
+  upb_strview name;
+  const google_protobuf_FieldDescriptorProto *field_proto = f->sub.unresolved;
+
+  if (f->is_extension_) {
+    if (!google_protobuf_FieldDescriptorProto_has_extendee(field_proto)) {
+      symtab_errf(ctx, "extension for field '%s' had no extendee",
+                  f->full_name);
+    }
+
+    name = google_protobuf_FieldDescriptorProto_extendee(field_proto);
+    f->msgdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_MSG);
+  }
+
+  if ((upb_fielddef_issubmsg(f) || f->type_ == UPB_DESCRIPTOR_TYPE_ENUM) &&
+      !google_protobuf_FieldDescriptorProto_has_type_name(field_proto)) {
+    symtab_errf(ctx, "field '%s' is missing type name", f->full_name);
+  }
+
+  name = google_protobuf_FieldDescriptorProto_type_name(field_proto);
+
+  if (upb_fielddef_issubmsg(f)) {
+    f->sub.msgdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_MSG);
+  } else if (f->type_ == UPB_DESCRIPTOR_TYPE_ENUM) {
+    f->sub.enumdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_ENUM);
+  }
+
+  /* Have to delay resolving of the default value until now because of the enum
+   * case, since enum defaults are specified with a label. */
+  if (google_protobuf_FieldDescriptorProto_has_default_value(field_proto)) {
+    upb_strview defaultval =
+        google_protobuf_FieldDescriptorProto_default_value(field_proto);
+
+    if (f->file->syntax == UPB_SYNTAX_PROTO3) {
+      symtab_errf(ctx, "proto3 fields cannot have explicit defaults (%s)",
+                  f->full_name);
+    }
+
+    if (upb_fielddef_issubmsg(f)) {
+      symtab_errf(ctx, "message fields cannot have explicit defaults (%s)",
+                  f->full_name);
+    }
+
+    parse_default(ctx, defaultval.data, defaultval.size, f);
+  } else {
+    set_default_default(ctx, f);
+  }
+}
+
+static void build_filedef(
+    symtab_addctx *ctx, upb_filedef *file,
+    const google_protobuf_FileDescriptorProto *file_proto) {
+  const google_protobuf_FileOptions *file_options_proto;
+  const google_protobuf_DescriptorProto *const *msgs;
+  const google_protobuf_EnumDescriptorProto *const *enums;
+  const google_protobuf_FieldDescriptorProto *const *exts;
+  const upb_strview* strs;
+  size_t i, n;
+
+  count_types_in_file(file_proto, file);
+
+  file->msgs = symtab_alloc(ctx, sizeof(*file->msgs) * file->msg_count);
+  file->enums = symtab_alloc(ctx, sizeof(*file->enums) * file->enum_count);
+  file->exts = symtab_alloc(ctx, sizeof(*file->exts) * file->ext_count);
+
+  /* We increment these as defs are added. */
+  file->msg_count = 0;
+  file->enum_count = 0;
+  file->ext_count = 0;
+
+  if (!google_protobuf_FileDescriptorProto_has_name(file_proto)) {
+    symtab_errf(ctx, "File has no name");
+  }
+
+  file->name =
+      strviewdup(ctx, google_protobuf_FileDescriptorProto_name(file_proto));
+  file->phpprefix = NULL;
+  file->phpnamespace = NULL;
+
+  if (google_protobuf_FileDescriptorProto_has_package(file_proto)) {
+    upb_strview package =
+        google_protobuf_FileDescriptorProto_package(file_proto);
+    check_ident(ctx, package, true);
+    file->package = strviewdup(ctx, package);
+  } else {
+    file->package = NULL;
+  }
+
+  if (google_protobuf_FileDescriptorProto_has_syntax(file_proto)) {
+    upb_strview syntax =
+        google_protobuf_FileDescriptorProto_syntax(file_proto);
+
+    if (streql_view(syntax, "proto2")) {
+      file->syntax = UPB_SYNTAX_PROTO2;
+    } else if (streql_view(syntax, "proto3")) {
+      file->syntax = UPB_SYNTAX_PROTO3;
+    } else {
+      symtab_errf(ctx, "Invalid syntax '" UPB_STRVIEW_FORMAT "'",
+                  UPB_STRVIEW_ARGS(syntax));
+    }
+  } else {
+    file->syntax = UPB_SYNTAX_PROTO2;
+  }
+
+  /* Read options. */
+  file_options_proto = google_protobuf_FileDescriptorProto_options(file_proto);
+  if (file_options_proto) {
+    if (google_protobuf_FileOptions_has_php_class_prefix(file_options_proto)) {
+      file->phpprefix = strviewdup(
+          ctx,
+          google_protobuf_FileOptions_php_class_prefix(file_options_proto));
+    }
+    if (google_protobuf_FileOptions_has_php_namespace(file_options_proto)) {
+      file->phpnamespace = strviewdup(
+          ctx, google_protobuf_FileOptions_php_namespace(file_options_proto));
+    }
+  }
+
+  /* Verify dependencies. */
+  strs = google_protobuf_FileDescriptorProto_dependency(file_proto, &n);
+  file->deps = symtab_alloc(ctx, sizeof(*file->deps) * n);
+
+  for (i = 0; i < n; i++) {
+    upb_strview dep_name = strs[i];
+    upb_value v;
+    if (!upb_strtable_lookup2(&ctx->symtab->files, dep_name.data,
+                              dep_name.size, &v)) {
+      symtab_errf(ctx,
+                  "Depends on file '" UPB_STRVIEW_FORMAT
+                  "', but it has not been loaded",
+                  UPB_STRVIEW_ARGS(dep_name));
+    }
+    file->deps[i] = upb_value_getconstptr(v);
+  }
+
+  /* Create messages. */
+  msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
+  for (i = 0; i < n; i++) {
+    create_msgdef(ctx, file->package, msgs[i]);
+  }
+
+  /* Create enums. */
+  enums = google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
+  for (i = 0; i < n; i++) {
+    create_enumdef(ctx, file->package, enums[i]);
+  }
+
+  /* Create extensions. */
+  exts = google_protobuf_FileDescriptorProto_extension(file_proto, &n);
+  file->exts = symtab_alloc(ctx, sizeof(*file->exts) * n);
+  for (i = 0; i < n; i++) {
+    create_fielddef(ctx, file->package, NULL, exts[i]);
+  }
+
+  /* Now that all names are in the table, build layouts and resolve refs. */
+  for (i = 0; i < (size_t)file->ext_count; i++) {
+    resolve_fielddef(ctx, file->package, (upb_fielddef*)&file->exts[i]);
+  }
+
+  for (i = 0; i < (size_t)file->msg_count; i++) {
+    const upb_msgdef *m = &file->msgs[i];
+    int j;
+    for (j = 0; j < m->field_count; j++) {
+      resolve_fielddef(ctx, m->full_name, (upb_fielddef*)&m->fields[j]);
+    }
+  }
+
+  if (!ctx->layouts) {
+    for (i = 0; i < (size_t)file->msg_count; i++) {
+      const upb_msgdef *m = &file->msgs[i];
+      make_layout(ctx, m);
+    }
+  }
+}
+
+static void remove_filedef(upb_symtab *s, upb_filedef *file) {
+  upb_alloc *alloc = upb_arena_alloc(s->arena);
+  int i;
+  for (i = 0; i < file->msg_count; i++) {
+    const char *name = file->msgs[i].full_name;
+    upb_strtable_remove3(&s->syms, name, strlen(name), NULL, alloc);
+  }
+  for (i = 0; i < file->enum_count; i++) {
+    const char *name = file->enums[i].full_name;
+    upb_strtable_remove3(&s->syms, name, strlen(name), NULL, alloc);
+  }
+  for (i = 0; i < file->ext_count; i++) {
+    const char *name = file->exts[i].full_name;
+    upb_strtable_remove3(&s->syms, name, strlen(name), NULL, alloc);
+  }
+}
+
+static const upb_filedef *_upb_symtab_addfile(
+    upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto,
+    const upb_msglayout **layouts, upb_status *status) {
+  upb_arena *file_arena = upb_arena_new();
+  upb_filedef *file;
+  symtab_addctx ctx;
+
+  if (!file_arena) return NULL;
+
+  file = upb_arena_malloc(file_arena, sizeof(*file));
+  if (!file) goto done;
+
+  ctx.file = file;
+  ctx.symtab = s;
+  ctx.file_arena = file_arena;
+  ctx.alloc = upb_arena_alloc(file_arena);
+  ctx.layouts = layouts;
+  ctx.status = status;
+
+  file->msg_count = 0;
+  file->enum_count = 0;
+  file->ext_count = 0;
+  file->symtab = s;
+
+  if (UPB_UNLIKELY(UPB_SETJMP(ctx.err))) {
+    UPB_ASSERT(!upb_ok(status));
+    remove_filedef(s, file);
+    file = NULL;
+  } else {
+    build_filedef(&ctx, file, file_proto);
+    upb_strtable_insert3(&s->files, file->name, strlen(file->name),
+                         upb_value_constptr(file), ctx.alloc);
+    UPB_ASSERT(upb_ok(status));
+    upb_arena_fuse(s->arena, file_arena);
+  }
+
+done:
+  upb_arena_free(file_arena);
+  return file;
+}
+
+const upb_filedef *upb_symtab_addfile(
+    upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto,
+    upb_status *status) {
+  return _upb_symtab_addfile(s, file_proto, NULL, status);
+}
+
+/* Include here since we want most of this file to be stdio-free. */
+#include <stdio.h>
+
+bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init) {
+  /* Since this function should never fail (it would indicate a bug in upb) we
+   * print errors to stderr instead of returning error status to the user. */
+  upb_def_init **deps = init->deps;
+  google_protobuf_FileDescriptorProto *file;
+  upb_arena *arena;
+  upb_status status;
+
+  upb_status_clear(&status);
+
+  if (upb_strtable_lookup(&s->files, init->filename, NULL)) {
+    return true;
+  }
+
+  arena = upb_arena_new();
+
+  for (; *deps; deps++) {
+    if (!_upb_symtab_loaddefinit(s, *deps)) goto err;
+  }
+
+  file = google_protobuf_FileDescriptorProto_parse_ex(
+      init->descriptor.data, init->descriptor.size, arena, UPB_DECODE_ALIAS);
+  s->bytes_loaded += init->descriptor.size;
+
+  if (!file) {
+    upb_status_seterrf(
+        &status,
+        "Failed to parse compiled-in descriptor for file '%s'. This should "
+        "never happen.",
+        init->filename);
+    goto err;
+  }
+
+  if (!_upb_symtab_addfile(s, file, init->layouts, &status)) goto err;
+
+  upb_arena_free(arena);
+  return true;
+
+err:
+  fprintf(stderr, "Error loading compiled-in descriptor: %s\n",
+          upb_status_errmsg(&status));
+  upb_arena_free(arena);
+  return false;
+}
+
+size_t _upb_symtab_bytesloaded(const upb_symtab *s) {
+  return s->bytes_loaded;
+}
+
+upb_arena *_upb_symtab_arena(const upb_symtab *s) {
+  return s->arena;
+}
+
+#undef CHK_OOM
+
+
+#include <string.h>
+
+
+static size_t get_field_size(const upb_msglayout_field *f) {
+  static unsigned char sizes[] = {
+    0,/* 0 */
+    8, /* UPB_DESCRIPTOR_TYPE_DOUBLE */
+    4, /* UPB_DESCRIPTOR_TYPE_FLOAT */
+    8, /* UPB_DESCRIPTOR_TYPE_INT64 */
+    8, /* UPB_DESCRIPTOR_TYPE_UINT64 */
+    4, /* UPB_DESCRIPTOR_TYPE_INT32 */
+    8, /* UPB_DESCRIPTOR_TYPE_FIXED64 */
+    4, /* UPB_DESCRIPTOR_TYPE_FIXED32 */
+    1, /* UPB_DESCRIPTOR_TYPE_BOOL */
+    sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_STRING */
+    sizeof(void*), /* UPB_DESCRIPTOR_TYPE_GROUP */
+    sizeof(void*), /* UPB_DESCRIPTOR_TYPE_MESSAGE */
+    sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_BYTES */
+    4, /* UPB_DESCRIPTOR_TYPE_UINT32 */
+    4, /* UPB_DESCRIPTOR_TYPE_ENUM */
+    4, /* UPB_DESCRIPTOR_TYPE_SFIXED32 */
+    8, /* UPB_DESCRIPTOR_TYPE_SFIXED64 */
+    4, /* UPB_DESCRIPTOR_TYPE_SINT32 */
+    8, /* UPB_DESCRIPTOR_TYPE_SINT64 */
+  };
+  return _upb_repeated_or_map(f) ? sizeof(void *) : sizes[f->descriptortype];
+}
+
+/* Strings/bytes are special-cased in maps. */
+static char _upb_fieldtype_to_mapsize[12] = {
+  0,
+  1,  /* UPB_TYPE_BOOL */
+  4,  /* UPB_TYPE_FLOAT */
+  4,  /* UPB_TYPE_INT32 */
+  4,  /* UPB_TYPE_UINT32 */
+  4,  /* UPB_TYPE_ENUM */
+  sizeof(void*),  /* UPB_TYPE_MESSAGE */
+  8,  /* UPB_TYPE_DOUBLE */
+  8,  /* UPB_TYPE_INT64 */
+  8,  /* UPB_TYPE_UINT64 */
+  0,  /* UPB_TYPE_STRING */
+  0,  /* UPB_TYPE_BYTES */
+};
+
+static const char _upb_fieldtype_to_sizelg2[12] = {
+  0,
+  0,  /* UPB_TYPE_BOOL */
+  2,  /* UPB_TYPE_FLOAT */
+  2,  /* UPB_TYPE_INT32 */
+  2,  /* UPB_TYPE_UINT32 */
+  2,  /* UPB_TYPE_ENUM */
+  UPB_SIZE(2, 3),  /* UPB_TYPE_MESSAGE */
+  3,  /* UPB_TYPE_DOUBLE */
+  3,  /* UPB_TYPE_INT64 */
+  3,  /* UPB_TYPE_UINT64 */
+  UPB_SIZE(3, 4),  /* UPB_TYPE_STRING */
+  UPB_SIZE(3, 4),  /* UPB_TYPE_BYTES */
+};
+
+/** upb_msg *******************************************************************/
+
+upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a) {
+  return _upb_msg_new(upb_msgdef_layout(m), a);
+}
+
+static bool in_oneof(const upb_msglayout_field *field) {
+  return field->presence < 0;
+}
+
+static upb_msgval _upb_msg_getraw(const upb_msg *msg, const upb_fielddef *f) {
+  const upb_msglayout_field *field = upb_fielddef_layout(f);
+  const char *mem = UPB_PTR_AT(msg, field->offset, char);
+  upb_msgval val = {0};
+  memcpy(&val, mem, get_field_size(field));
+  return val;
+}
+
+bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f) {
+  const upb_msglayout_field *field = upb_fielddef_layout(f);
+  if (in_oneof(field)) {
+    return _upb_getoneofcase_field(msg, field) == field->number;
+  } else if (field->presence > 0) {
+    return _upb_hasbit_field(msg, field);
+  } else {
+    UPB_ASSERT(field->descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE ||
+               field->descriptortype == UPB_DESCRIPTOR_TYPE_GROUP);
+    return _upb_msg_getraw(msg, f).msg_val != NULL;
+  }
+}
+
+const upb_fielddef *upb_msg_whichoneof(const upb_msg *msg,
+                                       const upb_oneofdef *o) {
+  const upb_fielddef *f = upb_oneofdef_field(o, 0);
+  if (upb_oneofdef_issynthetic(o)) {
+    UPB_ASSERT(upb_oneofdef_fieldcount(o) == 1);
+    return upb_msg_has(msg, f) ? f : NULL;
+  } else {
+    const upb_msglayout_field *field = upb_fielddef_layout(f);
+    uint32_t oneof_case = _upb_getoneofcase_field(msg, field);
+    f = oneof_case ? upb_oneofdef_itof(o, oneof_case) : NULL;
+    UPB_ASSERT((f != NULL) == (oneof_case != 0));
+    return f;
+  }
+}
+
+upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f) {
+  if (!upb_fielddef_haspresence(f) || upb_msg_has(msg, f)) {
+    return _upb_msg_getraw(msg, f);
+  } else {
+    /* TODO(haberman): change upb_fielddef to not require this switch(). */
+    upb_msgval val = {0};
+    switch (upb_fielddef_type(f)) {
+      case UPB_TYPE_INT32:
+      case UPB_TYPE_ENUM:
+        val.int32_val = upb_fielddef_defaultint32(f);
+        break;
+      case UPB_TYPE_INT64:
+        val.int64_val = upb_fielddef_defaultint64(f);
+        break;
+      case UPB_TYPE_UINT32:
+        val.uint32_val = upb_fielddef_defaultuint32(f);
+        break;
+      case UPB_TYPE_UINT64:
+        val.uint64_val = upb_fielddef_defaultuint64(f);
+        break;
+      case UPB_TYPE_FLOAT:
+        val.float_val = upb_fielddef_defaultfloat(f);
+        break;
+      case UPB_TYPE_DOUBLE:
+        val.double_val = upb_fielddef_defaultdouble(f);
+        break;
+      case UPB_TYPE_BOOL:
+        val.bool_val = upb_fielddef_defaultbool(f);
+        break;
+      case UPB_TYPE_STRING:
+      case UPB_TYPE_BYTES:
+        val.str_val.data = upb_fielddef_defaultstr(f, &val.str_val.size);
+        break;
+      case UPB_TYPE_MESSAGE:
+        val.msg_val = NULL;
+        break;
+    }
+    return val;
+  }
+}
+
+upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f,
+                              upb_arena *a) {
+  const upb_msglayout_field *field = upb_fielddef_layout(f);
+  upb_mutmsgval ret;
+  char *mem = UPB_PTR_AT(msg, field->offset, char);
+  bool wrong_oneof =
+      in_oneof(field) && _upb_getoneofcase_field(msg, field) != field->number;
+
+  memcpy(&ret, mem, sizeof(void*));
+
+  if (a && (!ret.msg || wrong_oneof)) {
+    if (upb_fielddef_ismap(f)) {
+      const upb_msgdef *entry = upb_fielddef_msgsubdef(f);
+      const upb_fielddef *key = upb_msgdef_itof(entry, UPB_MAPENTRY_KEY);
+      const upb_fielddef *value = upb_msgdef_itof(entry, UPB_MAPENTRY_VALUE);
+      ret.map = upb_map_new(a, upb_fielddef_type(key), upb_fielddef_type(value));
+    } else if (upb_fielddef_isseq(f)) {
+      ret.array = upb_array_new(a, upb_fielddef_type(f));
+    } else {
+      UPB_ASSERT(upb_fielddef_issubmsg(f));
+      ret.msg = upb_msg_new(upb_fielddef_msgsubdef(f), a);
+    }
+
+    memcpy(mem, &ret, sizeof(void*));
+
+    if (wrong_oneof) {
+      *_upb_oneofcase_field(msg, field) = field->number;
+    } else if (field->presence > 0) {
+      _upb_sethas_field(msg, field);
+    }
+  }
+  return ret;
+}
+
+void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val,
+                 upb_arena *a) {
+  const upb_msglayout_field *field = upb_fielddef_layout(f);
+  char *mem = UPB_PTR_AT(msg, field->offset, char);
+  UPB_UNUSED(a);  /* We reserve the right to make set insert into a map. */
+  memcpy(mem, &val, get_field_size(field));
+  if (field->presence > 0) {
+    _upb_sethas_field(msg, field);
+  } else if (in_oneof(field)) {
+    *_upb_oneofcase_field(msg, field) = field->number;
+  }
+}
+
+void upb_msg_clearfield(upb_msg *msg, const upb_fielddef *f) {
+  const upb_msglayout_field *field = upb_fielddef_layout(f);
+  char *mem = UPB_PTR_AT(msg, field->offset, char);
+
+  if (field->presence > 0) {
+    _upb_clearhas_field(msg, field);
+  } else if (in_oneof(field)) {
+    uint32_t *oneof_case = _upb_oneofcase_field(msg, field);
+    if (*oneof_case != field->number) return;
+    *oneof_case = 0;
+  }
+
+  memset(mem, 0, get_field_size(field));
+}
+
+void upb_msg_clear(upb_msg *msg, const upb_msgdef *m) {
+  _upb_msg_clear(msg, upb_msgdef_layout(m));
+}
+
+bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m,
+                  const upb_symtab *ext_pool, const upb_fielddef **out_f,
+                  upb_msgval *out_val, size_t *iter) {
+  int i = *iter;
+  int n = upb_msgdef_fieldcount(m);
+  const upb_msgval zero = {0};
+  UPB_UNUSED(ext_pool);
+  while (++i < n) {
+    const upb_fielddef *f = upb_msgdef_field(m, i);
+    upb_msgval val = _upb_msg_getraw(msg, f);
+
+    /* Skip field if unset or empty. */
+    if (upb_fielddef_haspresence(f)) {
+      if (!upb_msg_has(msg, f)) continue;
+    } else {
+      upb_msgval test = val;
+      if (upb_fielddef_isstring(f) && !upb_fielddef_isseq(f)) {
+        /* Clear string pointer, only size matters (ptr could be non-NULL). */
+        test.str_val.data = NULL;
+      }
+      /* Continue if NULL or 0. */
+      if (memcmp(&test, &zero, sizeof(test)) == 0) continue;
+
+      /* Continue on empty array or map. */
+      if (upb_fielddef_ismap(f)) {
+        if (upb_map_size(test.map_val) == 0) continue;
+      } else if (upb_fielddef_isseq(f)) {
+        if (upb_array_size(test.array_val) == 0) continue;
+      }
+    }
+
+    *out_val = val;
+    *out_f = f;
+    *iter = i;
+    return true;
+  }
+  *iter = i;
+  return false;
+}
+
+bool _upb_msg_discardunknown(upb_msg *msg, const upb_msgdef *m, int depth) {
+  size_t iter = UPB_MSG_BEGIN;
+  const upb_fielddef *f;
+  upb_msgval val;
+  bool ret = true;
+
+  if (--depth == 0) return false;
+
+  _upb_msg_discardunknown_shallow(msg);
+
+  while (upb_msg_next(msg, m, NULL /*ext_pool*/, &f, &val, &iter)) {
+    const upb_msgdef *subm = upb_fielddef_msgsubdef(f);
+    if (!subm) continue;
+    if (upb_fielddef_ismap(f)) {
+      const upb_fielddef *val_f = upb_msgdef_itof(subm, 2);
+      const upb_msgdef *val_m = upb_fielddef_msgsubdef(val_f);
+      upb_map *map = (upb_map*)val.map_val;
+      size_t iter = UPB_MAP_BEGIN;
+
+      if (!val_m) continue;
+
+      while (upb_mapiter_next(map, &iter)) {
+        upb_msgval map_val = upb_mapiter_value(map, iter);
+        if (!_upb_msg_discardunknown((upb_msg*)map_val.msg_val, val_m, depth)) {
+          ret = false;
+        }
+      }
+    } else if (upb_fielddef_isseq(f)) {
+      const upb_array *arr = val.array_val;
+      size_t i, n = upb_array_size(arr);
+      for (i = 0; i < n; i++) {
+        upb_msgval elem = upb_array_get(arr, i);
+        if (!_upb_msg_discardunknown((upb_msg*)elem.msg_val, subm, depth)) {
+          ret = false;
+        }
+      }
+    } else {
+      if (!_upb_msg_discardunknown((upb_msg*)val.msg_val, subm, depth)) {
+        ret = false;
+      }
+    }
+  }
+
+  return ret;
+}
+
+bool upb_msg_discardunknown(upb_msg *msg, const upb_msgdef *m, int maxdepth) {
+  return _upb_msg_discardunknown(msg, m, maxdepth);
+}
+
+/** upb_array *****************************************************************/
+
+upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type) {
+  return _upb_array_new(a, 4, _upb_fieldtype_to_sizelg2[type]);
+}
+
+size_t upb_array_size(const upb_array *arr) {
+  return arr->len;
+}
+
+upb_msgval upb_array_get(const upb_array *arr, size_t i) {
+  upb_msgval ret;
+  const char* data = _upb_array_constptr(arr);
+  int lg2 = arr->data & 7;
+  UPB_ASSERT(i < arr->len);
+  memcpy(&ret, data + (i << lg2), 1 << lg2);
+  return ret;
+}
+
+void upb_array_set(upb_array *arr, size_t i, upb_msgval val) {
+  char* data = _upb_array_ptr(arr);
+  int lg2 = arr->data & 7;
+  UPB_ASSERT(i < arr->len);
+  memcpy(data + (i << lg2), &val, 1 << lg2);
+}
+
+bool upb_array_append(upb_array *arr, upb_msgval val, upb_arena *arena) {
+  if (!_upb_array_realloc(arr, arr->len + 1, arena)) {
+    return false;
+  }
+  arr->len++;
+  upb_array_set(arr, arr->len - 1, val);
+  return true;
+}
+
+bool upb_array_resize(upb_array *arr, size_t size, upb_arena *arena) {
+  return _upb_array_resize(arr, size, arena);
+}
+
+/** upb_map *******************************************************************/
+
+upb_map *upb_map_new(upb_arena *a, upb_fieldtype_t key_type,
+                     upb_fieldtype_t value_type) {
+  return _upb_map_new(a, _upb_fieldtype_to_mapsize[key_type],
+                      _upb_fieldtype_to_mapsize[value_type]);
+}
+
+size_t upb_map_size(const upb_map *map) {
+  return _upb_map_size(map);
+}
+
+bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val) {
+  return _upb_map_get(map, &key, map->key_size, val, map->val_size);
+}
+
+void upb_map_clear(upb_map *map) {
+  _upb_map_clear(map);
+}
+
+bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val,
+                 upb_arena *arena) {
+  return _upb_map_set(map, &key, map->key_size, &val, map->val_size, arena);
+}
+
+bool upb_map_delete(upb_map *map, upb_msgval key) {
+  return _upb_map_delete(map, &key, map->key_size);
+}
+
+bool upb_mapiter_next(const upb_map *map, size_t *iter) {
+  return _upb_map_next(map, iter);
+}
+
+bool upb_mapiter_done(const upb_map *map, size_t iter) {
+  upb_strtable_iter i;
+  UPB_ASSERT(iter != UPB_MAP_BEGIN);
+  i.t = &map->table;
+  i.index = iter;
+  return upb_strtable_done(&i);
+}
+
+/* Returns the key and value for this entry of the map. */
+upb_msgval upb_mapiter_key(const upb_map *map, size_t iter) {
+  upb_strtable_iter i;
+  upb_msgval ret;
+  i.t = &map->table;
+  i.index = iter;
+  _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size);
+  return ret;
+}
+
+upb_msgval upb_mapiter_value(const upb_map *map, size_t iter) {
+  upb_strtable_iter i;
+  upb_msgval ret;
+  i.t = &map->table;
+  i.index = iter;
+  _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size);
+  return ret;
+}
+
+/* void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value); */
+
+
+#include <errno.h>
+#include <float.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <math.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Special header, must be included last. */
+
+typedef struct {
+  const char *ptr, *end;
+  upb_arena *arena;  /* TODO: should we have a tmp arena for tmp data? */
+  const upb_symtab *any_pool;
+  int depth;
+  upb_status *status;
+  jmp_buf err;
+  int line;
+  const char *line_begin;
+  bool is_first;
+  int options;
+  const upb_fielddef *debug_field;
+} jsondec;
+
+enum { JD_OBJECT, JD_ARRAY, JD_STRING, JD_NUMBER, JD_TRUE, JD_FALSE, JD_NULL };
+
+/* Forward declarations of mutually-recursive functions. */
+static void jsondec_wellknown(jsondec *d, upb_msg *msg, const upb_msgdef *m);
+static upb_msgval jsondec_value(jsondec *d, const upb_fielddef *f);
+static void jsondec_wellknownvalue(jsondec *d, upb_msg *msg,
+                                   const upb_msgdef *m);
+static void jsondec_object(jsondec *d, upb_msg *msg, const upb_msgdef *m);
+
+static bool jsondec_streql(upb_strview str, const char *lit) {
+  return str.size == strlen(lit) && memcmp(str.data, lit, str.size) == 0;
+}
+
+static bool jsondec_isnullvalue(const upb_fielddef *f) {
+  return upb_fielddef_type(f) == UPB_TYPE_ENUM &&
+         strcmp(upb_enumdef_fullname(upb_fielddef_enumsubdef(f)),
+                "google.protobuf.NullValue") == 0;
+}
+
+static bool jsondec_isvalue(const upb_fielddef *f) {
+  return (upb_fielddef_type(f) == UPB_TYPE_MESSAGE &&
+          upb_msgdef_wellknowntype(upb_fielddef_msgsubdef(f)) ==
+              UPB_WELLKNOWN_VALUE) ||
+         jsondec_isnullvalue(f);
+}
+
+UPB_NORETURN static void jsondec_err(jsondec *d, const char *msg) {
+  upb_status_seterrf(d->status, "Error parsing JSON @%d:%d: %s", d->line,
+                     (int)(d->ptr - d->line_begin), msg);
+  UPB_LONGJMP(d->err, 1);
+}
+
+UPB_PRINTF(2, 3)
+UPB_NORETURN static void jsondec_errf(jsondec *d, const char *fmt, ...) {
+  va_list argp;
+  upb_status_seterrf(d->status, "Error parsing JSON @%d:%d: ", d->line,
+                     (int)(d->ptr - d->line_begin));
+  va_start(argp, fmt);
+  upb_status_vappenderrf(d->status, fmt, argp);
+  va_end(argp);
+  UPB_LONGJMP(d->err, 1);
+}
+
+static void jsondec_skipws(jsondec *d) {
+  while (d->ptr != d->end) {
+    switch (*d->ptr) {
+      case '\n':
+        d->line++;
+        d->line_begin = d->ptr;
+        /* Fallthrough. */
+      case '\r':
+      case '\t':
+      case ' ':
+        d->ptr++;
+        break;
+      default:
+        return;
+    }
+  }
+  jsondec_err(d, "Unexpected EOF");
+}
+
+static bool jsondec_tryparsech(jsondec *d, char ch) {
+  if (d->ptr == d->end || *d->ptr != ch) return false;
+  d->ptr++;
+  return true;
+}
+
+static void jsondec_parselit(jsondec *d, const char *lit) {
+  size_t avail = d->end - d->ptr;
+  size_t len = strlen(lit);
+  if (avail < len || memcmp(d->ptr, lit, len) != 0) {
+    jsondec_errf(d, "Expected: '%s'", lit);
+  }
+  d->ptr += len;
+}
+
+static void jsondec_wsch(jsondec *d, char ch) {
+  jsondec_skipws(d);
+  if (!jsondec_tryparsech(d, ch)) {
+    jsondec_errf(d, "Expected: '%c'", ch);
+  }
+}
+
+static void jsondec_true(jsondec *d) { jsondec_parselit(d, "true"); }
+static void jsondec_false(jsondec *d) { jsondec_parselit(d, "false"); }
+static void jsondec_null(jsondec *d) { jsondec_parselit(d, "null"); }
+
+static void jsondec_entrysep(jsondec *d) {
+  jsondec_skipws(d);
+  jsondec_parselit(d, ":");
+}
+
+static int jsondec_rawpeek(jsondec *d) {
+  switch (*d->ptr) {
+    case '{':
+      return JD_OBJECT;
+    case '[':
+      return JD_ARRAY;
+    case '"':
+      return JD_STRING;
+    case '-':
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+      return JD_NUMBER;
+    case 't':
+      return JD_TRUE;
+    case 'f':
+      return JD_FALSE;
+    case 'n':
+      return JD_NULL;
+    default:
+      jsondec_errf(d, "Unexpected character: '%c'", *d->ptr);
+  }
+}
+
+/* JSON object/array **********************************************************/
+
+/* These are used like so:
+ *
+ * jsondec_objstart(d);
+ * while (jsondec_objnext(d)) {
+ *   ...
+ * }
+ * jsondec_objend(d) */
+
+static int jsondec_peek(jsondec *d) {
+  jsondec_skipws(d);
+  return jsondec_rawpeek(d);
+}
+
+static void jsondec_push(jsondec *d) {
+  if (--d->depth < 0) {
+    jsondec_err(d, "Recursion limit exceeded");
+  }
+  d->is_first = true;
+}
+
+static bool jsondec_seqnext(jsondec *d, char end_ch) {
+  bool is_first = d->is_first;
+  d->is_first = false;
+  jsondec_skipws(d);
+  if (*d->ptr == end_ch) return false;
+  if (!is_first) jsondec_parselit(d, ",");
+  return true;
+}
+
+static void jsondec_arrstart(jsondec *d) {
+  jsondec_push(d);
+  jsondec_wsch(d, '[');
+}
+
+static void jsondec_arrend(jsondec *d) {
+  d->depth++;
+  jsondec_wsch(d, ']');
+}
+
+static bool jsondec_arrnext(jsondec *d) {
+  return jsondec_seqnext(d, ']');
+}
+
+static void jsondec_objstart(jsondec *d) {
+  jsondec_push(d);
+  jsondec_wsch(d, '{');
+}
+
+static void jsondec_objend(jsondec *d) {
+  d->depth++;
+  jsondec_wsch(d, '}');
+}
+
+static bool jsondec_objnext(jsondec *d) {
+  if (!jsondec_seqnext(d, '}')) return false;
+  if (jsondec_peek(d) != JD_STRING) {
+    jsondec_err(d, "Object must start with string");
+  }
+  return true;
+}
+
+/* JSON number ****************************************************************/
+
+static bool jsondec_tryskipdigits(jsondec *d) {
+  const char *start = d->ptr;
+
+  while (d->ptr < d->end) {
+    if (*d->ptr < '0' || *d->ptr > '9') {
+      break;
+    }
+    d->ptr++;
+  }
+
+  return d->ptr != start;
+}
+
+static void jsondec_skipdigits(jsondec *d) {
+  if (!jsondec_tryskipdigits(d)) {
+    jsondec_err(d, "Expected one or more digits");
+  }
+}
+
+static double jsondec_number(jsondec *d) {
+  const char *start = d->ptr;
+
+  assert(jsondec_rawpeek(d) == JD_NUMBER);
+
+  /* Skip over the syntax of a number, as specified by JSON. */
+  if (*d->ptr == '-') d->ptr++;
+
+  if (jsondec_tryparsech(d, '0')) {
+    if (jsondec_tryskipdigits(d)) {
+      jsondec_err(d, "number cannot have leading zero");
+    }
+  } else {
+    jsondec_skipdigits(d);
+  }
+
+  if (d->ptr == d->end) goto parse;
+  if (jsondec_tryparsech(d, '.')) {
+    jsondec_skipdigits(d);
+  }
+  if (d->ptr == d->end) goto parse;
+
+  if (*d->ptr == 'e' || *d->ptr == 'E') {
+    d->ptr++;
+    if (d->ptr == d->end) {
+      jsondec_err(d, "Unexpected EOF in number");
+    }
+    if (*d->ptr == '+' || *d->ptr == '-') {
+      d->ptr++;
+    }
+    jsondec_skipdigits(d);
+  }
+
+parse:
+  /* Having verified the syntax of a JSON number, use strtod() to parse
+   * (strtod() accepts a superset of JSON syntax). */
+  errno = 0;
+  {
+    char* end;
+    double val = strtod(start, &end);
+    assert(end == d->ptr);
+
+    /* Currently the min/max-val conformance tests fail if we check this.  Does
+     * this mean the conformance tests are wrong or strtod() is wrong, or
+     * something else?  Investigate further. */
+    /*
+    if (errno == ERANGE) {
+      jsondec_err(d, "Number out of range");
+    }
+    */
+
+    if (val > DBL_MAX || val < -DBL_MAX) {
+      jsondec_err(d, "Number out of range");
+    }
+
+    return val;
+  }
+}
+
+/* JSON string ****************************************************************/
+
+static char jsondec_escape(jsondec *d) {
+  switch (*d->ptr++) {
+    case '"':
+      return '\"';
+    case '\\':
+      return '\\';
+    case '/':
+      return '/';
+    case 'b':
+      return '\b';
+    case 'f':
+      return '\f';
+    case 'n':
+      return '\n';
+    case 'r':
+      return '\r';
+    case 't':
+      return '\t';
+    default:
+      jsondec_err(d, "Invalid escape char");
+  }
+}
+
+static uint32_t jsondec_codepoint(jsondec *d) {
+  uint32_t cp = 0;
+  const char *end;
+
+  if (d->end - d->ptr < 4) {
+    jsondec_err(d, "EOF inside string");
+  }
+
+  end = d->ptr + 4;
+  while (d->ptr < end) {
+    char ch = *d->ptr++;
+    if (ch >= '0' && ch <= '9') {
+      ch -= '0';
+    } else if (ch >= 'a' && ch <= 'f') {
+      ch = ch - 'a' + 10;
+    } else if (ch >= 'A' && ch <= 'F') {
+      ch = ch - 'A' + 10;
+    } else {
+      jsondec_err(d, "Invalid hex digit");
+    }
+    cp = (cp << 4) | ch;
+  }
+
+  return cp;
+}
+
+/* Parses a \uXXXX unicode escape (possibly a surrogate pair). */
+static size_t jsondec_unicode(jsondec *d, char* out) {
+  uint32_t cp = jsondec_codepoint(d);
+  if (cp >= 0xd800 && cp <= 0xdbff) {
+    /* Surrogate pair: two 16-bit codepoints become a 32-bit codepoint. */
+    uint32_t high = cp;
+    uint32_t low;
+    jsondec_parselit(d, "\\u");
+    low = jsondec_codepoint(d);
+    if (low < 0xdc00 || low > 0xdfff) {
+      jsondec_err(d, "Invalid low surrogate");
+    }
+    cp = (high & 0x3ff) << 10;
+    cp |= (low & 0x3ff);
+    cp += 0x10000;
+  } else if (cp >= 0xdc00 && cp <= 0xdfff) {
+    jsondec_err(d, "Unpaired low surrogate");
+  }
+
+  /* Write to UTF-8 */
+  if (cp <= 0x7f) {
+    out[0] = cp;
+    return 1;
+  } else if (cp <= 0x07FF) {
+    out[0] = ((cp >> 6) & 0x1F) | 0xC0;
+    out[1] = ((cp >> 0) & 0x3F) | 0x80;
+    return 2;
+  } else if (cp <= 0xFFFF) {
+    out[0] = ((cp >> 12) & 0x0F) | 0xE0;
+    out[1] = ((cp >> 6) & 0x3F) | 0x80;
+    out[2] = ((cp >> 0) & 0x3F) | 0x80;
+    return 3;
+  } else if (cp < 0x10FFFF) {
+    out[0] = ((cp >> 18) & 0x07) | 0xF0;
+    out[1] = ((cp >> 12) & 0x3f) | 0x80;
+    out[2] = ((cp >> 6) & 0x3f) | 0x80;
+    out[3] = ((cp >> 0) & 0x3f) | 0x80;
+    return 4;
+  } else {
+    jsondec_err(d, "Invalid codepoint");
+  }
+}
+
+static void jsondec_resize(jsondec *d, char **buf, char **end, char **buf_end) {
+  size_t oldsize = *buf_end - *buf;
+  size_t len = *end - *buf;
+  size_t size = UPB_MAX(8, 2 * oldsize);
+
+  *buf = upb_arena_realloc(d->arena, *buf, len, size);
+  if (!*buf) jsondec_err(d, "Out of memory");
+
+  *end = *buf + len;
+  *buf_end = *buf + size;
+}
+
+static upb_strview jsondec_string(jsondec *d) {
+  char *buf = NULL;
+  char *end = NULL;
+  char *buf_end = NULL;
+
+  jsondec_skipws(d);
+
+  if (*d->ptr++ != '"') {
+    jsondec_err(d, "Expected string");
+  }
+
+  while (d->ptr < d->end) {
+    char ch = *d->ptr++;
+
+    if (end == buf_end) {
+      jsondec_resize(d, &buf, &end, &buf_end);
+    }
+
+    switch (ch) {
+      case '"': {
+        upb_strview ret;
+        ret.data = buf;
+        ret.size = end - buf;
+        *end = '\0';  /* Needed for possible strtod(). */
+        return ret;
+      }
+      case '\\':
+        if (d->ptr == d->end) goto eof;
+        if (*d->ptr == 'u') {
+          d->ptr++;
+          if (buf_end - end < 4) {
+            /* Allow space for maximum-sized code point (4 bytes). */
+            jsondec_resize(d, &buf, &end, &buf_end);
+          }
+          end += jsondec_unicode(d, end);
+        } else {
+          *end++ = jsondec_escape(d);
+        }
+        break;
+      default:
+        if ((unsigned char)*d->ptr < 0x20) {
+          jsondec_err(d, "Invalid char in JSON string");
+        }
+        *end++ = ch;
+        break;
+    }
+  }
+
+eof:
+  jsondec_err(d, "EOF inside string");
+}
+
+static void jsondec_skipval(jsondec *d) {
+  switch (jsondec_peek(d)) {
+    case JD_OBJECT:
+      jsondec_objstart(d);
+      while (jsondec_objnext(d)) {
+        jsondec_string(d);
+        jsondec_entrysep(d);
+        jsondec_skipval(d);
+      }
+      jsondec_objend(d);
+      break;
+    case JD_ARRAY:
+      jsondec_arrstart(d);
+      while (jsondec_arrnext(d)) {
+        jsondec_skipval(d);
+      }
+      jsondec_arrend(d);
+      break;
+    case JD_TRUE:
+      jsondec_true(d);
+      break;
+    case JD_FALSE:
+      jsondec_false(d);
+      break;
+    case JD_NULL:
+      jsondec_null(d);
+      break;
+    case JD_STRING:
+      jsondec_string(d);
+      break;
+    case JD_NUMBER:
+      jsondec_number(d);
+      break;
+  }
+}
+
+/* Base64 decoding for bytes fields. ******************************************/
+
+static unsigned int jsondec_base64_tablelookup(const char ch) {
+  /* Table includes the normal base64 chars plus the URL-safe variant. */
+  const signed char table[256] = {
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       62 /*+*/, -1,       62 /*-*/, -1,       63 /*/ */, 52 /*0*/,
+      53 /*1*/, 54 /*2*/, 55 /*3*/, 56 /*4*/, 57 /*5*/, 58 /*6*/,  59 /*7*/,
+      60 /*8*/, 61 /*9*/, -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       0 /*A*/,  1 /*B*/,  2 /*C*/,  3 /*D*/,   4 /*E*/,
+      5 /*F*/,  6 /*G*/,  07 /*H*/, 8 /*I*/,  9 /*J*/,  10 /*K*/,  11 /*L*/,
+      12 /*M*/, 13 /*N*/, 14 /*O*/, 15 /*P*/, 16 /*Q*/, 17 /*R*/,  18 /*S*/,
+      19 /*T*/, 20 /*U*/, 21 /*V*/, 22 /*W*/, 23 /*X*/, 24 /*Y*/,  25 /*Z*/,
+      -1,       -1,       -1,       -1,       63 /*_*/, -1,        26 /*a*/,
+      27 /*b*/, 28 /*c*/, 29 /*d*/, 30 /*e*/, 31 /*f*/, 32 /*g*/,  33 /*h*/,
+      34 /*i*/, 35 /*j*/, 36 /*k*/, 37 /*l*/, 38 /*m*/, 39 /*n*/,  40 /*o*/,
+      41 /*p*/, 42 /*q*/, 43 /*r*/, 44 /*s*/, 45 /*t*/, 46 /*u*/,  47 /*v*/,
+      48 /*w*/, 49 /*x*/, 50 /*y*/, 51 /*z*/, -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1,       -1,       -1,        -1,
+      -1,       -1,       -1,       -1};
+
+  /* Sign-extend return value so high bit will be set on any unexpected char. */
+  return table[(unsigned)ch];
+}
+
+static char *jsondec_partialbase64(jsondec *d, const char *ptr, const char *end,
+                                   char *out) {
+  int32_t val = -1;
+
+  switch (end - ptr) {
+    case 2:
+      val = jsondec_base64_tablelookup(ptr[0]) << 18 |
+            jsondec_base64_tablelookup(ptr[1]) << 12;
+      out[0] = val >> 16;
+      out += 1;
+      break;
+    case 3:
+      val = jsondec_base64_tablelookup(ptr[0]) << 18 |
+            jsondec_base64_tablelookup(ptr[1]) << 12 |
+            jsondec_base64_tablelookup(ptr[2]) << 6;
+      out[0] = val >> 16;
+      out[1] = (val >> 8) & 0xff;
+      out += 2;
+      break;
+  }
+
+  if (val < 0) {
+    jsondec_err(d, "Corrupt base64");
+  }
+
+  return out;
+}
+
+static size_t jsondec_base64(jsondec *d, upb_strview str) {
+  /* We decode in place. This is safe because this is a new buffer (not
+   * aliasing the input) and because base64 decoding shrinks 4 bytes into 3. */
+  char *out = (char*)str.data;
+  const char *ptr = str.data;
+  const char *end = ptr + str.size;
+  const char *end4 = ptr + (str.size & -4);  /* Round down to multiple of 4. */
+
+  for (; ptr < end4; ptr += 4, out += 3) {
+    int val = jsondec_base64_tablelookup(ptr[0]) << 18 |
+              jsondec_base64_tablelookup(ptr[1]) << 12 |
+              jsondec_base64_tablelookup(ptr[2]) << 6 |
+              jsondec_base64_tablelookup(ptr[3]) << 0;
+
+    if (val < 0) {
+      /* Junk chars or padding. Remove trailing padding, if any. */
+      if (end - ptr == 4 && ptr[3] == '=') {
+        if (ptr[2] == '=') {
+          end -= 2;
+        } else {
+          end -= 1;
+        }
+      }
+      break;
+    }
+
+    out[0] = val >> 16;
+    out[1] = (val >> 8) & 0xff;
+    out[2] = val & 0xff;
+  }
+
+  if (ptr < end) {
+    /* Process remaining chars. We do not require padding. */
+    out = jsondec_partialbase64(d, ptr, end, out);
+  }
+
+  return out - str.data;
+}
+
+/* Low-level integer parsing **************************************************/
+
+/* We use these hand-written routines instead of strto[u]l() because the "long
+ * long" variants aren't in c89. Also our version allows setting a ptr limit. */
+
+static const char *jsondec_buftouint64(jsondec *d, const char *ptr,
+                                       const char *end, uint64_t *val) {
+  uint64_t u64 = 0;
+  while (ptr < end) {
+    unsigned ch = *ptr - '0';
+    if (ch >= 10) break;
+    if (u64 > UINT64_MAX / 10 || u64 * 10 > UINT64_MAX - ch) {
+      jsondec_err(d, "Integer overflow");
+    }
+    u64 *= 10;
+    u64 += ch;
+    ptr++;
+  }
+
+  *val = u64;
+  return ptr;
+}
+
+static const char *jsondec_buftoint64(jsondec *d, const char *ptr,
+                                      const char *end, int64_t *val) {
+  bool neg = false;
+  uint64_t u64;
+
+  if (ptr != end && *ptr == '-') {
+    ptr++;
+    neg = true;
+  }
+
+  ptr = jsondec_buftouint64(d, ptr, end, &u64);
+  if (u64 > (uint64_t)INT64_MAX + neg) {
+    jsondec_err(d, "Integer overflow");
+  }
+
+  *val = neg ? -u64 : u64;
+  return ptr;
+}
+
+static uint64_t jsondec_strtouint64(jsondec *d, upb_strview str) {
+  const char *end = str.data + str.size;
+  uint64_t ret;
+  if (jsondec_buftouint64(d, str.data, end, &ret) != end) {
+    jsondec_err(d, "Non-number characters in quoted integer");
+  }
+  return ret;
+}
+
+static int64_t jsondec_strtoint64(jsondec *d, upb_strview str) {
+  const char *end = str.data + str.size;
+  int64_t ret;
+  if (jsondec_buftoint64(d, str.data, end, &ret) != end) {
+    jsondec_err(d, "Non-number characters in quoted integer");
+  }
+  return ret;
+}
+
+/* Primitive value types ******************************************************/
+
+/* Parse INT32 or INT64 value. */
+static upb_msgval jsondec_int(jsondec *d, const upb_fielddef *f) {
+  upb_msgval val;
+
+  switch (jsondec_peek(d)) {
+    case JD_NUMBER: {
+      double dbl = jsondec_number(d);
+      if (dbl > 9223372036854774784.0 || dbl < -9223372036854775808.0) {
+        jsondec_err(d, "JSON number is out of range.");
+      }
+      val.int64_val = dbl;  /* must be guarded, overflow here is UB */
+      if (val.int64_val != dbl) {
+        jsondec_errf(d, "JSON number was not integral (%f != %" PRId64 ")", dbl,
+                     val.int64_val);
+      }
+      break;
+    }
+    case JD_STRING: {
+      upb_strview str = jsondec_string(d);
+      val.int64_val = jsondec_strtoint64(d, str);
+      break;
+    }
+    default:
+      jsondec_err(d, "Expected number or string");
+  }
+
+  if (upb_fielddef_type(f) == UPB_TYPE_INT32) {
+    if (val.int64_val > INT32_MAX || val.int64_val < INT32_MIN) {
+      jsondec_err(d, "Integer out of range.");
+    }
+    val.int32_val = (int32_t)val.int64_val;
+  }
+
+  return val;
+}
+
+/* Parse UINT32 or UINT64 value. */
+static upb_msgval jsondec_uint(jsondec *d, const upb_fielddef *f) {
+  upb_msgval val = {0};
+
+  switch (jsondec_peek(d)) {
+    case JD_NUMBER: {
+      double dbl = jsondec_number(d);
+      if (dbl > 18446744073709549568.0 || dbl < 0) {
+        jsondec_err(d, "JSON number is out of range.");
+      }
+      val.uint64_val = dbl;  /* must be guarded, overflow here is UB */
+      if (val.uint64_val != dbl) {
+        jsondec_errf(d, "JSON number was not integral (%f != %" PRIu64 ")", dbl,
+                     val.uint64_val);
+      }
+      break;
+    }
+    case JD_STRING: {
+      upb_strview str = jsondec_string(d);
+      val.uint64_val = jsondec_strtouint64(d, str);
+      break;
+    }
+    default:
+      jsondec_err(d, "Expected number or string");
+  }
+
+  if (upb_fielddef_type(f) == UPB_TYPE_UINT32) {
+    if (val.uint64_val > UINT32_MAX) {
+      jsondec_err(d, "Integer out of range.");
+    }
+    val.uint32_val = (uint32_t)val.uint64_val;
+  }
+
+  return val;
+}
+
+/* Parse DOUBLE or FLOAT value. */
+static upb_msgval jsondec_double(jsondec *d, const upb_fielddef *f) {
+  upb_strview str;
+  upb_msgval val = {0};
+
+  switch (jsondec_peek(d)) {
+    case JD_NUMBER:
+      val.double_val = jsondec_number(d);
+      break;
+    case JD_STRING:
+      str = jsondec_string(d);
+      if (jsondec_streql(str, "NaN")) {
+        val.double_val = NAN;
+      } else if (jsondec_streql(str, "Infinity")) {
+        val.double_val = INFINITY;
+      } else if (jsondec_streql(str, "-Infinity")) {
+        val.double_val = -INFINITY;
+      } else {
+        val.double_val = strtod(str.data, NULL);
+      }
+      break;
+    default:
+      jsondec_err(d, "Expected number or string");
+  }
+
+  if (upb_fielddef_type(f) == UPB_TYPE_FLOAT) {
+    if (val.double_val != INFINITY && val.double_val != -INFINITY &&
+        (val.double_val > FLT_MAX || val.double_val < -FLT_MAX)) {
+      jsondec_err(d, "Float out of range");
+    }
+    val.float_val = val.double_val;
+  }
+
+  return val;
+}
+
+/* Parse STRING or BYTES value. */
+static upb_msgval jsondec_strfield(jsondec *d, const upb_fielddef *f) {
+  upb_msgval val;
+  val.str_val = jsondec_string(d);
+  if (upb_fielddef_type(f) == UPB_TYPE_BYTES) {
+    val.str_val.size = jsondec_base64(d, val.str_val);
+  }
+  return val;
+}
+
+static upb_msgval jsondec_enum(jsondec *d, const upb_fielddef *f) {
+  switch (jsondec_peek(d)) {
+    case JD_STRING: {
+      const upb_enumdef *e = upb_fielddef_enumsubdef(f);
+      upb_strview str = jsondec_string(d);
+      upb_msgval val;
+      if (!upb_enumdef_ntoi(e, str.data, str.size, &val.int32_val)) {
+        if (d->options & UPB_JSONDEC_IGNOREUNKNOWN) {
+          val.int32_val = 0;
+        } else {
+          jsondec_errf(d, "Unknown enumerator: '" UPB_STRVIEW_FORMAT "'",
+                       UPB_STRVIEW_ARGS(str));
+        }
+      }
+      return val;
+    }
+    case JD_NULL: {
+      if (jsondec_isnullvalue(f)) {
+        upb_msgval val;
+        jsondec_null(d);
+        val.int32_val = 0;
+        return val;
+      }
+    }
+      /* Fallthrough. */
+    default:
+      return jsondec_int(d, f);
+  }
+}
+
+static upb_msgval jsondec_bool(jsondec *d, const upb_fielddef *f) {
+  bool is_map_key = upb_fielddef_number(f) == 1 &&
+                    upb_msgdef_mapentry(upb_fielddef_containingtype(f));
+  upb_msgval val;
+
+  if (is_map_key) {
+    upb_strview str = jsondec_string(d);
+    if (jsondec_streql(str, "true")) {
+      val.bool_val = true;
+    } else if (jsondec_streql(str, "false")) {
+      val.bool_val = false;
+    } else {
+      jsondec_err(d, "Invalid boolean map key");
+    }
+  } else {
+    switch (jsondec_peek(d)) {
+      case JD_TRUE:
+        val.bool_val = true;
+        jsondec_true(d);
+        break;
+      case JD_FALSE:
+        val.bool_val = false;
+        jsondec_false(d);
+        break;
+      default:
+        jsondec_err(d, "Expected true or false");
+    }
+  }
+
+  return val;
+}
+
+/* Composite types (array/message/map) ****************************************/
+
+static void jsondec_array(jsondec *d, upb_msg *msg, const upb_fielddef *f) {
+  upb_array *arr = upb_msg_mutable(msg, f, d->arena).array;
+
+  jsondec_arrstart(d);
+  while (jsondec_arrnext(d)) {
+    upb_msgval elem = jsondec_value(d, f);
+    upb_array_append(arr, elem, d->arena);
+  }
+  jsondec_arrend(d);
+}
+
+static void jsondec_map(jsondec *d, upb_msg *msg, const upb_fielddef *f) {
+  upb_map *map = upb_msg_mutable(msg, f, d->arena).map;
+  const upb_msgdef *entry = upb_fielddef_msgsubdef(f);
+  const upb_fielddef *key_f = upb_msgdef_itof(entry, 1);
+  const upb_fielddef *val_f = upb_msgdef_itof(entry, 2);
+
+  jsondec_objstart(d);
+  while (jsondec_objnext(d)) {
+    upb_msgval key, val;
+    key = jsondec_value(d, key_f);
+    jsondec_entrysep(d);
+    val = jsondec_value(d, val_f);
+    upb_map_set(map, key, val, d->arena);
+  }
+  jsondec_objend(d);
+}
+
+static void jsondec_tomsg(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  if (upb_msgdef_wellknowntype(m) == UPB_WELLKNOWN_UNSPECIFIED) {
+    jsondec_object(d, msg, m);
+  } else {
+    jsondec_wellknown(d, msg, m);
+  }
+}
+
+static upb_msgval jsondec_msg(jsondec *d, const upb_fielddef *f) {
+  const upb_msgdef *m = upb_fielddef_msgsubdef(f);
+  upb_msg *msg = upb_msg_new(m, d->arena);
+  upb_msgval val;
+
+  jsondec_tomsg(d, msg, m);
+  val.msg_val = msg;
+  return val;
+}
+
+static void jsondec_field(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  upb_strview name;
+  const upb_fielddef *f;
+  const upb_fielddef *preserved;
+
+  name = jsondec_string(d);
+  jsondec_entrysep(d);
+  f = upb_msgdef_lookupjsonname(m, name.data, name.size);
+
+  if (!f) {
+    if ((d->options & UPB_JSONDEC_IGNOREUNKNOWN) == 0) {
+      jsondec_errf(d, "No such field: " UPB_STRVIEW_FORMAT,
+                   UPB_STRVIEW_ARGS(name));
+    }
+    jsondec_skipval(d);
+    return;
+  }
+
+  if (upb_fielddef_realcontainingoneof(f) &&
+      upb_msg_whichoneof(msg, upb_fielddef_containingoneof(f))) {
+    jsondec_err(d, "More than one field for this oneof.");
+  }
+
+  if (jsondec_peek(d) == JD_NULL && !jsondec_isvalue(f)) {
+    /* JSON "null" indicates a default value, so no need to set anything. */
+    jsondec_null(d);
+    return;
+  }
+
+  preserved = d->debug_field;
+  d->debug_field = f;
+
+  if (upb_fielddef_ismap(f)) {
+    jsondec_map(d, msg, f);
+  } else if (upb_fielddef_isseq(f)) {
+    jsondec_array(d, msg, f);
+  } else if (upb_fielddef_issubmsg(f)) {
+    upb_msg *submsg = upb_msg_mutable(msg, f, d->arena).msg;
+    const upb_msgdef *subm = upb_fielddef_msgsubdef(f);
+    jsondec_tomsg(d, submsg, subm);
+  } else {
+    upb_msgval val = jsondec_value(d, f);
+    upb_msg_set(msg, f, val, d->arena);
+  }
+
+  d->debug_field = preserved;
+}
+
+static void jsondec_object(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  jsondec_objstart(d);
+  while (jsondec_objnext(d)) {
+    jsondec_field(d, msg, m);
+  }
+  jsondec_objend(d);
+}
+
+static upb_msgval jsondec_value(jsondec *d, const upb_fielddef *f) {
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_BOOL:
+      return jsondec_bool(d, f);
+    case UPB_TYPE_FLOAT:
+    case UPB_TYPE_DOUBLE:
+      return jsondec_double(d, f);
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_UINT64:
+      return jsondec_uint(d, f);
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64:
+      return jsondec_int(d, f);
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+      return jsondec_strfield(d, f);
+    case UPB_TYPE_ENUM:
+      return jsondec_enum(d, f);
+    case UPB_TYPE_MESSAGE:
+      return jsondec_msg(d, f);
+    default:
+      UPB_UNREACHABLE();
+  }
+}
+
+/* Well-known types ***********************************************************/
+
+static int jsondec_tsdigits(jsondec *d, const char **ptr, size_t digits,
+                            const char *after) {
+  uint64_t val;
+  const char *p = *ptr;
+  const char *end = p + digits;
+  size_t after_len = after ? strlen(after) : 0;
+
+  UPB_ASSERT(digits <= 9);  /* int can't overflow. */
+
+  if (jsondec_buftouint64(d, p, end, &val) != end ||
+      (after_len && memcmp(end, after, after_len) != 0)) {
+    jsondec_err(d, "Malformed timestamp");
+  }
+
+  UPB_ASSERT(val < INT_MAX);
+
+  *ptr = end + after_len;
+  return (int)val;
+}
+
+static int jsondec_nanos(jsondec *d, const char **ptr, const char *end) {
+  uint64_t nanos = 0;
+  const char *p = *ptr;
+
+  if (p != end && *p == '.') {
+    const char *nano_end = jsondec_buftouint64(d, p + 1, end, &nanos);
+    int digits = (int)(nano_end - p - 1);
+    int exp_lg10 = 9 - digits;
+    if (digits > 9) {
+      jsondec_err(d, "Too many digits for partial seconds");
+    }
+    while (exp_lg10--) nanos *= 10;
+    *ptr = nano_end;
+  }
+
+  UPB_ASSERT(nanos < INT_MAX);
+
+  return (int)nanos;
+}
+
+/* jsondec_epochdays(1970, 1, 1) == 1970-01-01 == 0. */
+int jsondec_epochdays(int y, int m, int d) {
+  const uint32_t year_base = 4800;    /* Before min year, multiple of 400. */
+  const uint32_t m_adj = m - 3;       /* March-based month. */
+  const uint32_t carry = m_adj > (uint32_t)m ? 1 : 0;
+  const uint32_t adjust = carry ? 12 : 0;
+  const uint32_t y_adj = y + year_base - carry;
+  const uint32_t month_days = ((m_adj + adjust) * 62719 + 769) / 2048;
+  const uint32_t leap_days = y_adj / 4 - y_adj / 100 + y_adj / 400;
+  return y_adj * 365 + leap_days + month_days + (d - 1) - 2472632;
+}
+
+static int64_t jsondec_unixtime(int y, int m, int d, int h, int min, int s) {
+  return (int64_t)jsondec_epochdays(y, m, d) * 86400 + h * 3600 + min * 60 + s;
+}
+
+static void jsondec_timestamp(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  upb_msgval seconds;
+  upb_msgval nanos;
+  upb_strview str = jsondec_string(d);
+  const char *ptr = str.data;
+  const char *end = ptr + str.size;
+
+  if (str.size < 20) goto malformed;
+
+  {
+    /* 1972-01-01T01:00:00 */
+    int year = jsondec_tsdigits(d, &ptr, 4, "-");
+    int mon = jsondec_tsdigits(d, &ptr, 2, "-");
+    int day = jsondec_tsdigits(d, &ptr, 2, "T");
+    int hour = jsondec_tsdigits(d, &ptr, 2, ":");
+    int min = jsondec_tsdigits(d, &ptr, 2, ":");
+    int sec = jsondec_tsdigits(d, &ptr, 2, NULL);
+
+    seconds.int64_val = jsondec_unixtime(year, mon, day, hour, min, sec);
+  }
+
+  nanos.int32_val = jsondec_nanos(d, &ptr, end);
+
+  {
+    /* [+-]08:00 or Z */
+    int ofs = 0;
+    bool neg = false;
+
+    if (ptr == end) goto malformed;
+
+    switch (*ptr++) {
+      case '-':
+        neg = true;
+        /* fallthrough */
+      case '+':
+        if ((end - ptr) != 5) goto malformed;
+        ofs = jsondec_tsdigits(d, &ptr, 2, ":00");
+        ofs *= 60 * 60;
+        seconds.int64_val += (neg ? ofs : -ofs);
+        break;
+      case 'Z':
+        if (ptr != end) goto malformed;
+        break;
+      default:
+        goto malformed;
+    }
+  }
+
+  if (seconds.int64_val < -62135596800) {
+    jsondec_err(d, "Timestamp out of range");
+  }
+
+  upb_msg_set(msg, upb_msgdef_itof(m, 1), seconds, d->arena);
+  upb_msg_set(msg, upb_msgdef_itof(m, 2), nanos, d->arena);
+  return;
+
+malformed:
+  jsondec_err(d, "Malformed timestamp");
+}
+
+static void jsondec_duration(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  upb_msgval seconds;
+  upb_msgval nanos;
+  upb_strview str = jsondec_string(d);
+  const char *ptr = str.data;
+  const char *end = ptr + str.size;
+  const int64_t max = (uint64_t)3652500 * 86400;
+
+  /* "3.000000001s", "3s", etc. */
+  ptr = jsondec_buftoint64(d, ptr, end, &seconds.int64_val);
+  nanos.int32_val = jsondec_nanos(d, &ptr, end);
+
+  if (end - ptr != 1 || *ptr != 's') {
+    jsondec_err(d, "Malformed duration");
+  }
+
+  if (seconds.int64_val < -max || seconds.int64_val > max) {
+    jsondec_err(d, "Duration out of range");
+  }
+
+  if (seconds.int64_val < 0) {
+    nanos.int32_val = - nanos.int32_val;
+  }
+
+  upb_msg_set(msg, upb_msgdef_itof(m, 1), seconds, d->arena);
+  upb_msg_set(msg, upb_msgdef_itof(m, 2), nanos, d->arena);
+}
+
+static void jsondec_listvalue(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  const upb_fielddef *values_f = upb_msgdef_itof(m, 1);
+  const upb_msgdef *value_m = upb_fielddef_msgsubdef(values_f);
+  upb_array *values = upb_msg_mutable(msg, values_f, d->arena).array;
+
+  jsondec_arrstart(d);
+  while (jsondec_arrnext(d)) {
+    upb_msg *value_msg = upb_msg_new(value_m, d->arena);
+    upb_msgval value;
+    value.msg_val = value_msg;
+    upb_array_append(values, value, d->arena);
+    jsondec_wellknownvalue(d, value_msg, value_m);
+  }
+  jsondec_arrend(d);
+}
+
+static void jsondec_struct(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  const upb_fielddef *fields_f = upb_msgdef_itof(m, 1);
+  const upb_msgdef *entry_m = upb_fielddef_msgsubdef(fields_f);
+  const upb_fielddef *value_f = upb_msgdef_itof(entry_m, 2);
+  const upb_msgdef *value_m = upb_fielddef_msgsubdef(value_f);
+  upb_map *fields = upb_msg_mutable(msg, fields_f, d->arena).map;
+
+  jsondec_objstart(d);
+  while (jsondec_objnext(d)) {
+    upb_msgval key, value;
+    upb_msg *value_msg = upb_msg_new(value_m, d->arena);
+    key.str_val = jsondec_string(d);
+    value.msg_val = value_msg;
+    upb_map_set(fields, key, value, d->arena);
+    jsondec_entrysep(d);
+    jsondec_wellknownvalue(d, value_msg, value_m);
+  }
+  jsondec_objend(d);
+}
+
+static void jsondec_wellknownvalue(jsondec *d, upb_msg *msg,
+                                   const upb_msgdef *m) {
+  upb_msgval val;
+  const upb_fielddef *f;
+  upb_msg *submsg;
+
+  switch (jsondec_peek(d)) {
+    case JD_NUMBER:
+      /* double number_value = 2; */
+      f = upb_msgdef_itof(m, 2);
+      val.double_val = jsondec_number(d);
+      break;
+    case JD_STRING:
+      /* string string_value = 3; */
+      f = upb_msgdef_itof(m, 3);
+      val.str_val = jsondec_string(d);
+      break;
+    case JD_FALSE:
+      /* bool bool_value = 4; */
+      f = upb_msgdef_itof(m, 4);
+      val.bool_val = false;
+      jsondec_false(d);
+      break;
+    case JD_TRUE:
+      /* bool bool_value = 4; */
+      f = upb_msgdef_itof(m, 4);
+      val.bool_val = true;
+      jsondec_true(d);
+      break;
+    case JD_NULL:
+      /* NullValue null_value = 1; */
+      f = upb_msgdef_itof(m, 1);
+      val.int32_val = 0;
+      jsondec_null(d);
+      break;
+    /* Note: these cases return, because upb_msg_mutable() is enough. */
+    case JD_OBJECT:
+      /* Struct struct_value = 5; */
+      f = upb_msgdef_itof(m, 5);
+      submsg = upb_msg_mutable(msg, f, d->arena).msg;
+      jsondec_struct(d, submsg, upb_fielddef_msgsubdef(f));
+      return;
+    case JD_ARRAY:
+      /* ListValue list_value = 6; */
+      f = upb_msgdef_itof(m, 6);
+      submsg = upb_msg_mutable(msg, f, d->arena).msg;
+      jsondec_listvalue(d, submsg, upb_fielddef_msgsubdef(f));
+      return;
+    default:
+      UPB_UNREACHABLE();
+  }
+
+  upb_msg_set(msg, f, val, d->arena);
+}
+
+static upb_strview jsondec_mask(jsondec *d, const char *buf, const char *end) {
+  /* FieldMask fields grow due to inserted '_' characters, so we can't do the
+   * transform in place. */
+  const char *ptr = buf;
+  upb_strview ret;
+  char *out;
+
+  ret.size = end - ptr;
+  while (ptr < end) {
+    ret.size += (*ptr >= 'A' && *ptr <= 'Z');
+    ptr++;
+  }
+
+  out = upb_arena_malloc(d->arena, ret.size);
+  ptr = buf;
+  ret.data = out;
+
+  while (ptr < end) {
+    char ch = *ptr++;
+    if (ch >= 'A' && ch <= 'Z') {
+      *out++ = '_';
+      *out++ = ch + 32;
+    } else if (ch == '_') {
+      jsondec_err(d, "field mask may not contain '_'");
+    } else {
+      *out++ = ch;
+    }
+  }
+
+  return ret;
+}
+
+static void jsondec_fieldmask(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  /* repeated string paths = 1; */
+  const upb_fielddef *paths_f = upb_msgdef_itof(m, 1);
+  upb_array *arr = upb_msg_mutable(msg, paths_f, d->arena).array;
+  upb_strview str = jsondec_string(d);
+  const char *ptr = str.data;
+  const char *end = ptr + str.size;
+  upb_msgval val;
+
+  while (ptr < end) {
+    const char *elem_end = memchr(ptr, ',', end - ptr);
+    if (elem_end) {
+      val.str_val = jsondec_mask(d, ptr, elem_end);
+      ptr = elem_end + 1;
+    } else {
+      val.str_val = jsondec_mask(d, ptr, end);
+      ptr = end;
+    }
+    upb_array_append(arr, val, d->arena);
+  }
+}
+
+static void jsondec_anyfield(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  if (upb_msgdef_wellknowntype(m) == UPB_WELLKNOWN_UNSPECIFIED) {
+    /* For regular types: {"@type": "[user type]", "f1": <V1>, "f2": <V2>}
+     * where f1, f2, etc. are the normal fields of this type. */
+    jsondec_field(d, msg, m);
+  } else {
+    /* For well-known types: {"@type": "[well-known type]", "value": <X>}
+     * where <X> is whatever encoding the WKT normally uses. */
+    upb_strview str = jsondec_string(d);
+    jsondec_entrysep(d);
+    if (!jsondec_streql(str, "value")) {
+      jsondec_err(d, "Key for well-known type must be 'value'");
+    }
+    jsondec_wellknown(d, msg, m);
+  }
+}
+
+static const upb_msgdef *jsondec_typeurl(jsondec *d, upb_msg *msg,
+                                         const upb_msgdef *m) {
+  const upb_fielddef *type_url_f = upb_msgdef_itof(m, 1);
+  const upb_msgdef *type_m;
+  upb_strview type_url = jsondec_string(d);
+  const char *end = type_url.data + type_url.size;
+  const char *ptr = end;
+  upb_msgval val;
+
+  val.str_val = type_url;
+  upb_msg_set(msg, type_url_f, val, d->arena);
+
+  /* Find message name after the last '/' */
+  while (ptr > type_url.data && *--ptr != '/') {}
+
+  if (ptr == type_url.data || ptr == end) {
+    jsondec_err(d, "Type url must have at least one '/' and non-empty host");
+  }
+
+  ptr++;
+  type_m = upb_symtab_lookupmsg2(d->any_pool, ptr, end - ptr);
+
+  if (!type_m) {
+    jsondec_err(d, "Type was not found");
+  }
+
+  return type_m;
+}
+
+static void jsondec_any(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  /* string type_url = 1;
+   * bytes value = 2; */
+  const upb_fielddef *value_f = upb_msgdef_itof(m, 2);
+  upb_msg *any_msg;
+  const upb_msgdef *any_m = NULL;
+  const char *pre_type_data = NULL;
+  const char *pre_type_end = NULL;
+  upb_msgval encoded;
+
+  jsondec_objstart(d);
+
+  /* Scan looking for "@type", which is not necessarily first. */
+  while (!any_m && jsondec_objnext(d)) {
+    const char *start = d->ptr;
+    upb_strview name = jsondec_string(d);
+    jsondec_entrysep(d);
+    if (jsondec_streql(name, "@type")) {
+      any_m = jsondec_typeurl(d, msg, m);
+      if (pre_type_data) {
+        pre_type_end = start;
+        while (*pre_type_end != ',') pre_type_end--;
+      }
+    } else {
+      if (!pre_type_data) pre_type_data = start;
+      jsondec_skipval(d);
+    }
+  }
+
+  if (!any_m) {
+    jsondec_err(d, "Any object didn't contain a '@type' field");
+  }
+
+  any_msg = upb_msg_new(any_m, d->arena);
+
+  if (pre_type_data) {
+    size_t len = pre_type_end - pre_type_data + 1;
+    char *tmp = upb_arena_malloc(d->arena, len);
+    const char *saved_ptr = d->ptr;
+    const char *saved_end = d->end;
+    memcpy(tmp, pre_type_data, len - 1);
+    tmp[len - 1] = '}';
+    d->ptr = tmp;
+    d->end = tmp + len;
+    d->is_first = true;
+    while (jsondec_objnext(d)) {
+      jsondec_anyfield(d, any_msg, any_m);
+    }
+    d->ptr = saved_ptr;
+    d->end = saved_end;
+  }
+
+  while (jsondec_objnext(d)) {
+    jsondec_anyfield(d, any_msg, any_m);
+  }
+
+  jsondec_objend(d);
+
+  encoded.str_val.data = upb_encode(any_msg, upb_msgdef_layout(any_m), d->arena,
+                                    &encoded.str_val.size);
+  upb_msg_set(msg, value_f, encoded, d->arena);
+}
+
+static void jsondec_wrapper(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  const upb_fielddef *value_f = upb_msgdef_itof(m, 1);
+  upb_msgval val = jsondec_value(d, value_f);
+  upb_msg_set(msg, value_f, val, d->arena);
+}
+
+static void jsondec_wellknown(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
+  switch (upb_msgdef_wellknowntype(m)) {
+    case UPB_WELLKNOWN_ANY:
+      jsondec_any(d, msg, m);
+      break;
+    case UPB_WELLKNOWN_FIELDMASK:
+      jsondec_fieldmask(d, msg, m);
+      break;
+    case UPB_WELLKNOWN_DURATION:
+      jsondec_duration(d, msg, m);
+      break;
+    case UPB_WELLKNOWN_TIMESTAMP:
+      jsondec_timestamp(d, msg, m);
+      break;
+    case UPB_WELLKNOWN_VALUE:
+      jsondec_wellknownvalue(d, msg, m);
+      break;
+    case UPB_WELLKNOWN_LISTVALUE:
+      jsondec_listvalue(d, msg, m);
+      break;
+    case UPB_WELLKNOWN_STRUCT:
+      jsondec_struct(d, msg, m);
+      break;
+    case UPB_WELLKNOWN_DOUBLEVALUE:
+    case UPB_WELLKNOWN_FLOATVALUE:
+    case UPB_WELLKNOWN_INT64VALUE:
+    case UPB_WELLKNOWN_UINT64VALUE:
+    case UPB_WELLKNOWN_INT32VALUE:
+    case UPB_WELLKNOWN_UINT32VALUE:
+    case UPB_WELLKNOWN_STRINGVALUE:
+    case UPB_WELLKNOWN_BYTESVALUE:
+    case UPB_WELLKNOWN_BOOLVALUE:
+      jsondec_wrapper(d, msg, m);
+      break;
+    default:
+      UPB_UNREACHABLE();
+  }
+}
+
+bool upb_json_decode(const char *buf, size_t size, upb_msg *msg,
+                     const upb_msgdef *m, const upb_symtab *any_pool,
+                     int options, upb_arena *arena, upb_status *status) {
+  jsondec d;
+  d.ptr = buf;
+  d.end = buf + size;
+  d.arena = arena;
+  d.any_pool = any_pool;
+  d.status = status;
+  d.options = options;
+  d.depth = 64;
+  d.line = 1;
+  d.line_begin = d.ptr;
+  d.debug_field = NULL;
+  d.is_first = false;
+
+  if (UPB_SETJMP(d.err)) return false;
+
+  jsondec_tomsg(&d, msg, m);
+  return true;
+}
+
+
+#include <ctype.h>
+#include <float.h>
+#include <inttypes.h>
+#include <math.h>
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+
+/* Must be last. */
+
+typedef struct {
+  char *buf, *ptr, *end;
+  size_t overflow;
+  int indent_depth;
+  int options;
+  const upb_symtab *ext_pool;
+  jmp_buf err;
+  upb_status *status;
+  upb_arena *arena;
+} jsonenc;
+
+static void jsonenc_msg(jsonenc *e, const upb_msg *msg, const upb_msgdef *m);
+static void jsonenc_scalar(jsonenc *e, upb_msgval val, const upb_fielddef *f);
+static void jsonenc_msgfield(jsonenc *e, const upb_msg *msg,
+                             const upb_msgdef *m);
+static void jsonenc_msgfields(jsonenc *e, const upb_msg *msg,
+                              const upb_msgdef *m);
+static void jsonenc_value(jsonenc *e, const upb_msg *msg, const upb_msgdef *m);
+
+UPB_NORETURN static void jsonenc_err(jsonenc *e, const char *msg) {
+  upb_status_seterrmsg(e->status, msg);
+  longjmp(e->err, 1);
+}
+
+UPB_PRINTF(2, 3)
+UPB_NORETURN static void jsonenc_errf(jsonenc *e, const char *fmt, ...) {
+  va_list argp;
+  va_start(argp, fmt);
+  upb_status_vseterrf(e->status, fmt, argp);
+  va_end(argp);
+  longjmp(e->err, 1);
+}
+
+static upb_arena *jsonenc_arena(jsonenc *e) {
+  /* Create lazily, since it's only needed for Any */
+  if (!e->arena) {
+    e->arena = upb_arena_new();
+  }
+  return e->arena;
+}
+
+static void jsonenc_putbytes(jsonenc *e, const void *data, size_t len) {
+  size_t have = e->end - e->ptr;
+  if (UPB_LIKELY(have >= len)) {
+    memcpy(e->ptr, data, len);
+    e->ptr += len;
+  } else {
+    if (have) memcpy(e->ptr, data, have);
+    e->ptr += have;
+    e->overflow += (len - have);
+  }
+}
+
+static void jsonenc_putstr(jsonenc *e, const char *str) {
+  jsonenc_putbytes(e, str, strlen(str));
+}
+
+UPB_PRINTF(2, 3)
+static void jsonenc_printf(jsonenc *e, const char *fmt, ...) {
+  size_t n;
+  size_t have = e->end - e->ptr;
+  va_list args;
+
+  va_start(args, fmt);
+  n = vsnprintf(e->ptr, have, fmt, args);
+  va_end(args);
+
+  if (UPB_LIKELY(have > n)) {
+    e->ptr += n;
+  } else {
+    e->ptr += have;
+    e->overflow += (n - have);
+  }
+}
+
+static void jsonenc_nanos(jsonenc *e, int32_t nanos) {
+  int digits = 9;
+
+  if (nanos == 0) return;
+  if (nanos < 0 || nanos >= 1000000000) {
+    jsonenc_err(e, "error formatting timestamp as JSON: invalid nanos");
+  }
+
+  while (nanos % 1000 == 0) {
+    nanos /= 1000;
+    digits -= 3;
+  }
+
+  jsonenc_printf(e, ".%.*" PRId32, digits, nanos);
+}
+
+static void jsonenc_timestamp(jsonenc *e, const upb_msg *msg,
+                              const upb_msgdef *m) {
+  const upb_fielddef *seconds_f = upb_msgdef_itof(m, 1);
+  const upb_fielddef *nanos_f = upb_msgdef_itof(m, 2);
+  int64_t seconds = upb_msg_get(msg, seconds_f).int64_val;
+  int32_t nanos = upb_msg_get(msg, nanos_f).int32_val;
+  int L, N, I, J, K, hour, min, sec;
+
+  if (seconds < -62135596800) {
+    jsonenc_err(e,
+                "error formatting timestamp as JSON: minimum acceptable value "
+                "is 0001-01-01T00:00:00Z");
+  } else if (seconds > 253402300799) {
+    jsonenc_err(e,
+                "error formatting timestamp as JSON: maximum acceptable value "
+                "is 9999-12-31T23:59:59Z");
+  }
+
+  /* Julian Day -> Y/M/D, Algorithm from:
+   * Fliegel, H. F., and Van Flandern, T. C., "A Machine Algorithm for
+   *   Processing Calendar Dates," Communications of the Association of
+   *   Computing Machines, vol. 11 (1968), p. 657.  */
+  L = (int)(seconds / 86400) + 68569 + 2440588;
+  N = 4 * L / 146097;
+  L = L - (146097 * N + 3) / 4;
+  I = 4000 * (L + 1) / 1461001;
+  L = L - 1461 * I / 4 + 31;
+  J = 80 * L / 2447;
+  K = L - 2447 * J / 80;
+  L = J / 11;
+  J = J + 2 - 12 * L;
+  I = 100 * (N - 49) + I + L;
+
+  sec = seconds % 60;
+  min = (seconds / 60) % 60;
+  hour = (seconds / 3600) % 24;
+
+  jsonenc_printf(e, "\"%04d-%02d-%02dT%02d:%02d:%02d", I, J, K, hour, min, sec);
+  jsonenc_nanos(e, nanos);
+  jsonenc_putstr(e, "Z\"");
+}
+
+static void jsonenc_duration(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) {
+  const upb_fielddef *seconds_f = upb_msgdef_itof(m, 1);
+  const upb_fielddef *nanos_f = upb_msgdef_itof(m, 2);
+  int64_t seconds = upb_msg_get(msg, seconds_f).int64_val;
+  int32_t nanos = upb_msg_get(msg, nanos_f).int32_val;
+
+  if (seconds > 315576000000 || seconds < -315576000000 ||
+      (seconds < 0) != (nanos < 0)) {
+    jsonenc_err(e, "bad duration");
+  }
+
+  if (nanos < 0) {
+    nanos = -nanos;
+  }
+
+  jsonenc_printf(e, "\"%" PRId64, seconds);
+  jsonenc_nanos(e, nanos);
+  jsonenc_putstr(e, "s\"");
+}
+
+static void jsonenc_enum(int32_t val, const upb_fielddef *f, jsonenc *e) {
+  const upb_enumdef *e_def = upb_fielddef_enumsubdef(f);
+
+  if (strcmp(upb_enumdef_fullname(e_def), "google.protobuf.NullValue") == 0) {
+    jsonenc_putstr(e, "null");
+  } else {
+    const char *name = upb_enumdef_iton(e_def, val);
+
+    if (name) {
+      jsonenc_printf(e, "\"%s\"", name);
+    } else {
+      jsonenc_printf(e, "%" PRId32, val);
+    }
+  }
+}
+
+static void jsonenc_bytes(jsonenc *e, upb_strview str) {
+  /* This is the regular base64, not the "web-safe" version. */
+  static const char base64[] =
+      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  const unsigned char *ptr = (unsigned char*)str.data;
+  const unsigned char *end = ptr + str.size;
+  char buf[4];
+
+  jsonenc_putstr(e, "\"");
+
+  while (end - ptr >= 3) {
+    buf[0] = base64[ptr[0] >> 2];
+    buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)];
+    buf[2] = base64[((ptr[1] & 0xf) << 2) | (ptr[2] >> 6)];
+    buf[3] = base64[ptr[2] & 0x3f];
+    jsonenc_putbytes(e, buf, 4);
+    ptr += 3;
+  }
+
+  switch (end - ptr) {
+    case 2:
+      buf[0] = base64[ptr[0] >> 2];
+      buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)];
+      buf[2] = base64[(ptr[1] & 0xf) << 2];
+      buf[3] = '=';
+      jsonenc_putbytes(e, buf, 4);
+      break;
+    case 1:
+      buf[0] = base64[ptr[0] >> 2];
+      buf[1] = base64[((ptr[0] & 0x3) << 4)];
+      buf[2] = '=';
+      buf[3] = '=';
+      jsonenc_putbytes(e, buf, 4);
+      break;
+  }
+
+  jsonenc_putstr(e, "\"");
+}
+
+static void jsonenc_stringbody(jsonenc *e, upb_strview str) {
+  const char *ptr = str.data;
+  const char *end = ptr + str.size;
+
+  while (ptr < end) {
+    switch (*ptr) {
+      case '\n':
+        jsonenc_putstr(e, "\\n");
+        break;
+      case '\r':
+        jsonenc_putstr(e, "\\r");
+        break;
+      case '\t':
+        jsonenc_putstr(e, "\\t");
+        break;
+      case '\"':
+        jsonenc_putstr(e, "\\\"");
+        break;
+      case '\f':
+        jsonenc_putstr(e, "\\f");
+        break;
+      case '\b':
+        jsonenc_putstr(e, "\\b");
+        break;
+      case '\\':
+        jsonenc_putstr(e, "\\\\");
+        break;
+      default:
+        if ((uint8_t)*ptr < 0x20) {
+          jsonenc_printf(e, "\\u%04x", (int)(uint8_t)*ptr);
+        } else {
+          /* This could be a non-ASCII byte.  We rely on the string being valid
+           * UTF-8. */
+          jsonenc_putbytes(e, ptr, 1);
+        }
+        break;
+    }
+    ptr++;
+  }
+}
+
+static void jsonenc_string(jsonenc *e, upb_strview str) {
+  jsonenc_putstr(e, "\"");
+  jsonenc_stringbody(e, str);
+  jsonenc_putstr(e, "\"");
+}
+
+static void jsonenc_double(jsonenc *e, const char *fmt, double val) {
+  if (val == INFINITY) {
+    jsonenc_putstr(e, "\"Infinity\"");
+  } else if (val == -INFINITY) {
+    jsonenc_putstr(e, "\"-Infinity\"");
+  } else if (val != val) {
+    jsonenc_putstr(e, "\"NaN\"");
+  } else {
+    jsonenc_printf(e, fmt, val);
+  }
+}
+
+static void jsonenc_wrapper(jsonenc *e, const upb_msg *msg,
+                            const upb_msgdef *m) {
+  const upb_fielddef *val_f = upb_msgdef_itof(m, 1);
+  upb_msgval val = upb_msg_get(msg, val_f);
+  jsonenc_scalar(e, val, val_f);
+}
+
+static const upb_msgdef *jsonenc_getanymsg(jsonenc *e, upb_strview type_url) {
+  /* Find last '/', if any. */
+  const char *end = type_url.data + type_url.size;
+  const char *ptr = end;
+  const upb_msgdef *ret;
+
+  if (!e->ext_pool) {
+    jsonenc_err(e, "Tried to encode Any, but no symtab was provided");
+  }
+
+  if (type_url.size == 0) goto badurl;
+
+  while (true) {
+    if (--ptr == type_url.data) {
+      /* Type URL must contain at least one '/', with host before. */
+      goto badurl;
+    }
+    if (*ptr == '/') {
+      ptr++;
+      break;
+    }
+  }
+
+  ret = upb_symtab_lookupmsg2(e->ext_pool, ptr, end - ptr);
+
+  if (!ret) {
+    jsonenc_errf(e, "Couldn't find Any type: %.*s", (int)(end - ptr), ptr);
+  }
+
+  return ret;
+
+badurl:
+  jsonenc_errf(
+      e, "Bad type URL: " UPB_STRVIEW_FORMAT, UPB_STRVIEW_ARGS(type_url));
+}
+
+static void jsonenc_any(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) {
+  const upb_fielddef *type_url_f = upb_msgdef_itof(m, 1);
+  const upb_fielddef *value_f = upb_msgdef_itof(m, 2);
+  upb_strview type_url = upb_msg_get(msg, type_url_f).str_val;
+  upb_strview value = upb_msg_get(msg, value_f).str_val;
+  const upb_msgdef *any_m = jsonenc_getanymsg(e, type_url);
+  const upb_msglayout *any_layout = upb_msgdef_layout(any_m);
+  upb_arena *arena = jsonenc_arena(e);
+  upb_msg *any = upb_msg_new(any_m, arena);
+
+  if (!upb_decode(value.data, value.size, any, any_layout, arena)) {
+    jsonenc_err(e, "Error decoding message in Any");
+  }
+
+  jsonenc_putstr(e, "{\"@type\":");
+  jsonenc_string(e, type_url);
+  jsonenc_putstr(e, ",");
+
+  if (upb_msgdef_wellknowntype(any_m) == UPB_WELLKNOWN_UNSPECIFIED) {
+    /* Regular messages: {"@type": "...","foo": 1, "bar": 2} */
+    jsonenc_msgfields(e, any, any_m);
+  } else {
+    /* Well-known type: {"@type": "...","value": <well-known encoding>} */
+    jsonenc_putstr(e, "\"value\":");
+    jsonenc_msgfield(e, any, any_m);
+  }
+
+  jsonenc_putstr(e, "}");
+}
+
+static void jsonenc_putsep(jsonenc *e, const char *str, bool *first) {
+  if (*first) {
+    *first = false;
+  } else {
+    jsonenc_putstr(e, str);
+  }
+}
+
+static void jsonenc_fieldpath(jsonenc *e, upb_strview path) {
+  const char *ptr = path.data;
+  const char *end = ptr + path.size;
+
+  while (ptr < end) {
+    char ch = *ptr;
+
+    if (ch >= 'A' && ch <= 'Z') {
+      jsonenc_err(e, "Field mask element may not have upper-case letter.");
+    } else if (ch == '_') {
+      if (ptr == end - 1 || *(ptr + 1) < 'a' || *(ptr + 1) > 'z') {
+        jsonenc_err(e, "Underscore must be followed by a lowercase letter.");
+      }
+      ch = *++ptr - 32;
+    }
+
+    jsonenc_putbytes(e, &ch, 1);
+    ptr++;
+  }
+}
+
+static void jsonenc_fieldmask(jsonenc *e, const upb_msg *msg,
+                              const upb_msgdef *m) {
+  const upb_fielddef *paths_f = upb_msgdef_itof(m, 1);
+  const upb_array *paths = upb_msg_get(msg, paths_f).array_val;
+  bool first = true;
+  size_t i, n = 0;
+
+  if (paths) n = upb_array_size(paths);
+
+  jsonenc_putstr(e, "\"");
+
+  for (i = 0; i < n; i++) {
+    jsonenc_putsep(e, ",", &first);
+    jsonenc_fieldpath(e, upb_array_get(paths, i).str_val);
+  }
+
+  jsonenc_putstr(e, "\"");
+}
+
+static void jsonenc_struct(jsonenc *e, const upb_msg *msg,
+                           const upb_msgdef *m) {
+  const upb_fielddef *fields_f = upb_msgdef_itof(m, 1);
+  const upb_map *fields = upb_msg_get(msg, fields_f).map_val;
+  const upb_msgdef *entry_m = upb_fielddef_msgsubdef(fields_f);
+  const upb_fielddef *value_f = upb_msgdef_itof(entry_m, 2);
+  size_t iter = UPB_MAP_BEGIN;
+  bool first = true;
+
+  jsonenc_putstr(e, "{");
+
+  if (fields) {
+    while (upb_mapiter_next(fields, &iter)) {
+      upb_msgval key = upb_mapiter_key(fields, iter);
+      upb_msgval val = upb_mapiter_value(fields, iter);
+
+      jsonenc_putsep(e, ",", &first);
+      jsonenc_string(e, key.str_val);
+      jsonenc_putstr(e, ":");
+      jsonenc_value(e, val.msg_val, upb_fielddef_msgsubdef(value_f));
+    }
+  }
+
+  jsonenc_putstr(e, "}");
+}
+
+static void jsonenc_listvalue(jsonenc *e, const upb_msg *msg,
+                              const upb_msgdef *m) {
+  const upb_fielddef *values_f = upb_msgdef_itof(m, 1);
+  const upb_msgdef *values_m = upb_fielddef_msgsubdef(values_f);
+  const upb_array *values = upb_msg_get(msg, values_f).array_val;
+  size_t i;
+  bool first = true;
+
+  jsonenc_putstr(e, "[");
+
+  if (values) {
+    const size_t size = upb_array_size(values);
+    for (i = 0; i < size; i++) {
+      upb_msgval elem = upb_array_get(values, i);
+
+      jsonenc_putsep(e, ",", &first);
+      jsonenc_value(e, elem.msg_val, values_m);
+    }
+  }
+
+  jsonenc_putstr(e, "]");
+}
+
+static void jsonenc_value(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) {
+  /* TODO(haberman): do we want a reflection method to get oneof case? */
+  size_t iter = UPB_MSG_BEGIN;
+  const upb_fielddef *f;
+  upb_msgval val;
+
+  if (!upb_msg_next(msg, m, NULL,  &f, &val, &iter)) {
+    jsonenc_err(e, "No value set in Value proto");
+  }
+
+  switch (upb_fielddef_number(f)) {
+    case 1:
+      jsonenc_putstr(e, "null");
+      break;
+    case 2:
+      jsonenc_double(e, "%.17g", val.double_val);
+      break;
+    case 3:
+      jsonenc_string(e, val.str_val);
+      break;
+    case 4:
+      jsonenc_putstr(e, val.bool_val ? "true" : "false");
+      break;
+    case 5:
+      jsonenc_struct(e, val.msg_val, upb_fielddef_msgsubdef(f));
+      break;
+    case 6:
+      jsonenc_listvalue(e, val.msg_val, upb_fielddef_msgsubdef(f));
+      break;
+  }
+}
+
+static void jsonenc_msgfield(jsonenc *e, const upb_msg *msg,
+                             const upb_msgdef *m) {
+  switch (upb_msgdef_wellknowntype(m)) {
+    case UPB_WELLKNOWN_UNSPECIFIED:
+      jsonenc_msg(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_ANY:
+      jsonenc_any(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_FIELDMASK:
+      jsonenc_fieldmask(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_DURATION:
+      jsonenc_duration(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_TIMESTAMP:
+      jsonenc_timestamp(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_DOUBLEVALUE:
+    case UPB_WELLKNOWN_FLOATVALUE:
+    case UPB_WELLKNOWN_INT64VALUE:
+    case UPB_WELLKNOWN_UINT64VALUE:
+    case UPB_WELLKNOWN_INT32VALUE:
+    case UPB_WELLKNOWN_UINT32VALUE:
+    case UPB_WELLKNOWN_STRINGVALUE:
+    case UPB_WELLKNOWN_BYTESVALUE:
+    case UPB_WELLKNOWN_BOOLVALUE:
+      jsonenc_wrapper(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_VALUE:
+      jsonenc_value(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_LISTVALUE:
+      jsonenc_listvalue(e, msg, m);
+      break;
+    case UPB_WELLKNOWN_STRUCT:
+      jsonenc_struct(e, msg, m);
+      break;
+  }
+}
+
+static void jsonenc_scalar(jsonenc *e, upb_msgval val, const upb_fielddef *f) {
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_BOOL:
+      jsonenc_putstr(e, val.bool_val ? "true" : "false");
+      break;
+    case UPB_TYPE_FLOAT:
+      jsonenc_double(e, "%.9g", val.float_val);
+      break;
+    case UPB_TYPE_DOUBLE:
+      jsonenc_double(e, "%.17g", val.double_val);
+      break;
+    case UPB_TYPE_INT32:
+      jsonenc_printf(e, "%" PRId32, val.int32_val);
+      break;
+    case UPB_TYPE_UINT32:
+      jsonenc_printf(e, "%" PRIu32, val.uint32_val);
+      break;
+    case UPB_TYPE_INT64:
+      jsonenc_printf(e, "\"%" PRId64 "\"", val.int64_val);
+      break;
+    case UPB_TYPE_UINT64:
+      jsonenc_printf(e, "\"%" PRIu64 "\"", val.uint64_val);
+      break;
+    case UPB_TYPE_STRING:
+      jsonenc_string(e, val.str_val);
+      break;
+    case UPB_TYPE_BYTES:
+      jsonenc_bytes(e, val.str_val);
+      break;
+    case UPB_TYPE_ENUM:
+      jsonenc_enum(val.int32_val, f, e);
+      break;
+    case UPB_TYPE_MESSAGE:
+      jsonenc_msgfield(e, val.msg_val, upb_fielddef_msgsubdef(f));
+      break;
+  }
+}
+
+static void jsonenc_mapkey(jsonenc *e, upb_msgval val, const upb_fielddef *f) {
+  jsonenc_putstr(e, "\"");
+
+  switch (upb_fielddef_type(f)) {
+    case UPB_TYPE_BOOL:
+      jsonenc_putstr(e, val.bool_val ? "true" : "false");
+      break;
+    case UPB_TYPE_INT32:
+      jsonenc_printf(e, "%" PRId32, val.int32_val);
+      break;
+    case UPB_TYPE_UINT32:
+      jsonenc_printf(e, "%" PRIu32, val.uint32_val);
+      break;
+    case UPB_TYPE_INT64:
+      jsonenc_printf(e, "%" PRId64, val.int64_val);
+      break;
+    case UPB_TYPE_UINT64:
+      jsonenc_printf(e, "%" PRIu64, val.uint64_val);
+      break;
+    case UPB_TYPE_STRING:
+      jsonenc_stringbody(e, val.str_val);
+      break;
+    default:
+      UPB_UNREACHABLE();
+  }
+
+  jsonenc_putstr(e, "\":");
+}
+
+static void jsonenc_array(jsonenc *e, const upb_array *arr,
+                         const upb_fielddef *f) {
+  size_t i;
+  size_t size = arr ? upb_array_size(arr) : 0;
+  bool first = true;
+
+  jsonenc_putstr(e, "[");
+
+  for (i = 0; i < size; i++) {
+    jsonenc_putsep(e, ",", &first);
+    jsonenc_scalar(e, upb_array_get(arr, i), f);
+  }
+
+  jsonenc_putstr(e, "]");
+}
+
+static void jsonenc_map(jsonenc *e, const upb_map *map, const upb_fielddef *f) {
+  const upb_msgdef *entry = upb_fielddef_msgsubdef(f);
+  const upb_fielddef *key_f = upb_msgdef_itof(entry, 1);
+  const upb_fielddef *val_f = upb_msgdef_itof(entry, 2);
+  size_t iter = UPB_MAP_BEGIN;
+  bool first = true;
+
+  jsonenc_putstr(e, "{");
+
+  if (map) {
+    while (upb_mapiter_next(map, &iter)) {
+      jsonenc_putsep(e, ",", &first);
+      jsonenc_mapkey(e, upb_mapiter_key(map, iter), key_f);
+      jsonenc_scalar(e, upb_mapiter_value(map, iter), val_f);
+    }
+  }
+
+  jsonenc_putstr(e, "}");
+}
+
+static void jsonenc_fieldval(jsonenc *e, const upb_fielddef *f,
+                             upb_msgval val, bool *first) {
+  const char *name;
+
+  if (e->options & UPB_JSONENC_PROTONAMES) {
+    name = upb_fielddef_name(f);
+  } else {
+    name = upb_fielddef_jsonname(f);
+  }
+
+  jsonenc_putsep(e, ",", first);
+  jsonenc_printf(e, "\"%s\":", name);
+
+  if (upb_fielddef_ismap(f)) {
+    jsonenc_map(e, val.map_val, f);
+  } else if (upb_fielddef_isseq(f)) {
+    jsonenc_array(e, val.array_val, f);
+  } else {
+    jsonenc_scalar(e, val, f);
+  }
+}
+
+static void jsonenc_msgfields(jsonenc *e, const upb_msg *msg,
+                              const upb_msgdef *m) {
+  upb_msgval val;
+  const upb_fielddef *f;
+  bool first = true;
+
+  if (e->options & UPB_JSONENC_EMITDEFAULTS) {
+    /* Iterate over all fields. */
+    int i = 0;
+    int n = upb_msgdef_fieldcount(m);
+    for (i = 0; i < n; i++) {
+      f = upb_msgdef_field(m, i);
+      if (!upb_fielddef_haspresence(f) || upb_msg_has(msg, f)) {
+        jsonenc_fieldval(e, f, upb_msg_get(msg, f), &first);
+      }
+    }
+  } else {
+    /* Iterate over non-empty fields. */
+    size_t iter = UPB_MSG_BEGIN;
+    while (upb_msg_next(msg, m, e->ext_pool, &f, &val, &iter)) {
+      jsonenc_fieldval(e, f, val, &first);
+    }
+  }
+}
+
+static void jsonenc_msg(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) {
+  jsonenc_putstr(e, "{");
+  jsonenc_msgfields(e, msg, m);
+  jsonenc_putstr(e, "}");
+}
+
+static size_t jsonenc_nullz(jsonenc *e, size_t size) {
+  size_t ret = e->ptr - e->buf + e->overflow;
+
+  if (size > 0) {
+    if (e->ptr == e->end) e->ptr--;
+    *e->ptr = '\0';
+  }
+
+  return ret;
+}
+
+size_t upb_json_encode(const upb_msg *msg, const upb_msgdef *m,
+                       const upb_symtab *ext_pool, int options, char *buf,
+                       size_t size, upb_status *status) {
+  jsonenc e;
+
+  e.buf = buf;
+  e.ptr = buf;
+  e.end = buf + size;
+  e.overflow = 0;
+  e.options = options;
+  e.ext_pool = ext_pool;
+  e.status = status;
+  e.arena = NULL;
+
+  if (setjmp(e.err)) return -1;
+
+  jsonenc_msgfield(&e, msg, m);
+  if (e.arena) upb_arena_free(e.arena);
+  return jsonenc_nullz(&e, size);
+}
+/* See port_def.inc.  This should #undef all macros #defined there. */
+
+#undef UPB_MAPTYPE_STRING
+#undef UPB_SIZE
+#undef UPB_PTR_AT
+#undef UPB_READ_ONEOF
+#undef UPB_WRITE_ONEOF
+#undef UPB_INLINE
+#undef UPB_ALIGN_UP
+#undef UPB_ALIGN_DOWN
+#undef UPB_ALIGN_MALLOC
+#undef UPB_ALIGN_OF
+#undef UPB_FORCEINLINE
+#undef UPB_NOINLINE
+#undef UPB_NORETURN
+#undef UPB_MAX
+#undef UPB_MIN
+#undef UPB_UNUSED
+#undef UPB_ASSUME
+#undef UPB_ASSERT
+#undef UPB_UNREACHABLE
+#undef UPB_POISON_MEMORY_REGION
+#undef UPB_UNPOISON_MEMORY_REGION
+#undef UPB_ASAN
diff --git a/ruby/ext/google/protobuf_c/ruby-upb.h b/ruby/ext/google/protobuf_c/ruby-upb.h
new file mode 100755
index 0000000..106c73b
--- /dev/null
+++ b/ruby/ext/google/protobuf_c/ruby-upb.h
@@ -0,0 +1,4452 @@
+/* Amalgamated source file */
+#include <stdint.h>/*
+* This is where we define macros used across upb.
+*
+* All of these macros are undef'd in port_undef.inc to avoid leaking them to
+* users.
+*
+* The correct usage is:
+*
+*   #include "upb/foobar.h"
+*   #include "upb/baz.h"
+*
+*   // MUST be last included header.
+*   #include "upb/port_def.inc"
+*
+*   // Code for this file.
+*   // <...>
+*
+*   // Can be omitted for .c files, required for .h.
+*   #include "upb/port_undef.inc"
+*
+* This file is private and must not be included by users!
+*/
+
+#if !((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
+      (defined(__cplusplus) && __cplusplus >= 201103L) ||           \
+      (defined(_MSC_VER) && _MSC_VER >= 1900))
+#error upb requires C99 or C++11 or MSVC >= 2015.
+#endif
+
+#include <stdint.h>
+#include <stddef.h>
+
+#if UINTPTR_MAX == 0xffffffff
+#define UPB_SIZE(size32, size64) size32
+#else
+#define UPB_SIZE(size32, size64) size64
+#endif
+
+/* If we always read/write as a consistent type to each address, this shouldn't
+ * violate aliasing.
+ */
+#define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs)))
+
+#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \
+  *UPB_PTR_AT(msg, case_offset, int) == case_val                              \
+      ? *UPB_PTR_AT(msg, offset, fieldtype)                                   \
+      : default
+
+#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \
+  *UPB_PTR_AT(msg, case_offset, int) = case_val;                             \
+  *UPB_PTR_AT(msg, offset, fieldtype) = value;
+
+#define UPB_MAPTYPE_STRING 0
+
+/* UPB_INLINE: inline if possible, emit standalone code if required. */
+#ifdef __cplusplus
+#define UPB_INLINE inline
+#elif defined (__GNUC__) || defined(__clang__)
+#define UPB_INLINE static __inline__
+#else
+#define UPB_INLINE static
+#endif
+
+#define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align))
+#define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align))
+#define UPB_ALIGN_MALLOC(size) UPB_ALIGN_UP(size, 16)
+#define UPB_ALIGN_OF(type) offsetof (struct { char c; type member; }, member)
+
+/* Hints to the compiler about likely/unlikely branches. */
+#if defined (__GNUC__) || defined(__clang__)
+#define UPB_LIKELY(x) __builtin_expect((x),1)
+#define UPB_UNLIKELY(x) __builtin_expect((x),0)
+#else
+#define UPB_LIKELY(x) (x)
+#define UPB_UNLIKELY(x) (x)
+#endif
+
+/* Macros for function attributes on compilers that support them. */
+#ifdef __GNUC__
+#define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
+#define UPB_NOINLINE __attribute__((noinline))
+#define UPB_NORETURN __attribute__((__noreturn__))
+#define UPB_PRINTF(str, first_vararg) __attribute__((format (printf, str, first_vararg)))
+#elif defined(_MSC_VER)
+#define UPB_NOINLINE
+#define UPB_FORCEINLINE
+#define UPB_NORETURN __declspec(noreturn)
+#define UPB_PRINTF(str, first_vararg)
+#else  /* !defined(__GNUC__) */
+#define UPB_FORCEINLINE
+#define UPB_NOINLINE
+#define UPB_NORETURN
+#define UPB_PRINTF(str, first_vararg)
+#endif
+
+#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
+#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
+
+#define UPB_UNUSED(var) (void)var
+
+/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true.
+ */
+#ifdef NDEBUG
+#ifdef __GNUC__
+#define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable()
+#elif defined _MSC_VER
+#define UPB_ASSUME(expr) if (!(expr)) __assume(0)
+#else
+#define UPB_ASSUME(expr) do {} while (false && (expr))
+#endif
+#else
+#define UPB_ASSUME(expr) assert(expr)
+#endif
+
+/* UPB_ASSERT(): in release mode, we use the expression without letting it be
+ * evaluated.  This prevents "unused variable" warnings. */
+#ifdef NDEBUG
+#define UPB_ASSERT(expr) do {} while (false && (expr))
+#else
+#define UPB_ASSERT(expr) assert(expr)
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0)
+#else
+#define UPB_UNREACHABLE() do { assert(0); } while(0)
+#endif
+
+/* UPB_SETJMP() / UPB_LONGJMP(): avoid setting/restoring signal mask. */
+#ifdef __APPLE__
+#define UPB_SETJMP(buf) _setjmp(buf)
+#define UPB_LONGJMP(buf, val) _longjmp(buf, val)
+#else
+#define UPB_SETJMP(buf) setjmp(buf)
+#define UPB_LONGJMP(buf, val) longjmp(buf, val)
+#endif
+
+/* Configure whether fasttable is switched on or not. *************************/
+
+#if defined(__x86_64__) && defined(__GNUC__)
+#define UPB_FASTTABLE_SUPPORTED 1
+#else
+#define UPB_FASTTABLE_SUPPORTED 0
+#endif
+
+/* define UPB_ENABLE_FASTTABLE to force fast table support.
+ * This is useful when we want to ensure we are really getting fasttable,
+ * for example for testing or benchmarking. */
+#if defined(UPB_ENABLE_FASTTABLE)
+#if !UPB_FASTTABLE_SUPPORTED
+#error fasttable is x86-64 + Clang/GCC only
+#endif
+#define UPB_FASTTABLE 1
+/* Define UPB_TRY_ENABLE_FASTTABLE to use fasttable if possible.
+ * This is useful for releasing code that might be used on multiple platforms,
+ * for example the PHP or Ruby C extensions. */
+#elif defined(UPB_TRY_ENABLE_FASTTABLE)
+#define UPB_FASTTABLE UPB_FASTTABLE_SUPPORTED
+#else
+#define UPB_FASTTABLE 0
+#endif
+
+/* UPB_FASTTABLE_INIT() allows protos compiled for fasttable to gracefully
+ * degrade to non-fasttable if we are using UPB_TRY_ENABLE_FASTTABLE. */
+#if !UPB_FASTTABLE && defined(UPB_TRY_ENABLE_FASTTABLE)
+#define UPB_FASTTABLE_INIT(...)
+#else
+#define UPB_FASTTABLE_INIT(...) __VA_ARGS__
+#endif
+
+#undef UPB_FASTTABLE_SUPPORTED
+
+/* ASAN poisoning (for arena) *************************************************/
+
+#if defined(__SANITIZE_ADDRESS__)
+#define UPB_ASAN 1
+#ifdef __cplusplus
+extern "C" {
+#endif
+void __asan_poison_memory_region(void const volatile *addr, size_t size);
+void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+#define UPB_POISON_MEMORY_REGION(addr, size) \
+  __asan_poison_memory_region((addr), (size))
+#define UPB_UNPOISON_MEMORY_REGION(addr, size) \
+  __asan_unpoison_memory_region((addr), (size))
+#else
+#define UPB_ASAN 0
+#define UPB_POISON_MEMORY_REGION(addr, size) \
+  ((void)(addr), (void)(size))
+#define UPB_UNPOISON_MEMORY_REGION(addr, size) \
+  ((void)(addr), (void)(size))
+#endif 
+/*
+** upb_decode: parsing into a upb_msg using a upb_msglayout.
+*/
+
+#ifndef UPB_DECODE_H_
+#define UPB_DECODE_H_
+
+/*
+** Our memory representation for parsing tables and messages themselves.
+** Functions in this file are used by generated code and possibly reflection.
+**
+** The definitions in this file are internal to upb.
+**/
+
+#ifndef UPB_MSG_H_
+#define UPB_MSG_H_
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+** upb_table
+**
+** This header is INTERNAL-ONLY!  Its interfaces are not public or stable!
+** This file defines very fast int->upb_value (inttable) and string->upb_value
+** (strtable) hash tables.
+**
+** The table uses chained scatter with Brent's variation (inspired by the Lua
+** implementation of hash tables).  The hash function for strings is Austin
+** Appleby's "MurmurHash."
+**
+** The inttable uses uintptr_t as its key, which guarantees it can be used to
+** store pointers or integers of at least 32 bits (upb isn't really useful on
+** systems where sizeof(void*) < 4).
+**
+** The table must be homogeneous (all values of the same type).  In debug
+** mode, we check this on insert and lookup.
+*/
+
+#ifndef UPB_TABLE_H_
+#define UPB_TABLE_H_
+
+#include <stdint.h>
+#include <string.h>
+/*
+** This file contains shared definitions that are widely used across upb.
+*/
+
+#ifndef UPB_H_
+#define UPB_H_
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* upb_status *****************************************************************/
+
+#define UPB_STATUS_MAX_MESSAGE 127
+
+typedef struct {
+  bool ok;
+  char msg[UPB_STATUS_MAX_MESSAGE];  /* Error message; NULL-terminated. */
+} upb_status;
+
+const char *upb_status_errmsg(const upb_status *status);
+bool upb_ok(const upb_status *status);
+
+/* These are no-op if |status| is NULL. */
+void upb_status_clear(upb_status *status);
+void upb_status_seterrmsg(upb_status *status, const char *msg);
+void upb_status_seterrf(upb_status *status, const char *fmt, ...)
+    UPB_PRINTF(2, 3);
+void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args)
+    UPB_PRINTF(2, 0);
+void upb_status_vappenderrf(upb_status *status, const char *fmt, va_list args)
+    UPB_PRINTF(2, 0);
+
+/** upb_strview ************************************************************/
+
+typedef struct {
+  const char *data;
+  size_t size;
+} upb_strview;
+
+UPB_INLINE upb_strview upb_strview_make(const char *data, size_t size) {
+  upb_strview ret;
+  ret.data = data;
+  ret.size = size;
+  return ret;
+}
+
+UPB_INLINE upb_strview upb_strview_makez(const char *data) {
+  return upb_strview_make(data, strlen(data));
+}
+
+UPB_INLINE bool upb_strview_eql(upb_strview a, upb_strview b) {
+  return a.size == b.size && memcmp(a.data, b.data, a.size) == 0;
+}
+
+#define UPB_STRVIEW_INIT(ptr, len) {ptr, len}
+
+#define UPB_STRVIEW_FORMAT "%.*s"
+#define UPB_STRVIEW_ARGS(view) (int)(view).size, (view).data
+
+/** upb_alloc *****************************************************************/
+
+/* A upb_alloc is a possibly-stateful allocator object.
+ *
+ * It could either be an arena allocator (which doesn't require individual
+ * free() calls) or a regular malloc() (which does).  The client must therefore
+ * free memory unless it knows that the allocator is an arena allocator. */
+
+struct upb_alloc;
+typedef struct upb_alloc upb_alloc;
+
+/* A malloc()/free() function.
+ * If "size" is 0 then the function acts like free(), otherwise it acts like
+ * realloc().  Only "oldsize" bytes from a previous allocation are preserved. */
+typedef void *upb_alloc_func(upb_alloc *alloc, void *ptr, size_t oldsize,
+                             size_t size);
+
+struct upb_alloc {
+  upb_alloc_func *func;
+};
+
+UPB_INLINE void *upb_malloc(upb_alloc *alloc, size_t size) {
+  UPB_ASSERT(alloc);
+  return alloc->func(alloc, NULL, 0, size);
+}
+
+UPB_INLINE void *upb_realloc(upb_alloc *alloc, void *ptr, size_t oldsize,
+                             size_t size) {
+  UPB_ASSERT(alloc);
+  return alloc->func(alloc, ptr, oldsize, size);
+}
+
+UPB_INLINE void upb_free(upb_alloc *alloc, void *ptr) {
+  assert(alloc);
+  alloc->func(alloc, ptr, 0, 0);
+}
+
+/* The global allocator used by upb.  Uses the standard malloc()/free(). */
+
+extern upb_alloc upb_alloc_global;
+
+/* Functions that hard-code the global malloc.
+ *
+ * We still get benefit because we can put custom logic into our global
+ * allocator, like injecting out-of-memory faults in debug/testing builds. */
+
+UPB_INLINE void *upb_gmalloc(size_t size) {
+  return upb_malloc(&upb_alloc_global, size);
+}
+
+UPB_INLINE void *upb_grealloc(void *ptr, size_t oldsize, size_t size) {
+  return upb_realloc(&upb_alloc_global, ptr, oldsize, size);
+}
+
+UPB_INLINE void upb_gfree(void *ptr) {
+  upb_free(&upb_alloc_global, ptr);
+}
+
+/* upb_arena ******************************************************************/
+
+/* upb_arena is a specific allocator implementation that uses arena allocation.
+ * The user provides an allocator that will be used to allocate the underlying
+ * arena blocks.  Arenas by nature do not require the individual allocations
+ * to be freed.  However the Arena does allow users to register cleanup
+ * functions that will run when the arena is destroyed.
+ *
+ * A upb_arena is *not* thread-safe.
+ *
+ * You could write a thread-safe arena allocator that satisfies the
+ * upb_alloc interface, but it would not be as efficient for the
+ * single-threaded case. */
+
+typedef void upb_cleanup_func(void *ud);
+
+struct upb_arena;
+typedef struct upb_arena upb_arena;
+
+typedef struct {
+  /* We implement the allocator interface.
+   * This must be the first member of upb_arena!
+   * TODO(haberman): remove once handlers are gone. */
+  upb_alloc alloc;
+
+  char *ptr, *end;
+} _upb_arena_head;
+
+/* Creates an arena from the given initial block (if any -- n may be 0).
+ * Additional blocks will be allocated from |alloc|.  If |alloc| is NULL, this
+ * is a fixed-size arena and cannot grow. */
+upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc);
+void upb_arena_free(upb_arena *a);
+bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func);
+void upb_arena_fuse(upb_arena *a, upb_arena *b);
+void *_upb_arena_slowmalloc(upb_arena *a, size_t size);
+
+UPB_INLINE upb_alloc *upb_arena_alloc(upb_arena *a) { return (upb_alloc*)a; }
+
+UPB_INLINE size_t _upb_arenahas(upb_arena *a) {
+  _upb_arena_head *h = (_upb_arena_head*)a;
+  return (size_t)(h->end - h->ptr);
+}
+
+UPB_INLINE void *upb_arena_malloc(upb_arena *a, size_t size) {
+  _upb_arena_head *h = (_upb_arena_head*)a;
+  void* ret;
+  size = UPB_ALIGN_MALLOC(size);
+
+  if (UPB_UNLIKELY(_upb_arenahas(a) < size)) {
+    return _upb_arena_slowmalloc(a, size);
+  }
+
+  ret = h->ptr;
+  h->ptr += size;
+  UPB_UNPOISON_MEMORY_REGION(ret, size);
+
+#if UPB_ASAN
+  {
+    size_t guard_size = 32;
+    if (_upb_arenahas(a) >= guard_size) {
+      h->ptr += guard_size;
+    } else {
+      h->ptr = h->end;
+    }
+  }
+#endif
+
+  return ret;
+}
+
+UPB_INLINE void *upb_arena_realloc(upb_arena *a, void *ptr, size_t oldsize,
+                                   size_t size) {
+  void *ret = upb_arena_malloc(a, size);
+
+  if (ret && oldsize > 0) {
+    memcpy(ret, ptr, oldsize);
+  }
+
+  return ret;
+}
+
+UPB_INLINE upb_arena *upb_arena_new(void) {
+  return upb_arena_init(NULL, 0, &upb_alloc_global);
+}
+
+/* Constants ******************************************************************/
+
+/* Generic function type. */
+typedef void upb_func(void);
+
+/* A list of types as they are encoded on-the-wire. */
+typedef enum {
+  UPB_WIRE_TYPE_VARINT      = 0,
+  UPB_WIRE_TYPE_64BIT       = 1,
+  UPB_WIRE_TYPE_DELIMITED   = 2,
+  UPB_WIRE_TYPE_START_GROUP = 3,
+  UPB_WIRE_TYPE_END_GROUP   = 4,
+  UPB_WIRE_TYPE_32BIT       = 5
+} upb_wiretype_t;
+
+/* The types a field can have.  Note that this list is not identical to the
+ * types defined in descriptor.proto, which gives INT32 and SINT32 separate
+ * types (we distinguish the two with the "integer encoding" enum below). */
+typedef enum {
+  UPB_TYPE_BOOL     = 1,
+  UPB_TYPE_FLOAT    = 2,
+  UPB_TYPE_INT32    = 3,
+  UPB_TYPE_UINT32   = 4,
+  UPB_TYPE_ENUM     = 5,  /* Enum values are int32. */
+  UPB_TYPE_MESSAGE  = 6,
+  UPB_TYPE_DOUBLE   = 7,
+  UPB_TYPE_INT64    = 8,
+  UPB_TYPE_UINT64   = 9,
+  UPB_TYPE_STRING   = 10,
+  UPB_TYPE_BYTES    = 11
+} upb_fieldtype_t;
+
+/* The repeated-ness of each field; this matches descriptor.proto. */
+typedef enum {
+  UPB_LABEL_OPTIONAL = 1,
+  UPB_LABEL_REQUIRED = 2,
+  UPB_LABEL_REPEATED = 3
+} upb_label_t;
+
+/* Descriptor types, as defined in descriptor.proto. */
+typedef enum {
+  /* Old (long) names.  TODO(haberman): remove */
+  UPB_DESCRIPTOR_TYPE_DOUBLE   = 1,
+  UPB_DESCRIPTOR_TYPE_FLOAT    = 2,
+  UPB_DESCRIPTOR_TYPE_INT64    = 3,
+  UPB_DESCRIPTOR_TYPE_UINT64   = 4,
+  UPB_DESCRIPTOR_TYPE_INT32    = 5,
+  UPB_DESCRIPTOR_TYPE_FIXED64  = 6,
+  UPB_DESCRIPTOR_TYPE_FIXED32  = 7,
+  UPB_DESCRIPTOR_TYPE_BOOL     = 8,
+  UPB_DESCRIPTOR_TYPE_STRING   = 9,
+  UPB_DESCRIPTOR_TYPE_GROUP    = 10,
+  UPB_DESCRIPTOR_TYPE_MESSAGE  = 11,
+  UPB_DESCRIPTOR_TYPE_BYTES    = 12,
+  UPB_DESCRIPTOR_TYPE_UINT32   = 13,
+  UPB_DESCRIPTOR_TYPE_ENUM     = 14,
+  UPB_DESCRIPTOR_TYPE_SFIXED32 = 15,
+  UPB_DESCRIPTOR_TYPE_SFIXED64 = 16,
+  UPB_DESCRIPTOR_TYPE_SINT32   = 17,
+  UPB_DESCRIPTOR_TYPE_SINT64   = 18,
+
+  UPB_DTYPE_DOUBLE   = 1,
+  UPB_DTYPE_FLOAT    = 2,
+  UPB_DTYPE_INT64    = 3,
+  UPB_DTYPE_UINT64   = 4,
+  UPB_DTYPE_INT32    = 5,
+  UPB_DTYPE_FIXED64  = 6,
+  UPB_DTYPE_FIXED32  = 7,
+  UPB_DTYPE_BOOL     = 8,
+  UPB_DTYPE_STRING   = 9,
+  UPB_DTYPE_GROUP    = 10,
+  UPB_DTYPE_MESSAGE  = 11,
+  UPB_DTYPE_BYTES    = 12,
+  UPB_DTYPE_UINT32   = 13,
+  UPB_DTYPE_ENUM     = 14,
+  UPB_DTYPE_SFIXED32 = 15,
+  UPB_DTYPE_SFIXED64 = 16,
+  UPB_DTYPE_SINT32   = 17,
+  UPB_DTYPE_SINT64   = 18
+} upb_descriptortype_t;
+
+#define UPB_MAP_BEGIN ((size_t)-1)
+
+UPB_INLINE bool _upb_isle(void) {
+  int x = 1;
+  return *(char*)&x == 1;
+}
+
+UPB_INLINE uint32_t _upb_be_swap32(uint32_t val) {
+  if (_upb_isle()) {
+    return val;
+  } else {
+    return ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
+           ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24);
+  }
+}
+
+UPB_INLINE uint64_t _upb_be_swap64(uint64_t val) {
+  if (_upb_isle()) {
+    return val;
+  } else {
+    return ((uint64_t)_upb_be_swap32(val) << 32) | _upb_be_swap32(val >> 32);
+  }
+}
+
+UPB_INLINE int _upb_lg2ceil(int x) {
+  if (x <= 1) return 0;
+#ifdef __GNUC__
+  return 32 - __builtin_clz(x - 1);
+#else
+  int lg2 = 0;
+  while (1 << lg2 < x) lg2++;
+  return lg2;
+#endif
+}
+
+UPB_INLINE int _upb_lg2ceilsize(int x) {
+  return 1 << _upb_lg2ceil(x);
+}
+
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif  /* UPB_H_ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* upb_value ******************************************************************/
+
+/* A tagged union (stored untagged inside the table) so that we can check that
+ * clients calling table accessors are correctly typed without having to have
+ * an explosion of accessors. */
+typedef enum {
+  UPB_CTYPE_INT32    = 1,
+  UPB_CTYPE_INT64    = 2,
+  UPB_CTYPE_UINT32   = 3,
+  UPB_CTYPE_UINT64   = 4,
+  UPB_CTYPE_BOOL     = 5,
+  UPB_CTYPE_CSTR     = 6,
+  UPB_CTYPE_PTR      = 7,
+  UPB_CTYPE_CONSTPTR = 8,
+  UPB_CTYPE_FPTR     = 9,
+  UPB_CTYPE_FLOAT    = 10,
+  UPB_CTYPE_DOUBLE   = 11
+} upb_ctype_t;
+
+typedef struct {
+  uint64_t val;
+} upb_value;
+
+/* Like strdup(), which isn't always available since it's not ANSI C. */
+char *upb_strdup(const char *s, upb_alloc *a);
+/* Variant that works with a length-delimited rather than NULL-delimited string,
+ * as supported by strtable. */
+char *upb_strdup2(const char *s, size_t len, upb_alloc *a);
+
+UPB_INLINE char *upb_gstrdup(const char *s) {
+  return upb_strdup(s, &upb_alloc_global);
+}
+
+UPB_INLINE void _upb_value_setval(upb_value *v, uint64_t val) {
+  v->val = val;
+}
+
+UPB_INLINE upb_value _upb_value_val(uint64_t val) {
+  upb_value ret;
+  _upb_value_setval(&ret, val);
+  return ret;
+}
+
+/* For each value ctype, define the following set of functions:
+ *
+ * // Get/set an int32 from a upb_value.
+ * int32_t upb_value_getint32(upb_value val);
+ * void upb_value_setint32(upb_value *val, int32_t cval);
+ *
+ * // Construct a new upb_value from an int32.
+ * upb_value upb_value_int32(int32_t val); */
+#define FUNCS(name, membername, type_t, converter, proto_type) \
+  UPB_INLINE void upb_value_set ## name(upb_value *val, type_t cval) { \
+    val->val = (converter)cval; \
+  } \
+  UPB_INLINE upb_value upb_value_ ## name(type_t val) { \
+    upb_value ret; \
+    upb_value_set ## name(&ret, val); \
+    return ret; \
+  } \
+  UPB_INLINE type_t upb_value_get ## name(upb_value val) { \
+    return (type_t)(converter)val.val; \
+  }
+
+FUNCS(int32,    int32,        int32_t,      int32_t,    UPB_CTYPE_INT32)
+FUNCS(int64,    int64,        int64_t,      int64_t,    UPB_CTYPE_INT64)
+FUNCS(uint32,   uint32,       uint32_t,     uint32_t,   UPB_CTYPE_UINT32)
+FUNCS(uint64,   uint64,       uint64_t,     uint64_t,   UPB_CTYPE_UINT64)
+FUNCS(bool,     _bool,        bool,         bool,       UPB_CTYPE_BOOL)
+FUNCS(cstr,     cstr,         char*,        uintptr_t,  UPB_CTYPE_CSTR)
+FUNCS(ptr,      ptr,          void*,        uintptr_t,  UPB_CTYPE_PTR)
+FUNCS(constptr, constptr,     const void*,  uintptr_t,  UPB_CTYPE_CONSTPTR)
+FUNCS(fptr,     fptr,         upb_func*,    uintptr_t,  UPB_CTYPE_FPTR)
+
+#undef FUNCS
+
+UPB_INLINE void upb_value_setfloat(upb_value *val, float cval) {
+  memcpy(&val->val, &cval, sizeof(cval));
+}
+
+UPB_INLINE void upb_value_setdouble(upb_value *val, double cval) {
+  memcpy(&val->val, &cval, sizeof(cval));
+}
+
+UPB_INLINE upb_value upb_value_float(float cval) {
+  upb_value ret;
+  upb_value_setfloat(&ret, cval);
+  return ret;
+}
+
+UPB_INLINE upb_value upb_value_double(double cval) {
+  upb_value ret;
+  upb_value_setdouble(&ret, cval);
+  return ret;
+}
+
+#undef SET_TYPE
+
+
+/* upb_tabkey *****************************************************************/
+
+/* Either:
+ *   1. an actual integer key, or
+ *   2. a pointer to a string prefixed by its uint32_t length, owned by us.
+ *
+ * ...depending on whether this is a string table or an int table.  We would
+ * make this a union of those two types, but C89 doesn't support statically
+ * initializing a non-first union member. */
+typedef uintptr_t upb_tabkey;
+
+UPB_INLINE char *upb_tabstr(upb_tabkey key, uint32_t *len) {
+  char* mem = (char*)key;
+  if (len) memcpy(len, mem, sizeof(*len));
+  return mem + sizeof(*len);
+}
+
+UPB_INLINE upb_strview upb_tabstrview(upb_tabkey key) {
+  upb_strview ret;
+  uint32_t len;
+  ret.data = upb_tabstr(key, &len);
+  ret.size = len;
+  return ret;
+}
+
+/* upb_tabval *****************************************************************/
+
+typedef struct upb_tabval {
+  uint64_t val;
+} upb_tabval;
+
+#define UPB_TABVALUE_EMPTY_INIT  {-1}
+
+/* upb_table ******************************************************************/
+
+typedef struct _upb_tabent {
+  upb_tabkey key;
+  upb_tabval val;
+
+  /* Internal chaining.  This is const so we can create static initializers for
+   * tables.  We cast away const sometimes, but *only* when the containing
+   * upb_table is known to be non-const.  This requires a bit of care, but
+   * the subtlety is confined to table.c. */
+  const struct _upb_tabent *next;
+} upb_tabent;
+
+typedef struct {
+  size_t count;          /* Number of entries in the hash part. */
+  uint32_t mask;         /* Mask to turn hash value -> bucket. */
+  uint32_t max_count;    /* Max count before we hit our load limit. */
+  uint8_t size_lg2;      /* Size of the hashtable part is 2^size_lg2 entries. */
+
+  /* Hash table entries.
+   * Making this const isn't entirely accurate; what we really want is for it to
+   * have the same const-ness as the table it's inside.  But there's no way to
+   * declare that in C.  So we have to make it const so that we can statically
+   * initialize const hash tables.  Then we cast away const when we have to.
+   */
+  const upb_tabent *entries;
+} upb_table;
+
+typedef struct {
+  upb_table t;
+} upb_strtable;
+
+typedef struct {
+  upb_table t;              /* For entries that don't fit in the array part. */
+  const upb_tabval *array;  /* Array part of the table. See const note above. */
+  size_t array_size;        /* Array part size. */
+  size_t array_count;       /* Array part number of elements. */
+} upb_inttable;
+
+#define UPB_ARRAY_EMPTYENT -1
+
+UPB_INLINE size_t upb_table_size(const upb_table *t) {
+  if (t->size_lg2 == 0)
+    return 0;
+  else
+    return 1 << t->size_lg2;
+}
+
+/* Internal-only functions, in .h file only out of necessity. */
+UPB_INLINE bool upb_tabent_isempty(const upb_tabent *e) {
+  return e->key == 0;
+}
+
+/* Used by some of the unit tests for generic hashing functionality. */
+uint32_t upb_murmur_hash2(const void * key, size_t len, uint32_t seed);
+
+UPB_INLINE uintptr_t upb_intkey(uintptr_t key) {
+  return key;
+}
+
+UPB_INLINE uint32_t upb_inthash(uintptr_t key) {
+  return (uint32_t)key;
+}
+
+static const upb_tabent *upb_getentry(const upb_table *t, uint32_t hash) {
+  return t->entries + (hash & t->mask);
+}
+
+UPB_INLINE bool upb_arrhas(upb_tabval key) {
+  return key.val != (uint64_t)-1;
+}
+
+/* Initialize and uninitialize a table, respectively.  If memory allocation
+ * failed, false is returned that the table is uninitialized. */
+bool upb_inttable_init2(upb_inttable *table, upb_ctype_t ctype, upb_alloc *a);
+bool upb_strtable_init2(upb_strtable *table, upb_ctype_t ctype,
+                        size_t expected_size, upb_alloc *a);
+void upb_inttable_uninit2(upb_inttable *table, upb_alloc *a);
+void upb_strtable_uninit2(upb_strtable *table, upb_alloc *a);
+
+UPB_INLINE bool upb_inttable_init(upb_inttable *table, upb_ctype_t ctype) {
+  return upb_inttable_init2(table, ctype, &upb_alloc_global);
+}
+
+UPB_INLINE bool upb_strtable_init(upb_strtable *table, upb_ctype_t ctype) {
+  return upb_strtable_init2(table, ctype, 4, &upb_alloc_global);
+}
+
+UPB_INLINE void upb_inttable_uninit(upb_inttable *table) {
+  upb_inttable_uninit2(table, &upb_alloc_global);
+}
+
+UPB_INLINE void upb_strtable_uninit(upb_strtable *table) {
+  upb_strtable_uninit2(table, &upb_alloc_global);
+}
+
+/* Returns the number of values in the table. */
+size_t upb_inttable_count(const upb_inttable *t);
+UPB_INLINE size_t upb_strtable_count(const upb_strtable *t) {
+  return t->t.count;
+}
+
+void upb_inttable_packedsize(const upb_inttable *t, size_t *size);
+void upb_strtable_packedsize(const upb_strtable *t, size_t *size);
+upb_inttable *upb_inttable_pack(const upb_inttable *t, void *p, size_t *ofs,
+                                size_t size);
+upb_strtable *upb_strtable_pack(const upb_strtable *t, void *p, size_t *ofs,
+                                size_t size);
+void upb_strtable_clear(upb_strtable *t);
+
+/* Inserts the given key into the hashtable with the given value.  The key must
+ * not already exist in the hash table.  For string tables, the key must be
+ * NULL-terminated, and the table will make an internal copy of the key.
+ * Inttables must not insert a value of UINTPTR_MAX.
+ *
+ * If a table resize was required but memory allocation failed, false is
+ * returned and the table is unchanged. */
+bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val,
+                          upb_alloc *a);
+bool upb_strtable_insert3(upb_strtable *t, const char *key, size_t len,
+                          upb_value val, upb_alloc *a);
+
+UPB_INLINE bool upb_inttable_insert(upb_inttable *t, uintptr_t key,
+                                    upb_value val) {
+  return upb_inttable_insert2(t, key, val, &upb_alloc_global);
+}
+
+UPB_INLINE bool upb_strtable_insert2(upb_strtable *t, const char *key,
+                                     size_t len, upb_value val) {
+  return upb_strtable_insert3(t, key, len, val, &upb_alloc_global);
+}
+
+/* For NULL-terminated strings. */
+UPB_INLINE bool upb_strtable_insert(upb_strtable *t, const char *key,
+                                    upb_value val) {
+  return upb_strtable_insert2(t, key, strlen(key), val);
+}
+
+/* Looks up key in this table, returning "true" if the key was found.
+ * If v is non-NULL, copies the value for this key into *v. */
+bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v);
+bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
+                          upb_value *v);
+
+/* For NULL-terminated strings. */
+UPB_INLINE bool upb_strtable_lookup(const upb_strtable *t, const char *key,
+                                    upb_value *v) {
+  return upb_strtable_lookup2(t, key, strlen(key), v);
+}
+
+/* Removes an item from the table.  Returns true if the remove was successful,
+ * and stores the removed item in *val if non-NULL. */
+bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val);
+bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len,
+                          upb_value *val, upb_alloc *alloc);
+
+UPB_INLINE bool upb_strtable_remove2(upb_strtable *t, const char *key,
+                                     size_t len, upb_value *val) {
+  return upb_strtable_remove3(t, key, len, val, &upb_alloc_global);
+}
+
+/* For NULL-terminated strings. */
+UPB_INLINE bool upb_strtable_remove(upb_strtable *t, const char *key,
+                                    upb_value *v) {
+  return upb_strtable_remove2(t, key, strlen(key), v);
+}
+
+/* Updates an existing entry in an inttable.  If the entry does not exist,
+ * returns false and does nothing.  Unlike insert/remove, this does not
+ * invalidate iterators. */
+bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val);
+
+/* Convenience routines for inttables with pointer keys. */
+bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val,
+                             upb_alloc *a);
+bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val);
+bool upb_inttable_lookupptr(
+    const upb_inttable *t, const void *key, upb_value *val);
+
+UPB_INLINE bool upb_inttable_insertptr(upb_inttable *t, const void *key,
+                                       upb_value val) {
+  return upb_inttable_insertptr2(t, key, val, &upb_alloc_global);
+}
+
+/* Optimizes the table for the current set of entries, for both memory use and
+ * lookup time.  Client should call this after all entries have been inserted;
+ * inserting more entries is legal, but will likely require a table resize. */
+void upb_inttable_compact2(upb_inttable *t, upb_alloc *a);
+
+UPB_INLINE void upb_inttable_compact(upb_inttable *t) {
+  upb_inttable_compact2(t, &upb_alloc_global);
+}
+
+/* A special-case inlinable version of the lookup routine for 32-bit
+ * integers. */
+UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key,
+                                      upb_value *v) {
+  *v = upb_value_int32(0);  /* Silence compiler warnings. */
+  if (key < t->array_size) {
+    upb_tabval arrval = t->array[key];
+    if (upb_arrhas(arrval)) {
+      _upb_value_setval(v, arrval.val);
+      return true;
+    } else {
+      return false;
+    }
+  } else {
+    const upb_tabent *e;
+    if (t->t.entries == NULL) return false;
+    for (e = upb_getentry(&t->t, upb_inthash(key)); true; e = e->next) {
+      if ((uint32_t)e->key == key) {
+        _upb_value_setval(v, e->val.val);
+        return true;
+      }
+      if (e->next == NULL) return false;
+    }
+  }
+}
+
+/* Exposed for testing only. */
+bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a);
+
+/* Iterators ******************************************************************/
+
+/* Iterators for int and string tables.  We are subject to some kind of unusual
+ * design constraints:
+ *
+ * For high-level languages:
+ *  - we must be able to guarantee that we don't crash or corrupt memory even if
+ *    the program accesses an invalidated iterator.
+ *
+ * For C++11 range-based for:
+ *  - iterators must be copyable
+ *  - iterators must be comparable
+ *  - it must be possible to construct an "end" value.
+ *
+ * Iteration order is undefined.
+ *
+ * Modifying the table invalidates iterators.  upb_{str,int}table_done() is
+ * guaranteed to work even on an invalidated iterator, as long as the table it
+ * is iterating over has not been freed.  Calling next() or accessing data from
+ * an invalidated iterator yields unspecified elements from the table, but it is
+ * guaranteed not to crash and to return real table elements (except when done()
+ * is true). */
+
+
+/* upb_strtable_iter **********************************************************/
+
+/*   upb_strtable_iter i;
+ *   upb_strtable_begin(&i, t);
+ *   for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
+ *     const char *key = upb_strtable_iter_key(&i);
+ *     const upb_value val = upb_strtable_iter_value(&i);
+ *     // ...
+ *   }
+ */
+
+typedef struct {
+  const upb_strtable *t;
+  size_t index;
+} upb_strtable_iter;
+
+void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t);
+void upb_strtable_next(upb_strtable_iter *i);
+bool upb_strtable_done(const upb_strtable_iter *i);
+upb_strview upb_strtable_iter_key(const upb_strtable_iter *i);
+upb_value upb_strtable_iter_value(const upb_strtable_iter *i);
+void upb_strtable_iter_setdone(upb_strtable_iter *i);
+bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
+                               const upb_strtable_iter *i2);
+
+
+/* upb_inttable_iter **********************************************************/
+
+/*   upb_inttable_iter i;
+ *   upb_inttable_begin(&i, t);
+ *   for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+ *     uintptr_t key = upb_inttable_iter_key(&i);
+ *     upb_value val = upb_inttable_iter_value(&i);
+ *     // ...
+ *   }
+ */
+
+typedef struct {
+  const upb_inttable *t;
+  size_t index;
+  bool array_part;
+} upb_inttable_iter;
+
+UPB_INLINE const upb_tabent *str_tabent(const upb_strtable_iter *i) {
+  return &i->t->t.entries[i->index];
+}
+
+void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t);
+void upb_inttable_next(upb_inttable_iter *i);
+bool upb_inttable_done(const upb_inttable_iter *i);
+uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i);
+upb_value upb_inttable_iter_value(const upb_inttable_iter *i);
+void upb_inttable_iter_setdone(upb_inttable_iter *i);
+bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
+                               const upb_inttable_iter *i2);
+
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+
+#endif  /* UPB_TABLE_H_ */
+
+/* Must be last. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PTR_AT(msg, ofs, type) (type*)((const char*)msg + ofs)
+
+typedef void upb_msg;
+
+/** upb_msglayout *************************************************************/
+
+/* upb_msglayout represents the memory layout of a given upb_msgdef.  The
+ * members are public so generated code can initialize them, but users MUST NOT
+ * read or write any of its members. */
+
+/* These aren't real labels according to descriptor.proto, but in the table we
+ * use these for map/packed fields instead of UPB_LABEL_REPEATED. */
+enum {
+  _UPB_LABEL_MAP = 4,
+  _UPB_LABEL_PACKED = 7  /* Low 3 bits are common with UPB_LABEL_REPEATED. */
+};
+
+typedef struct {
+  uint32_t number;
+  uint16_t offset;
+  int16_t presence;       /* If >0, hasbit_index.  If <0, ~oneof_index. */
+  uint16_t submsg_index;  /* undefined if descriptortype != MESSAGE or GROUP. */
+  uint8_t descriptortype;
+  uint8_t label;          /* google.protobuf.Label or _UPB_LABEL_* above. */
+} upb_msglayout_field;
+
+struct upb_decstate;
+struct upb_msglayout;
+
+typedef const char *_upb_field_parser(struct upb_decstate *d, const char *ptr,
+                                      upb_msg *msg, intptr_t table,
+                                      uint64_t hasbits, uint64_t data);
+
+typedef struct {
+  uint64_t field_data;
+  _upb_field_parser *field_parser;
+} _upb_fasttable_entry;
+
+typedef struct upb_msglayout {
+  const struct upb_msglayout *const* submsgs;
+  const upb_msglayout_field *fields;
+  /* Must be aligned to sizeof(void*).  Doesn't include internal members like
+   * unknown fields, extension dict, pointer to msglayout, etc. */
+  uint16_t size;
+  uint16_t field_count;
+  bool extendable;
+  uint8_t table_mask;
+  /* To constant-initialize the tables of variable length, we need a flexible
+   * array member, and we need to compile in C99 mode. */
+  _upb_fasttable_entry fasttable[];
+} upb_msglayout;
+
+/** upb_msg *******************************************************************/
+
+/* Internal members of a upb_msg.  We can change this without breaking binary
+ * compatibility.  We put these before the user's data.  The user's upb_msg*
+ * points after the upb_msg_internal. */
+
+typedef struct {
+  uint32_t len;
+  uint32_t size;
+  /* Data follows. */
+} upb_msg_unknowndata;
+
+/* Used when a message is not extendable. */
+typedef struct {
+  upb_msg_unknowndata *unknown;
+} upb_msg_internal;
+
+/* Maps upb_fieldtype_t -> memory size. */
+extern char _upb_fieldtype_to_size[12];
+
+UPB_INLINE size_t upb_msg_sizeof(const upb_msglayout *l) {
+  return l->size + sizeof(upb_msg_internal);
+}
+
+UPB_INLINE upb_msg *_upb_msg_new_inl(const upb_msglayout *l, upb_arena *a) {
+  size_t size = upb_msg_sizeof(l);
+  void *mem = upb_arena_malloc(a, size);
+  upb_msg *msg;
+  if (UPB_UNLIKELY(!mem)) return NULL;
+  msg = UPB_PTR_AT(mem, sizeof(upb_msg_internal), upb_msg);
+  memset(mem, 0, size);
+  return msg;
+}
+
+/* Creates a new messages with the given layout on the given arena. */
+upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a);
+
+UPB_INLINE upb_msg_internal *upb_msg_getinternal(upb_msg *msg) {
+  ptrdiff_t size = sizeof(upb_msg_internal);
+  return (upb_msg_internal*)((char*)msg - size);
+}
+
+/* Clears the given message. */
+void _upb_msg_clear(upb_msg *msg, const upb_msglayout *l);
+
+/* Discards the unknown fields for this message only. */
+void _upb_msg_discardunknown_shallow(upb_msg *msg);
+
+/* Adds unknown data (serialized protobuf data) to the given message.  The data
+ * is copied into the message instance. */
+bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
+                         upb_arena *arena);
+
+/* Returns a reference to the message's unknown data. */
+const char *upb_msg_getunknown(const upb_msg *msg, size_t *len);
+
+/** Hasbit access *************************************************************/
+
+UPB_INLINE bool _upb_hasbit(const upb_msg *msg, size_t idx) {
+  return (*PTR_AT(msg, idx / 8, const char) & (1 << (idx % 8))) != 0;
+}
+
+UPB_INLINE void _upb_sethas(const upb_msg *msg, size_t idx) {
+  (*PTR_AT(msg, idx / 8, char)) |= (char)(1 << (idx % 8));
+}
+
+UPB_INLINE void _upb_clearhas(const upb_msg *msg, size_t idx) {
+  (*PTR_AT(msg, idx / 8, char)) &= (char)(~(1 << (idx % 8)));
+}
+
+UPB_INLINE size_t _upb_msg_hasidx(const upb_msglayout_field *f) {
+  UPB_ASSERT(f->presence > 0);
+  return f->presence;
+}
+
+UPB_INLINE bool _upb_hasbit_field(const upb_msg *msg,
+                                  const upb_msglayout_field *f) {
+  return _upb_hasbit(msg, _upb_msg_hasidx(f));
+}
+
+UPB_INLINE void _upb_sethas_field(const upb_msg *msg,
+                                  const upb_msglayout_field *f) {
+  _upb_sethas(msg, _upb_msg_hasidx(f));
+}
+
+UPB_INLINE void _upb_clearhas_field(const upb_msg *msg,
+                                    const upb_msglayout_field *f) {
+  _upb_clearhas(msg, _upb_msg_hasidx(f));
+}
+
+/** Oneof case access *********************************************************/
+
+UPB_INLINE uint32_t *_upb_oneofcase(upb_msg *msg, size_t case_ofs) {
+  return PTR_AT(msg, case_ofs, uint32_t);
+}
+
+UPB_INLINE uint32_t _upb_getoneofcase(const void *msg, size_t case_ofs) {
+  return *PTR_AT(msg, case_ofs, uint32_t);
+}
+
+UPB_INLINE size_t _upb_oneofcase_ofs(const upb_msglayout_field *f) {
+  UPB_ASSERT(f->presence < 0);
+  return ~(ptrdiff_t)f->presence;
+}
+
+UPB_INLINE uint32_t *_upb_oneofcase_field(upb_msg *msg,
+                                          const upb_msglayout_field *f) {
+  return _upb_oneofcase(msg, _upb_oneofcase_ofs(f));
+}
+
+UPB_INLINE uint32_t _upb_getoneofcase_field(const upb_msg *msg,
+                                            const upb_msglayout_field *f) {
+  return _upb_getoneofcase(msg, _upb_oneofcase_ofs(f));
+}
+
+UPB_INLINE bool _upb_has_submsg_nohasbit(const upb_msg *msg, size_t ofs) {
+  return *PTR_AT(msg, ofs, const upb_msg*) != NULL;
+}
+
+UPB_INLINE bool _upb_isrepeated(const upb_msglayout_field *field) {
+  return (field->label & 3) == UPB_LABEL_REPEATED;
+}
+
+UPB_INLINE bool _upb_repeated_or_map(const upb_msglayout_field *field) {
+  return field->label >= UPB_LABEL_REPEATED;
+}
+
+/** upb_array *****************************************************************/
+
+/* Our internal representation for repeated fields.  */
+typedef struct {
+  uintptr_t data;   /* Tagged ptr: low 3 bits of ptr are lg2(elem size). */
+  size_t len;   /* Measured in elements. */
+  size_t size;  /* Measured in elements. */
+  uint64_t junk;
+} upb_array;
+
+UPB_INLINE const void *_upb_array_constptr(const upb_array *arr) {
+  UPB_ASSERT((arr->data & 7) <= 4);
+  return (void*)(arr->data & ~(uintptr_t)7);
+}
+
+UPB_INLINE uintptr_t _upb_array_tagptr(void* ptr, int elem_size_lg2) {
+  UPB_ASSERT(elem_size_lg2 <= 4);
+  return (uintptr_t)ptr | elem_size_lg2;
+}
+
+UPB_INLINE void *_upb_array_ptr(upb_array *arr) {
+  return (void*)_upb_array_constptr(arr);
+}
+
+UPB_INLINE uintptr_t _upb_tag_arrptr(void* ptr, int elem_size_lg2) {
+  UPB_ASSERT(elem_size_lg2 <= 4);
+  UPB_ASSERT(((uintptr_t)ptr & 7) == 0);
+  return (uintptr_t)ptr | (unsigned)elem_size_lg2;
+}
+
+UPB_INLINE upb_array *_upb_array_new(upb_arena *a, size_t init_size,
+                                     int elem_size_lg2) {
+  const size_t arr_size = UPB_ALIGN_UP(sizeof(upb_array), 8);
+  const size_t bytes = sizeof(upb_array) + (init_size << elem_size_lg2);
+  upb_array *arr = (upb_array*)upb_arena_malloc(a, bytes);
+  if (!arr) return NULL;
+  arr->data = _upb_tag_arrptr(UPB_PTR_AT(arr, arr_size, void), elem_size_lg2);
+  arr->len = 0;
+  arr->size = init_size;
+  return arr;
+}
+
+/* Resizes the capacity of the array to be at least min_size. */
+bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena);
+
+/* Fallback functions for when the accessors require a resize. */
+void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size,
+                                 int elem_size_lg2, upb_arena *arena);
+bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value,
+                                int elem_size_lg2, upb_arena *arena);
+
+UPB_INLINE bool _upb_array_reserve(upb_array *arr, size_t size,
+                                   upb_arena *arena) {
+  if (arr->size < size) return _upb_array_realloc(arr, size, arena);
+  return true;
+}
+
+UPB_INLINE bool _upb_array_resize(upb_array *arr, size_t size,
+                                  upb_arena *arena) {
+  if (!_upb_array_reserve(arr, size, arena)) return false;
+  arr->len = size;
+  return true;
+}
+
+UPB_INLINE const void *_upb_array_accessor(const void *msg, size_t ofs,
+                                           size_t *size) {
+  const upb_array *arr = *PTR_AT(msg, ofs, const upb_array*);
+  if (arr) {
+    if (size) *size = arr->len;
+    return _upb_array_constptr(arr);
+  } else {
+    if (size) *size = 0;
+    return NULL;
+  }
+}
+
+UPB_INLINE void *_upb_array_mutable_accessor(void *msg, size_t ofs,
+                                             size_t *size) {
+  upb_array *arr = *PTR_AT(msg, ofs, upb_array*);
+  if (arr) {
+    if (size) *size = arr->len;
+    return _upb_array_ptr(arr);
+  } else {
+    if (size) *size = 0;
+    return NULL;
+  }
+}
+
+UPB_INLINE void *_upb_array_resize_accessor2(void *msg, size_t ofs, size_t size,
+                                             int elem_size_lg2,
+                                             upb_arena *arena) {
+  upb_array **arr_ptr = PTR_AT(msg, ofs, upb_array *);
+  upb_array *arr = *arr_ptr;
+  if (!arr || arr->size < size) {
+    return _upb_array_resize_fallback(arr_ptr, size, elem_size_lg2, arena);
+  }
+  arr->len = size;
+  return _upb_array_ptr(arr);
+}
+
+UPB_INLINE bool _upb_array_append_accessor2(void *msg, size_t ofs,
+                                            int elem_size_lg2,
+                                            const void *value,
+                                            upb_arena *arena) {
+  upb_array **arr_ptr = PTR_AT(msg, ofs, upb_array *);
+  size_t elem_size = 1 << elem_size_lg2;
+  upb_array *arr = *arr_ptr;
+  void *ptr;
+  if (!arr || arr->len == arr->size) {
+    return _upb_array_append_fallback(arr_ptr, value, elem_size_lg2, arena);
+  }
+  ptr = _upb_array_ptr(arr);
+  memcpy(PTR_AT(ptr, arr->len * elem_size, char), value, elem_size);
+  arr->len++;
+  return true;
+}
+
+/* Used by old generated code, remove once all code has been regenerated. */
+UPB_INLINE int _upb_sizelg2(upb_fieldtype_t type) {
+  switch (type) {
+    case UPB_TYPE_BOOL:
+      return 0;
+    case UPB_TYPE_FLOAT:
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_ENUM:
+      return 2;
+    case UPB_TYPE_MESSAGE:
+      return UPB_SIZE(2, 3);
+    case UPB_TYPE_DOUBLE:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT64:
+      return 3;
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+      return UPB_SIZE(3, 4);
+  }
+  UPB_UNREACHABLE();
+}
+UPB_INLINE void *_upb_array_resize_accessor(void *msg, size_t ofs, size_t size,
+                                             upb_fieldtype_t type,
+                                             upb_arena *arena) {
+  return _upb_array_resize_accessor2(msg, ofs, size, _upb_sizelg2(type), arena);
+}
+UPB_INLINE bool _upb_array_append_accessor(void *msg, size_t ofs,
+                                            size_t elem_size, upb_fieldtype_t type,
+                                            const void *value,
+                                            upb_arena *arena) {
+  (void)elem_size;
+  return _upb_array_append_accessor2(msg, ofs, _upb_sizelg2(type), value,
+                                     arena);
+}
+
+/** upb_map *******************************************************************/
+
+/* Right now we use strmaps for everything.  We'll likely want to use
+ * integer-specific maps for integer-keyed maps.*/
+typedef struct {
+  /* Size of key and val, based on the map type.  Strings are represented as '0'
+   * because they must be handled specially. */
+  char key_size;
+  char val_size;
+
+  upb_strtable table;
+} upb_map;
+
+/* Map entries aren't actually stored, they are only used during parsing.  For
+ * parsing, it helps a lot if all map entry messages have the same layout.
+ * The compiler and def.c must ensure that all map entries have this layout. */
+typedef struct {
+  upb_msg_internal internal;
+  union {
+    upb_strview str;  /* For str/bytes. */
+    upb_value val;    /* For all other types. */
+  } k;
+  union {
+    upb_strview str;  /* For str/bytes. */
+    upb_value val;    /* For all other types. */
+  } v;
+} upb_map_entry;
+
+/* Creates a new map on the given arena with this key/value type. */
+upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size);
+
+/* Converting between internal table representation and user values.
+ *
+ * _upb_map_tokey() and _upb_map_fromkey() are inverses.
+ * _upb_map_tovalue() and _upb_map_fromvalue() are inverses.
+ *
+ * These functions account for the fact that strings are treated differently
+ * from other types when stored in a map.
+ */
+
+UPB_INLINE upb_strview _upb_map_tokey(const void *key, size_t size) {
+  if (size == UPB_MAPTYPE_STRING) {
+    return *(upb_strview*)key;
+  } else {
+    return upb_strview_make((const char*)key, size);
+  }
+}
+
+UPB_INLINE void _upb_map_fromkey(upb_strview key, void* out, size_t size) {
+  if (size == UPB_MAPTYPE_STRING) {
+    memcpy(out, &key, sizeof(key));
+  } else {
+    memcpy(out, key.data, size);
+  }
+}
+
+UPB_INLINE bool _upb_map_tovalue(const void *val, size_t size, upb_value *msgval,
+                                 upb_arena *a) {
+  if (size == UPB_MAPTYPE_STRING) {
+    upb_strview *strp = (upb_strview*)upb_arena_malloc(a, sizeof(*strp));
+    if (!strp) return false;
+    *strp = *(upb_strview*)val;
+    *msgval = upb_value_ptr(strp);
+  } else {
+    memcpy(msgval, val, size);
+  }
+  return true;
+}
+
+UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) {
+  if (size == UPB_MAPTYPE_STRING) {
+    const upb_strview *strp = (const upb_strview*)upb_value_getptr(val);
+    memcpy(out, strp, sizeof(upb_strview));
+  } else {
+    memcpy(out, &val, size);
+  }
+}
+
+/* Map operations, shared by reflection and generated code. */
+
+UPB_INLINE size_t _upb_map_size(const upb_map *map) {
+  return map->table.t.count;
+}
+
+UPB_INLINE bool _upb_map_get(const upb_map *map, const void *key,
+                             size_t key_size, void *val, size_t val_size) {
+  upb_value tabval;
+  upb_strview k = _upb_map_tokey(key, key_size);
+  bool ret = upb_strtable_lookup2(&map->table, k.data, k.size, &tabval);
+  if (ret && val) {
+    _upb_map_fromvalue(tabval, val, val_size);
+  }
+  return ret;
+}
+
+UPB_INLINE void* _upb_map_next(const upb_map *map, size_t *iter) {
+  upb_strtable_iter it;
+  it.t = &map->table;
+  it.index = *iter;
+  upb_strtable_next(&it);
+  *iter = it.index;
+  if (upb_strtable_done(&it)) return NULL;
+  return (void*)str_tabent(&it);
+}
+
+UPB_INLINE bool _upb_map_set(upb_map *map, const void *key, size_t key_size,
+                             void *val, size_t val_size, upb_arena *arena) {
+  upb_strview strkey = _upb_map_tokey(key, key_size);
+  upb_value tabval = {0};
+  if (!_upb_map_tovalue(val, val_size, &tabval, arena)) return false;
+  upb_alloc *a = upb_arena_alloc(arena);
+
+  /* TODO(haberman): add overwrite operation to minimize number of lookups. */
+  upb_strtable_remove3(&map->table, strkey.data, strkey.size, NULL, a);
+  return upb_strtable_insert3(&map->table, strkey.data, strkey.size, tabval, a);
+}
+
+UPB_INLINE bool _upb_map_delete(upb_map *map, const void *key, size_t key_size) {
+  upb_strview k = _upb_map_tokey(key, key_size);
+  return upb_strtable_remove3(&map->table, k.data, k.size, NULL, NULL);
+}
+
+UPB_INLINE void _upb_map_clear(upb_map *map) {
+  upb_strtable_clear(&map->table);
+}
+
+/* Message map operations, these get the map from the message first. */
+
+UPB_INLINE size_t _upb_msg_map_size(const upb_msg *msg, size_t ofs) {
+  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
+  return map ? _upb_map_size(map) : 0;
+}
+
+UPB_INLINE bool _upb_msg_map_get(const upb_msg *msg, size_t ofs,
+                                 const void *key, size_t key_size, void *val,
+                                 size_t val_size) {
+  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
+  if (!map) return false;
+  return _upb_map_get(map, key, key_size, val, val_size);
+}
+
+UPB_INLINE void *_upb_msg_map_next(const upb_msg *msg, size_t ofs,
+                                   size_t *iter) {
+  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
+  if (!map) return NULL;
+  return _upb_map_next(map, iter);
+}
+
+UPB_INLINE bool _upb_msg_map_set(upb_msg *msg, size_t ofs, const void *key,
+                                 size_t key_size, void *val, size_t val_size,
+                                 upb_arena *arena) {
+  upb_map **map = PTR_AT(msg, ofs, upb_map *);
+  if (!*map) {
+    *map = _upb_map_new(arena, key_size, val_size);
+  }
+  return _upb_map_set(*map, key, key_size, val, val_size, arena);
+}
+
+UPB_INLINE bool _upb_msg_map_delete(upb_msg *msg, size_t ofs, const void *key,
+                                    size_t key_size) {
+  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
+  if (!map) return false;
+  return _upb_map_delete(map, key, key_size);
+}
+
+UPB_INLINE void _upb_msg_map_clear(upb_msg *msg, size_t ofs) {
+  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
+  if (!map) return;
+  _upb_map_clear(map);
+}
+
+/* Accessing map key/value from a pointer, used by generated code only. */
+
+UPB_INLINE void _upb_msg_map_key(const void* msg, void* key, size_t size) {
+  const upb_tabent *ent = (const upb_tabent*)msg;
+  uint32_t u32len;
+  upb_strview k;
+  k.data = upb_tabstr(ent->key, &u32len);
+  k.size = u32len;
+  _upb_map_fromkey(k, key, size);
+}
+
+UPB_INLINE void _upb_msg_map_value(const void* msg, void* val, size_t size) {
+  const upb_tabent *ent = (const upb_tabent*)msg;
+  upb_value v;
+  _upb_value_setval(&v, ent->val.val);
+  _upb_map_fromvalue(v, val, size);
+}
+
+UPB_INLINE void _upb_msg_map_set_value(void* msg, const void* val, size_t size) {
+  upb_tabent *ent = (upb_tabent*)msg;
+  /* This is like _upb_map_tovalue() except the entry already exists so we can
+   * reuse the allocated upb_strview for string fields. */
+  if (size == UPB_MAPTYPE_STRING) {
+    upb_strview *strp = (upb_strview*)(uintptr_t)ent->val.val;
+    memcpy(strp, val, sizeof(*strp));
+  } else {
+    memcpy(&ent->val.val, val, size);
+  }
+}
+
+/** _upb_mapsorter *************************************************************/
+
+/* _upb_mapsorter sorts maps and provides ordered iteration over the entries.
+ * Since maps can be recursive (map values can be messages which contain other maps).
+ * _upb_mapsorter can contain a stack of maps. */
+
+typedef struct {
+  upb_tabent const**entries;
+  int size;
+  int cap;
+} _upb_mapsorter;
+
+typedef struct {
+  int start;
+  int pos;
+  int end;
+} _upb_sortedmap;
+
+UPB_INLINE void _upb_mapsorter_init(_upb_mapsorter *s) {
+  s->entries = NULL;
+  s->size = 0;
+  s->cap = 0;
+}
+
+UPB_INLINE void _upb_mapsorter_destroy(_upb_mapsorter *s) {
+  if (s->entries) free(s->entries);
+}
+
+bool _upb_mapsorter_pushmap(_upb_mapsorter *s, upb_descriptortype_t key_type,
+                            const upb_map *map, _upb_sortedmap *sorted);
+
+UPB_INLINE void _upb_mapsorter_popmap(_upb_mapsorter *s, _upb_sortedmap *sorted) {
+  s->size = sorted->start;
+}
+
+UPB_INLINE bool _upb_sortedmap_next(_upb_mapsorter *s, const upb_map *map,
+                                    _upb_sortedmap *sorted,
+                                    upb_map_entry *ent) {
+  if (sorted->pos == sorted->end) return false;
+  const upb_tabent *tabent = s->entries[sorted->pos++];
+  upb_strview key = upb_tabstrview(tabent->key);
+  _upb_map_fromkey(key, &ent->k, map->key_size);
+  upb_value val = {tabent->val.val};
+  _upb_map_fromvalue(val, &ent->v, map->val_size);
+  return true;
+}
+
+#undef PTR_AT
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+
+#endif /* UPB_MSG_H_ */
+
+/* Must be last. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+  /* If set, strings will alias the input buffer instead of copying into the
+   * arena. */
+  UPB_DECODE_ALIAS = 1,
+};
+
+#define UPB_DECODE_MAXDEPTH(depth) ((depth) << 16)
+
+bool _upb_decode(const char *buf, size_t size, upb_msg *msg,
+                 const upb_msglayout *l, upb_arena *arena, int options);
+
+UPB_INLINE
+bool upb_decode(const char *buf, size_t size, upb_msg *msg,
+                const upb_msglayout *l, upb_arena *arena) {
+  return _upb_decode(buf, size, msg, l, arena, 0);
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+
+#endif  /* UPB_DECODE_H_ */
+/*
+** Internal implementation details of the decoder that are shared between
+** decode.c and decode_fast.c.
+*/
+
+#ifndef UPB_DECODE_INT_H_
+#define UPB_DECODE_INT_H_
+
+#include <setjmp.h>
+
+
+#ifndef UPB_INT_H_
+#define UPB_INT_H_
+
+
+struct mem_block;
+typedef struct mem_block mem_block;
+
+struct upb_arena {
+  _upb_arena_head head;
+  uint32_t *cleanups;
+
+  /* Allocator to allocate arena blocks.  We are responsible for freeing these
+   * when we are destroyed. */
+  upb_alloc *block_alloc;
+  uint32_t last_size;
+
+  /* When multiple arenas are fused together, each arena points to a parent
+   * arena (root points to itself). The root tracks how many live arenas
+   * reference it. */
+  uint32_t refcount;  /* Only used when a->parent == a */
+  struct upb_arena *parent;
+
+  /* Linked list of blocks to free/cleanup. */
+  mem_block *freelist, *freelist_tail;
+};
+
+#endif  /* UPB_INT_H_ */
+
+/* Must be last. */
+
+#define DECODE_NOGROUP (uint32_t)-1
+
+typedef struct upb_decstate {
+  const char *end;         /* Can read up to 16 bytes slop beyond this. */
+  const char *limit_ptr;   /* = end + UPB_MIN(limit, 0) */
+  upb_msg *unknown_msg;    /* If non-NULL, add unknown data at buffer flip. */
+  const char *unknown;     /* Start of unknown data. */
+  int limit;               /* Submessage limit relative to end. */
+  int depth;
+  uint32_t end_group;   /* field number of END_GROUP tag, else DECODE_NOGROUP */
+  bool alias;
+  char patch[32];
+  upb_arena arena;
+  jmp_buf err;
+} upb_decstate;
+
+/* Error function that will abort decoding with longjmp(). We can't declare this
+ * UPB_NORETURN, even though it is appropriate, because if we do then compilers
+ * will "helpfully" refuse to tailcall to it
+ * (see: https://stackoverflow.com/a/55657013), which will defeat a major goal
+ * of our optimizations. That is also why we must declare it in a separate file,
+ * otherwise the compiler will see that it calls longjmp() and deduce that it is
+ * noreturn. */
+const char *fastdecode_err(upb_decstate *d);
+
+extern const uint8_t upb_utf8_offsets[];
+
+UPB_INLINE
+bool decode_verifyutf8_inl(const char *buf, int len) {
+  int i, j;
+  uint8_t offset;
+
+  i = 0;
+  while (i < len) {
+    offset = upb_utf8_offsets[(uint8_t)buf[i]];
+    if (offset == 0 || i + offset > len) {
+      return false;
+    }
+    for (j = i + 1; j < i + offset; j++) {
+      if ((buf[j] & 0xc0) != 0x80) {
+        return false;
+      }
+    }
+    i += offset;
+  }
+  return i == len;
+}
+
+/* x86-64 pointers always have the high 16 bits matching. So we can shift
+ * left 8 and right 8 without loss of information. */
+UPB_INLINE intptr_t decode_totable(const upb_msglayout *tablep) {
+  return ((intptr_t)tablep << 8) | tablep->table_mask;
+}
+
+UPB_INLINE const upb_msglayout *decode_totablep(intptr_t table) {
+  return (const upb_msglayout*)(table >> 8);
+}
+
+UPB_INLINE
+const char *decode_isdonefallback_inl(upb_decstate *d, const char *ptr,
+                                      int overrun) {
+  if (overrun < d->limit) {
+    /* Need to copy remaining data into patch buffer. */
+    UPB_ASSERT(overrun < 16);
+    if (d->unknown_msg) {
+      if (!_upb_msg_addunknown(d->unknown_msg, d->unknown, ptr - d->unknown,
+                               &d->arena)) {
+        return NULL;
+      }
+      d->unknown = &d->patch[0] + overrun;
+    }
+    memset(d->patch + 16, 0, 16);
+    memcpy(d->patch, d->end, 16);
+    ptr = &d->patch[0] + overrun;
+    d->end = &d->patch[16];
+    d->limit -= 16;
+    d->limit_ptr = d->end + d->limit;
+    d->alias = false;
+    UPB_ASSERT(ptr < d->limit_ptr);
+    return ptr;
+  } else {
+    return NULL;
+  }
+}
+
+const char *decode_isdonefallback(upb_decstate *d, const char *ptr,
+                                  int overrun);
+
+UPB_INLINE
+bool decode_isdone(upb_decstate *d, const char **ptr) {
+  int overrun = *ptr - d->end;
+  if (UPB_LIKELY(*ptr < d->limit_ptr)) {
+    return false;
+  } else if (UPB_LIKELY(overrun == d->limit)) {
+    return true;
+  } else {
+    *ptr = decode_isdonefallback(d, *ptr, overrun);
+    return false;
+  }
+}
+
+UPB_INLINE
+const char *fastdecode_tagdispatch(upb_decstate *d, const char *ptr,
+                                    upb_msg *msg, intptr_t table,
+                                    uint64_t hasbits, uint32_t tag) {
+  const upb_msglayout *table_p = decode_totablep(table);
+  uint8_t mask = table;
+  uint64_t data;
+  size_t idx = tag & mask;
+  UPB_ASSUME((idx & 7) == 0);
+  idx >>= 3;
+  data = table_p->fasttable[idx].field_data ^ tag;
+  return table_p->fasttable[idx].field_parser(d, ptr, msg, table, hasbits, data);
+}
+
+UPB_INLINE uint32_t fastdecode_loadtag(const char* ptr) {
+  uint16_t tag;
+  memcpy(&tag, ptr, 2);
+  return tag;
+}
+
+UPB_INLINE void decode_checklimit(upb_decstate *d) {
+  UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit));
+}
+
+UPB_INLINE int decode_pushlimit(upb_decstate *d, const char *ptr, int size) {
+  int limit = size + (int)(ptr - d->end);
+  int delta = d->limit - limit;
+  decode_checklimit(d);
+  d->limit = limit;
+  d->limit_ptr = d->end + UPB_MIN(0, limit);
+  decode_checklimit(d);
+  return delta;
+}
+
+UPB_INLINE void decode_poplimit(upb_decstate *d, const char *ptr,
+                                int saved_delta) {
+  UPB_ASSERT(ptr - d->end == d->limit);
+  decode_checklimit(d);
+  d->limit += saved_delta;
+  d->limit_ptr = d->end + UPB_MIN(0, d->limit);
+  decode_checklimit(d);
+}
+
+
+#endif  /* UPB_DECODE_INT_H_ */
+/*
+** upb_encode: parsing into a upb_msg using a upb_msglayout.
+*/
+
+#ifndef UPB_ENCODE_H_
+#define UPB_ENCODE_H_
+
+
+/* Must be last. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+  /* If set, the results of serializing will be deterministic across all
+   * instances of this binary. There are no guarantees across different
+   * binary builds.
+   *
+   * If your proto contains maps, the encoder will need to malloc()/free()
+   * memory during encode. */
+  UPB_ENCODE_DETERMINISTIC = 1,
+
+  /* When set, unknown fields are not printed. */
+  UPB_ENCODE_SKIPUNKNOWN = 2,
+};
+
+#define UPB_ENCODE_MAXDEPTH(depth) ((depth) << 16)
+
+char *upb_encode_ex(const void *msg, const upb_msglayout *l, int options,
+                    upb_arena *arena, size_t *size);
+
+UPB_INLINE char *upb_encode(const void *msg, const upb_msglayout *l,
+                            upb_arena *arena, size_t *size) {
+  return upb_encode_ex(msg, l, 0, arena, size);
+}
+
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif  /* UPB_ENCODE_H_ */
+// These are the specialized field parser functions for the fast parser.
+// Generated tables will refer to these by name.
+//
+// The function names are encoded with names like:
+//
+//   //  123 4
+//   upb_pss_1bt();   // Parse singular string, 1 byte tag.
+//
+// In position 1:
+//   - 'p' for parse, most function use this
+//   - 'c' for copy, for when we are copying strings instead of aliasing
+//
+// In position 2 (cardinality):
+//   - 's' for singular, with or without hasbit
+//   - 'o' for oneof
+//   - 'r' for non-packed repeated
+//   - 'p' for packed repeated
+//
+// In position 3 (type):
+//   - 'b1' for bool
+//   - 'v4' for 4-byte varint
+//   - 'v8' for 8-byte varint
+//   - 'z4' for zig-zag-encoded 4-byte varint
+//   - 'z8' for zig-zag-encoded 8-byte varint
+//   - 'f4' for 4-byte fixed
+//   - 'f8' for 8-byte fixed
+//   - 'm' for sub-message
+//   - 's' for string (validate UTF-8)
+//   - 'b' for bytes
+//
+// In position 4 (tag length):
+//   - '1' for one-byte tags (field numbers 1-15)
+//   - '2' for two-byte tags (field numbers 16-2048)
+
+#ifndef UPB_DECODE_FAST_H_
+#define UPB_DECODE_FAST_H_
+
+
+struct upb_decstate;
+
+// The fallback, generic parsing function that can handle any field type.
+// This just uses the regular (non-fast) parser to parse a single field.
+const char *fastdecode_generic(struct upb_decstate *d, const char *ptr,
+                               upb_msg *msg, intptr_t table, uint64_t hasbits,
+                               uint64_t data);
+
+#define UPB_PARSE_PARAMS                                                 \
+  struct upb_decstate *d, const char *ptr, upb_msg *msg, intptr_t table, \
+      uint64_t hasbits, uint64_t data
+
+/* primitive fields ***********************************************************/
+
+#define F(card, type, valbytes, tagbytes) \
+  const char *upb_p##card##type##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS);
+
+#define TYPES(card, tagbytes) \
+  F(card, b, 1, tagbytes)     \
+  F(card, v, 4, tagbytes)     \
+  F(card, v, 8, tagbytes)     \
+  F(card, z, 4, tagbytes)     \
+  F(card, z, 8, tagbytes)     \
+  F(card, f, 4, tagbytes)     \
+  F(card, f, 8, tagbytes)
+
+#define TAGBYTES(card) \
+  TYPES(card, 1)       \
+  TYPES(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+TAGBYTES(p)
+
+#undef F
+#undef TYPES
+#undef TAGBYTES
+
+/* string fields **************************************************************/
+
+#define F(card, tagbytes, type)                                     \
+  const char *upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS); \
+  const char *upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS);
+
+#define UTF8(card, tagbytes) \
+  F(card, tagbytes, s)       \
+  F(card, tagbytes, b)
+
+#define TAGBYTES(card) \
+  UTF8(card, 1)        \
+  UTF8(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+
+#undef F
+#undef TAGBYTES
+
+/* sub-message fields *********************************************************/
+
+#define F(card, tagbytes, size_ceil, ceil_arg) \
+  const char *upb_p##card##m_##tagbytes##bt_max##size_ceil##b(UPB_PARSE_PARAMS);
+
+#define SIZES(card, tagbytes) \
+  F(card, tagbytes, 64, 64) \
+  F(card, tagbytes, 128, 128) \
+  F(card, tagbytes, 192, 192) \
+  F(card, tagbytes, 256, 256) \
+  F(card, tagbytes, max, -1)
+
+#define TAGBYTES(card) \
+  SIZES(card, 1) \
+  SIZES(card, 2)
+
+TAGBYTES(s)
+TAGBYTES(o)
+TAGBYTES(r)
+
+#undef TAGBYTES
+#undef SIZES
+#undef F
+
+#undef UPB_PARSE_PARAMS
+
+#endif  /* UPB_DECODE_FAST_H_ */
+/* This file was generated by upbc (the upb compiler) from the input
+ * file:
+ *
+ *     google/protobuf/descriptor.proto
+ *
+ * Do not edit -- your changes will be discarded when the file is
+ * regenerated. */
+
+#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_
+#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct google_protobuf_FileDescriptorSet;
+struct google_protobuf_FileDescriptorProto;
+struct google_protobuf_DescriptorProto;
+struct google_protobuf_DescriptorProto_ExtensionRange;
+struct google_protobuf_DescriptorProto_ReservedRange;
+struct google_protobuf_ExtensionRangeOptions;
+struct google_protobuf_FieldDescriptorProto;
+struct google_protobuf_OneofDescriptorProto;
+struct google_protobuf_EnumDescriptorProto;
+struct google_protobuf_EnumDescriptorProto_EnumReservedRange;
+struct google_protobuf_EnumValueDescriptorProto;
+struct google_protobuf_ServiceDescriptorProto;
+struct google_protobuf_MethodDescriptorProto;
+struct google_protobuf_FileOptions;
+struct google_protobuf_MessageOptions;
+struct google_protobuf_FieldOptions;
+struct google_protobuf_OneofOptions;
+struct google_protobuf_EnumOptions;
+struct google_protobuf_EnumValueOptions;
+struct google_protobuf_ServiceOptions;
+struct google_protobuf_MethodOptions;
+struct google_protobuf_UninterpretedOption;
+struct google_protobuf_UninterpretedOption_NamePart;
+struct google_protobuf_SourceCodeInfo;
+struct google_protobuf_SourceCodeInfo_Location;
+struct google_protobuf_GeneratedCodeInfo;
+struct google_protobuf_GeneratedCodeInfo_Annotation;
+typedef struct google_protobuf_FileDescriptorSet google_protobuf_FileDescriptorSet;
+typedef struct google_protobuf_FileDescriptorProto google_protobuf_FileDescriptorProto;
+typedef struct google_protobuf_DescriptorProto google_protobuf_DescriptorProto;
+typedef struct google_protobuf_DescriptorProto_ExtensionRange google_protobuf_DescriptorProto_ExtensionRange;
+typedef struct google_protobuf_DescriptorProto_ReservedRange google_protobuf_DescriptorProto_ReservedRange;
+typedef struct google_protobuf_ExtensionRangeOptions google_protobuf_ExtensionRangeOptions;
+typedef struct google_protobuf_FieldDescriptorProto google_protobuf_FieldDescriptorProto;
+typedef struct google_protobuf_OneofDescriptorProto google_protobuf_OneofDescriptorProto;
+typedef struct google_protobuf_EnumDescriptorProto google_protobuf_EnumDescriptorProto;
+typedef struct google_protobuf_EnumDescriptorProto_EnumReservedRange google_protobuf_EnumDescriptorProto_EnumReservedRange;
+typedef struct google_protobuf_EnumValueDescriptorProto google_protobuf_EnumValueDescriptorProto;
+typedef struct google_protobuf_ServiceDescriptorProto google_protobuf_ServiceDescriptorProto;
+typedef struct google_protobuf_MethodDescriptorProto google_protobuf_MethodDescriptorProto;
+typedef struct google_protobuf_FileOptions google_protobuf_FileOptions;
+typedef struct google_protobuf_MessageOptions google_protobuf_MessageOptions;
+typedef struct google_protobuf_FieldOptions google_protobuf_FieldOptions;
+typedef struct google_protobuf_OneofOptions google_protobuf_OneofOptions;
+typedef struct google_protobuf_EnumOptions google_protobuf_EnumOptions;
+typedef struct google_protobuf_EnumValueOptions google_protobuf_EnumValueOptions;
+typedef struct google_protobuf_ServiceOptions google_protobuf_ServiceOptions;
+typedef struct google_protobuf_MethodOptions google_protobuf_MethodOptions;
+typedef struct google_protobuf_UninterpretedOption google_protobuf_UninterpretedOption;
+typedef struct google_protobuf_UninterpretedOption_NamePart google_protobuf_UninterpretedOption_NamePart;
+typedef struct google_protobuf_SourceCodeInfo google_protobuf_SourceCodeInfo;
+typedef struct google_protobuf_SourceCodeInfo_Location google_protobuf_SourceCodeInfo_Location;
+typedef struct google_protobuf_GeneratedCodeInfo google_protobuf_GeneratedCodeInfo;
+typedef struct google_protobuf_GeneratedCodeInfo_Annotation google_protobuf_GeneratedCodeInfo_Annotation;
+extern const upb_msglayout google_protobuf_FileDescriptorSet_msginit;
+extern const upb_msglayout google_protobuf_FileDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_DescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit;
+extern const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit;
+extern const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit;
+extern const upb_msglayout google_protobuf_FieldDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_OneofDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_EnumDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit;
+extern const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_MethodDescriptorProto_msginit;
+extern const upb_msglayout google_protobuf_FileOptions_msginit;
+extern const upb_msglayout google_protobuf_MessageOptions_msginit;
+extern const upb_msglayout google_protobuf_FieldOptions_msginit;
+extern const upb_msglayout google_protobuf_OneofOptions_msginit;
+extern const upb_msglayout google_protobuf_EnumOptions_msginit;
+extern const upb_msglayout google_protobuf_EnumValueOptions_msginit;
+extern const upb_msglayout google_protobuf_ServiceOptions_msginit;
+extern const upb_msglayout google_protobuf_MethodOptions_msginit;
+extern const upb_msglayout google_protobuf_UninterpretedOption_msginit;
+extern const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit;
+extern const upb_msglayout google_protobuf_SourceCodeInfo_msginit;
+extern const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit;
+extern const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit;
+extern const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit;
+
+typedef enum {
+  google_protobuf_FieldDescriptorProto_LABEL_OPTIONAL = 1,
+  google_protobuf_FieldDescriptorProto_LABEL_REQUIRED = 2,
+  google_protobuf_FieldDescriptorProto_LABEL_REPEATED = 3
+} google_protobuf_FieldDescriptorProto_Label;
+
+typedef enum {
+  google_protobuf_FieldDescriptorProto_TYPE_DOUBLE = 1,
+  google_protobuf_FieldDescriptorProto_TYPE_FLOAT = 2,
+  google_protobuf_FieldDescriptorProto_TYPE_INT64 = 3,
+  google_protobuf_FieldDescriptorProto_TYPE_UINT64 = 4,
+  google_protobuf_FieldDescriptorProto_TYPE_INT32 = 5,
+  google_protobuf_FieldDescriptorProto_TYPE_FIXED64 = 6,
+  google_protobuf_FieldDescriptorProto_TYPE_FIXED32 = 7,
+  google_protobuf_FieldDescriptorProto_TYPE_BOOL = 8,
+  google_protobuf_FieldDescriptorProto_TYPE_STRING = 9,
+  google_protobuf_FieldDescriptorProto_TYPE_GROUP = 10,
+  google_protobuf_FieldDescriptorProto_TYPE_MESSAGE = 11,
+  google_protobuf_FieldDescriptorProto_TYPE_BYTES = 12,
+  google_protobuf_FieldDescriptorProto_TYPE_UINT32 = 13,
+  google_protobuf_FieldDescriptorProto_TYPE_ENUM = 14,
+  google_protobuf_FieldDescriptorProto_TYPE_SFIXED32 = 15,
+  google_protobuf_FieldDescriptorProto_TYPE_SFIXED64 = 16,
+  google_protobuf_FieldDescriptorProto_TYPE_SINT32 = 17,
+  google_protobuf_FieldDescriptorProto_TYPE_SINT64 = 18
+} google_protobuf_FieldDescriptorProto_Type;
+
+typedef enum {
+  google_protobuf_FieldOptions_STRING = 0,
+  google_protobuf_FieldOptions_CORD = 1,
+  google_protobuf_FieldOptions_STRING_PIECE = 2
+} google_protobuf_FieldOptions_CType;
+
+typedef enum {
+  google_protobuf_FieldOptions_JS_NORMAL = 0,
+  google_protobuf_FieldOptions_JS_STRING = 1,
+  google_protobuf_FieldOptions_JS_NUMBER = 2
+} google_protobuf_FieldOptions_JSType;
+
+typedef enum {
+  google_protobuf_FileOptions_SPEED = 1,
+  google_protobuf_FileOptions_CODE_SIZE = 2,
+  google_protobuf_FileOptions_LITE_RUNTIME = 3
+} google_protobuf_FileOptions_OptimizeMode;
+
+typedef enum {
+  google_protobuf_MethodOptions_IDEMPOTENCY_UNKNOWN = 0,
+  google_protobuf_MethodOptions_NO_SIDE_EFFECTS = 1,
+  google_protobuf_MethodOptions_IDEMPOTENT = 2
+} google_protobuf_MethodOptions_IdempotencyLevel;
+
+
+/* google.protobuf.FileDescriptorSet */
+
+UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_new(upb_arena *arena) {
+  return (google_protobuf_FileDescriptorSet *)_upb_msg_new(&google_protobuf_FileDescriptorSet_msginit, arena);
+}
+UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_FileDescriptorSet *ret = google_protobuf_FileDescriptorSet_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_FileDescriptorSet *ret = google_protobuf_FileDescriptorSet_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_FileDescriptorSet_serialize(const google_protobuf_FileDescriptorSet *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_FileDescriptorSet_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_FileDescriptorSet_has_file(const google_protobuf_FileDescriptorSet *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
+UPB_INLINE const google_protobuf_FileDescriptorProto* const* google_protobuf_FileDescriptorSet_file(const google_protobuf_FileDescriptorSet *msg, size_t *len) { return (const google_protobuf_FileDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
+
+UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_mutable_file(google_protobuf_FileDescriptorSet *msg, size_t *len) {
+  return (google_protobuf_FileDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
+}
+UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_resize_file(google_protobuf_FileDescriptorSet *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_FileDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorSet_add_file(google_protobuf_FileDescriptorSet *msg, upb_arena *arena) {
+  struct google_protobuf_FileDescriptorProto* sub = (struct google_protobuf_FileDescriptorProto*)_upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.FileDescriptorProto */
+
+UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_FileDescriptorProto *)_upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_FileDescriptorProto *ret = google_protobuf_FileDescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_FileDescriptorProto *ret = google_protobuf_FileDescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_FileDescriptorProto_serialize(const google_protobuf_FileDescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_FileDescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_name(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_name(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_package(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_package(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); }
+UPB_INLINE upb_strview const* google_protobuf_FileDescriptorProto_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_message_type(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(40, 80)); }
+UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_FileDescriptorProto_message_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_enum_type(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(44, 88)); }
+UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_FileDescriptorProto_enum_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_service(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(48, 96)); }
+UPB_INLINE const google_protobuf_ServiceDescriptorProto* const* google_protobuf_FileDescriptorProto_service(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_ServiceDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(48, 96), len); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_extension(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(52, 104)); }
+UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_FileDescriptorProto_extension(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(52, 104), len); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_options(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE const google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_options(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_FileOptions*); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE const google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 64), const google_protobuf_SourceCodeInfo*); }
+UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_public_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(56, 112), len); }
+UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_weak_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(60, 120), len); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_syntax(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_syntax(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); }
+
+UPB_INLINE void google_protobuf_FileDescriptorProto_set_name(google_protobuf_FileDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_set_package(google_protobuf_FileDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value;
+}
+UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_mutable_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len);
+}
+UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_resize_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(36, 72), len, UPB_SIZE(3, 4), arena);
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_add_dependency(google_protobuf_FileDescriptorProto *msg, upb_strview val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(36, 72), UPB_SIZE(3, 4), &val,
+      arena);
+}
+UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_mutable_message_type(google_protobuf_FileDescriptorProto *msg, size_t *len) {
+  return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len);
+}
+UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_resize_message_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(40, 80), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_FileDescriptorProto_add_message_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(40, 80), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_mutable_enum_type(google_protobuf_FileDescriptorProto *msg, size_t *len) {
+  return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len);
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_resize_enum_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(44, 88), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_FileDescriptorProto_add_enum_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(44, 88), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_mutable_service(google_protobuf_FileDescriptorProto *msg, size_t *len) {
+  return (google_protobuf_ServiceDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(48, 96), len);
+}
+UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_resize_service(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_ServiceDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(48, 96), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_ServiceDescriptorProto* google_protobuf_FileDescriptorProto_add_service(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_ServiceDescriptorProto* sub = (struct google_protobuf_ServiceDescriptorProto*)_upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(48, 96), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_mutable_extension(google_protobuf_FileDescriptorProto *msg, size_t *len) {
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(52, 104), len);
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_resize_extension(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(52, 104), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_FileDescriptorProto_add_extension(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(52, 104), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_set_options(google_protobuf_FileDescriptorProto *msg, google_protobuf_FileOptions* value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_FileOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_mutable_options(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_FileOptions* sub = (struct google_protobuf_FileOptions*)google_protobuf_FileDescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_FileOptions*)_upb_msg_new(&google_protobuf_FileOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_FileDescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_set_source_code_info(google_protobuf_FileDescriptorProto *msg, google_protobuf_SourceCodeInfo* value) {
+  _upb_sethas(msg, 4);
+  *UPB_PTR_AT(msg, UPB_SIZE(32, 64), google_protobuf_SourceCodeInfo*) = value;
+}
+UPB_INLINE struct google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_mutable_source_code_info(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_SourceCodeInfo* sub = (struct google_protobuf_SourceCodeInfo*)google_protobuf_FileDescriptorProto_source_code_info(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_SourceCodeInfo*)_upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_FileDescriptorProto_set_source_code_info(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_public_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 112), len);
+}
+UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_public_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(56, 112), len, 2, arena);
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_add_public_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(56, 112), 2, &val,
+      arena);
+}
+UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(60, 120), len);
+}
+UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(60, 120), len, 2, arena);
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_add_weak_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(60, 120), 2, &val,
+      arena);
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_set_syntax(google_protobuf_FileDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 5);
+  *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value;
+}
+
+/* google.protobuf.DescriptorProto */
+
+UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_DescriptorProto *)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_DescriptorProto *ret = google_protobuf_DescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_DescriptorProto *ret = google_protobuf_DescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_DescriptorProto_serialize(const google_protobuf_DescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_DescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_DescriptorProto_has_name(const google_protobuf_DescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_DescriptorProto_name(const google_protobuf_DescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_field(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); }
+UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_field(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_nested_type(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 40)); }
+UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_DescriptorProto_nested_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_enum_type(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(24, 48)); }
+UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_DescriptorProto_enum_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_extension_range(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(28, 56)); }
+UPB_INLINE const google_protobuf_DescriptorProto_ExtensionRange* const* google_protobuf_DescriptorProto_extension_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ExtensionRange* const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_extension(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(32, 64)); }
+UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_extension(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(32, 64), len); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_options(const google_protobuf_DescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE const google_protobuf_MessageOptions* google_protobuf_DescriptorProto_options(const google_protobuf_DescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_MessageOptions*); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_oneof_decl(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(36, 72)); }
+UPB_INLINE const google_protobuf_OneofDescriptorProto* const* google_protobuf_DescriptorProto_oneof_decl(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_OneofDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_reserved_range(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(40, 80)); }
+UPB_INLINE const google_protobuf_DescriptorProto_ReservedRange* const* google_protobuf_DescriptorProto_reserved_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); }
+UPB_INLINE upb_strview const* google_protobuf_DescriptorProto_reserved_name(const google_protobuf_DescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); }
+
+UPB_INLINE void google_protobuf_DescriptorProto_set_name(google_protobuf_DescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_field(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len);
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_field(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 32), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_field(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_mutable_nested_type(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
+}
+UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_resize_nested_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(20, 40), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_add_nested_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(20, 40), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_mutable_enum_type(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_resize_enum_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(24, 48), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_DescriptorProto_add_enum_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(24, 48), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_mutable_extension_range(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len);
+}
+UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_resize_extension_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_resize_accessor2(msg, UPB_SIZE(28, 56), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_DescriptorProto_ExtensionRange* google_protobuf_DescriptorProto_add_extension_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_DescriptorProto_ExtensionRange* sub = (struct google_protobuf_DescriptorProto_ExtensionRange*)_upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(28, 56), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_extension(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 64), len);
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_extension(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(32, 64), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_extension(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(32, 64), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_set_options(google_protobuf_DescriptorProto *msg, google_protobuf_MessageOptions* value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_MessageOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_MessageOptions* google_protobuf_DescriptorProto_mutable_options(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_MessageOptions* sub = (struct google_protobuf_MessageOptions*)google_protobuf_DescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_MessageOptions*)_upb_msg_new(&google_protobuf_MessageOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_DescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_mutable_oneof_decl(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (google_protobuf_OneofDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len);
+}
+UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_resize_oneof_decl(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_OneofDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(36, 72), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_OneofDescriptorProto* google_protobuf_DescriptorProto_add_oneof_decl(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_OneofDescriptorProto* sub = (struct google_protobuf_OneofDescriptorProto*)_upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(36, 72), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_mutable_reserved_range(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len);
+}
+UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_resize_reserved_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_resize_accessor2(msg, UPB_SIZE(40, 80), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_add_reserved_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_DescriptorProto_ReservedRange* sub = (struct google_protobuf_DescriptorProto_ReservedRange*)_upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(40, 80), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE upb_strview* google_protobuf_DescriptorProto_mutable_reserved_name(google_protobuf_DescriptorProto *msg, size_t *len) {
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len);
+}
+UPB_INLINE upb_strview* google_protobuf_DescriptorProto_resize_reserved_name(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(44, 88), len, UPB_SIZE(3, 4), arena);
+}
+UPB_INLINE bool google_protobuf_DescriptorProto_add_reserved_name(google_protobuf_DescriptorProto *msg, upb_strview val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(44, 88), UPB_SIZE(3, 4), &val,
+      arena);
+}
+
+/* google.protobuf.DescriptorProto.ExtensionRange */
+
+UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_new(upb_arena *arena) {
+  return (google_protobuf_DescriptorProto_ExtensionRange *)_upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena);
+}
+UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_DescriptorProto_ExtensionRange *ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_DescriptorProto_ExtensionRange *ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_DescriptorProto_ExtensionRange_serialize(const google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
+UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE const google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), const google_protobuf_ExtensionRangeOptions*); }
+
+UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_start(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_end(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_options(google_protobuf_DescriptorProto_ExtensionRange *msg, google_protobuf_ExtensionRangeOptions* value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 16), google_protobuf_ExtensionRangeOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_mutable_options(google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena) {
+  struct google_protobuf_ExtensionRangeOptions* sub = (struct google_protobuf_ExtensionRangeOptions*)google_protobuf_DescriptorProto_ExtensionRange_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_ExtensionRangeOptions*)_upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_DescriptorProto_ExtensionRange_set_options(msg, sub);
+  }
+  return sub;
+}
+
+/* google.protobuf.DescriptorProto.ReservedRange */
+
+UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_new(upb_arena *arena) {
+  return (google_protobuf_DescriptorProto_ReservedRange *)_upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena);
+}
+UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_DescriptorProto_ReservedRange *ret = google_protobuf_DescriptorProto_ReservedRange_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_DescriptorProto_ReservedRange *ret = google_protobuf_DescriptorProto_ReservedRange_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_DescriptorProto_ReservedRange_serialize(const google_protobuf_DescriptorProto_ReservedRange *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
+
+UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_start(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_end(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
+}
+
+/* google.protobuf.ExtensionRangeOptions */
+
+UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_new(upb_arena *arena) {
+  return (google_protobuf_ExtensionRangeOptions *)_upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_ExtensionRangeOptions *ret = google_protobuf_ExtensionRangeOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_ExtensionRangeOptions *ret = google_protobuf_ExtensionRangeOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_ExtensionRangeOptions_serialize(const google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_ExtensionRangeOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_ExtensionRangeOptions_has_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ExtensionRangeOptions_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
+
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_mutable_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_resize_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ExtensionRangeOptions_add_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.FieldDescriptorProto */
+
+UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_FieldDescriptorProto *)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_FieldDescriptorProto *ret = google_protobuf_FieldDescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_FieldDescriptorProto *ret = google_protobuf_FieldDescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_FieldDescriptorProto_serialize(const google_protobuf_FieldDescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_FieldDescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), upb_strview); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 40), upb_strview); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_number(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_number(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), int32_t); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_label(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_label(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_type(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 6); }
+UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(40, 56), upb_strview); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 7); }
+UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(48, 72), upb_strview); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 8); }
+UPB_INLINE const google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_options(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(64, 104), const google_protobuf_FieldOptions*); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 9); }
+UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 10); }
+UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(56, 88), upb_strview); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 11); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool); }
+
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(24, 24), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_extendee(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(32, 40), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_number(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 12), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_label(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
+  _upb_sethas(msg, 4);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
+  _upb_sethas(msg, 5);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 6);
+  *UPB_PTR_AT(msg, UPB_SIZE(40, 56), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 7);
+  *UPB_PTR_AT(msg, UPB_SIZE(48, 72), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_options(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldOptions* value) {
+  _upb_sethas(msg, 8);
+  *UPB_PTR_AT(msg, UPB_SIZE(64, 104), google_protobuf_FieldOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_mutable_options(google_protobuf_FieldDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_FieldOptions* sub = (struct google_protobuf_FieldOptions*)google_protobuf_FieldDescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_FieldOptions*)_upb_msg_new(&google_protobuf_FieldOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_FieldDescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_oneof_index(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
+  _upb_sethas(msg, 9);
+  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 10);
+  *UPB_PTR_AT(msg, UPB_SIZE(56, 88), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_set_proto3_optional(google_protobuf_FieldDescriptorProto *msg, bool value) {
+  _upb_sethas(msg, 11);
+  *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool) = value;
+}
+
+/* google.protobuf.OneofDescriptorProto */
+
+UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_OneofDescriptorProto *)_upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_OneofDescriptorProto *ret = google_protobuf_OneofDescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_OneofDescriptorProto *ret = google_protobuf_OneofDescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_OneofDescriptorProto_serialize(const google_protobuf_OneofDescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_OneofDescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_name(const google_protobuf_OneofDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_OneofDescriptorProto_name(const google_protobuf_OneofDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_options(const google_protobuf_OneofDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE const google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_options(const google_protobuf_OneofDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_OneofOptions*); }
+
+UPB_INLINE void google_protobuf_OneofDescriptorProto_set_name(google_protobuf_OneofDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_OneofDescriptorProto_set_options(google_protobuf_OneofDescriptorProto *msg, google_protobuf_OneofOptions* value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_OneofOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_mutable_options(google_protobuf_OneofDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_OneofOptions* sub = (struct google_protobuf_OneofOptions*)google_protobuf_OneofDescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_OneofOptions*)_upb_msg_new(&google_protobuf_OneofOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_OneofDescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+
+/* google.protobuf.EnumDescriptorProto */
+
+UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_EnumDescriptorProto *)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_EnumDescriptorProto *ret = google_protobuf_EnumDescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_EnumDescriptorProto *ret = google_protobuf_EnumDescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_EnumDescriptorProto_serialize(const google_protobuf_EnumDescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_EnumDescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_name(const google_protobuf_EnumDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_EnumDescriptorProto_name(const google_protobuf_EnumDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_value(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); }
+UPB_INLINE const google_protobuf_EnumValueDescriptorProto* const* google_protobuf_EnumDescriptorProto_value(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumValueDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); }
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_options(const google_protobuf_EnumDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE const google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_options(const google_protobuf_EnumDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_EnumOptions*); }
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_reserved_range(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 40)); }
+UPB_INLINE const google_protobuf_EnumDescriptorProto_EnumReservedRange* const* google_protobuf_EnumDescriptorProto_reserved_range(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto_EnumReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
+UPB_INLINE upb_strview const* google_protobuf_EnumDescriptorProto_reserved_name(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
+
+UPB_INLINE void google_protobuf_EnumDescriptorProto_set_name(google_protobuf_EnumDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_mutable_value(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
+  return (google_protobuf_EnumValueDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len);
+}
+UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_resize_value(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_EnumValueDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 32), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_EnumValueDescriptorProto* google_protobuf_EnumDescriptorProto_add_value(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_EnumValueDescriptorProto* sub = (struct google_protobuf_EnumValueDescriptorProto*)_upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE void google_protobuf_EnumDescriptorProto_set_options(google_protobuf_EnumDescriptorProto *msg, google_protobuf_EnumOptions* value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_EnumOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_mutable_options(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_EnumOptions* sub = (struct google_protobuf_EnumOptions*)google_protobuf_EnumDescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_EnumOptions*)_upb_msg_new(&google_protobuf_EnumOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_EnumDescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_mutable_reserved_range(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
+  return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_resize_reserved_range(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_resize_accessor2(msg, UPB_SIZE(20, 40), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_EnumDescriptorProto_EnumReservedRange* google_protobuf_EnumDescriptorProto_add_reserved_range(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_EnumDescriptorProto_EnumReservedRange* sub = (struct google_protobuf_EnumDescriptorProto_EnumReservedRange*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(20, 40), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_mutable_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
+}
+UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_resize_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(24, 48), len, UPB_SIZE(3, 4), arena);
+}
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_add_reserved_name(google_protobuf_EnumDescriptorProto *msg, upb_strview val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(24, 48), UPB_SIZE(3, 4), &val,
+      arena);
+}
+
+/* google.protobuf.EnumDescriptorProto.EnumReservedRange */
+
+UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_new(upb_arena *arena) {
+  return (google_protobuf_EnumDescriptorProto_EnumReservedRange *)_upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena);
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_EnumDescriptorProto_EnumReservedRange *ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_EnumDescriptorProto_EnumReservedRange *ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_EnumDescriptorProto_EnumReservedRange_serialize(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
+
+UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_start(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_end(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
+}
+
+/* google.protobuf.EnumValueDescriptorProto */
+
+UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_EnumValueDescriptorProto *)_upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_EnumValueDescriptorProto *ret = google_protobuf_EnumValueDescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_EnumValueDescriptorProto *ret = google_protobuf_EnumValueDescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_EnumValueDescriptorProto_serialize(const google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_EnumValueDescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_name(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_EnumValueDescriptorProto_name(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_number(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE int32_t google_protobuf_EnumValueDescriptorProto_number(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_options(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE const google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_options(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), const google_protobuf_EnumValueOptions*); }
+
+UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_name(google_protobuf_EnumValueDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_number(google_protobuf_EnumValueDescriptorProto *msg, int32_t value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_options(google_protobuf_EnumValueDescriptorProto *msg, google_protobuf_EnumValueOptions* value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(16, 24), google_protobuf_EnumValueOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_mutable_options(google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_EnumValueOptions* sub = (struct google_protobuf_EnumValueOptions*)google_protobuf_EnumValueDescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_EnumValueOptions*)_upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_EnumValueDescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+
+/* google.protobuf.ServiceDescriptorProto */
+
+UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_ServiceDescriptorProto *)_upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_ServiceDescriptorProto *ret = google_protobuf_ServiceDescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_ServiceDescriptorProto *ret = google_protobuf_ServiceDescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_ServiceDescriptorProto_serialize(const google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_ServiceDescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_name(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_ServiceDescriptorProto_name(const google_protobuf_ServiceDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_method(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); }
+UPB_INLINE const google_protobuf_MethodDescriptorProto* const* google_protobuf_ServiceDescriptorProto_method(const google_protobuf_ServiceDescriptorProto *msg, size_t *len) { return (const google_protobuf_MethodDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); }
+UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_options(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE const google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_options(const google_protobuf_ServiceDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_ServiceOptions*); }
+
+UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_name(google_protobuf_ServiceDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_mutable_method(google_protobuf_ServiceDescriptorProto *msg, size_t *len) {
+  return (google_protobuf_MethodDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len);
+}
+UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_resize_method(google_protobuf_ServiceDescriptorProto *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_MethodDescriptorProto**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 32), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_MethodDescriptorProto* google_protobuf_ServiceDescriptorProto_add_method(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_MethodDescriptorProto* sub = (struct google_protobuf_MethodDescriptorProto*)_upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_options(google_protobuf_ServiceDescriptorProto *msg, google_protobuf_ServiceOptions* value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_ServiceOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_mutable_options(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_ServiceOptions* sub = (struct google_protobuf_ServiceOptions*)google_protobuf_ServiceDescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_ServiceOptions*)_upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_ServiceDescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+
+/* google.protobuf.MethodDescriptorProto */
+
+UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_new(upb_arena *arena) {
+  return (google_protobuf_MethodDescriptorProto *)_upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena);
+}
+UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_MethodDescriptorProto *ret = google_protobuf_MethodDescriptorProto_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_MethodDescriptorProto *ret = google_protobuf_MethodDescriptorProto_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_MethodDescriptorProto_serialize(const google_protobuf_MethodDescriptorProto *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_MethodDescriptorProto_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_name(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_name(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_input_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_input_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_output_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_output_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_options(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE const google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_options(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_MethodOptions*); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 6); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); }
+
+UPB_INLINE void google_protobuf_MethodDescriptorProto_set_name(google_protobuf_MethodDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_set_input_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_set_output_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_set_options(google_protobuf_MethodDescriptorProto *msg, google_protobuf_MethodOptions* value) {
+  _upb_sethas(msg, 4);
+  *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_MethodOptions*) = value;
+}
+UPB_INLINE struct google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_mutable_options(google_protobuf_MethodDescriptorProto *msg, upb_arena *arena) {
+  struct google_protobuf_MethodOptions* sub = (struct google_protobuf_MethodOptions*)google_protobuf_MethodDescriptorProto_options(msg);
+  if (sub == NULL) {
+    sub = (struct google_protobuf_MethodOptions*)_upb_msg_new(&google_protobuf_MethodOptions_msginit, arena);
+    if (!sub) return NULL;
+    google_protobuf_MethodDescriptorProto_set_options(msg, sub);
+  }
+  return sub;
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_set_client_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) {
+  _upb_sethas(msg, 5);
+  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_set_server_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) {
+  _upb_sethas(msg, 6);
+  *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value;
+}
+
+/* google.protobuf.FileOptions */
+
+UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_new(upb_arena *arena) {
+  return (google_protobuf_FileOptions *)_upb_msg_new(&google_protobuf_FileOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_FileOptions *ret = google_protobuf_FileOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_FileOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_FileOptions *ret = google_protobuf_FileOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_FileOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_FileOptions_serialize(const google_protobuf_FileOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_FileOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_FileOptions_has_java_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_java_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 24), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_java_outer_classname(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_java_outer_classname(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 40), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_optimize_for(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE int32_t google_protobuf_FileOptions_optimize_for(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_FileOptions_has_java_multiple_files(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE bool google_protobuf_FileOptions_java_multiple_files(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_go_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_go_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(36, 56), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_cc_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 6); }
+UPB_INLINE bool google_protobuf_FileOptions_cc_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(9, 9), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_java_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 7); }
+UPB_INLINE bool google_protobuf_FileOptions_java_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(10, 10), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_py_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 8); }
+UPB_INLINE bool google_protobuf_FileOptions_py_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(11, 11), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 9); }
+UPB_INLINE bool google_protobuf_FileOptions_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_deprecated(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 10); }
+UPB_INLINE bool google_protobuf_FileOptions_deprecated(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 11); }
+UPB_INLINE bool google_protobuf_FileOptions_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 12); }
+UPB_INLINE bool google_protobuf_FileOptions_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_objc_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 13); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_objc_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(44, 72), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_csharp_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 14); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_csharp_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(52, 88), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_swift_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 15); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_swift_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(60, 104), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_php_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 16); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_php_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(68, 120), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_php_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 17); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_php_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(76, 136), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_php_generic_services(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 18); }
+UPB_INLINE bool google_protobuf_FileOptions_php_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool); }
+UPB_INLINE bool google_protobuf_FileOptions_has_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 19); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(84, 152), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_ruby_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 20); }
+UPB_INLINE upb_strview google_protobuf_FileOptions_ruby_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(92, 168), upb_strview); }
+UPB_INLINE bool google_protobuf_FileOptions_has_uninterpreted_option(const google_protobuf_FileOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(100, 184)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FileOptions_uninterpreted_option(const google_protobuf_FileOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(100, 184), len); }
+
+UPB_INLINE void google_protobuf_FileOptions_set_java_package(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(20, 24), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_java_outer_classname(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(28, 40), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_optimize_for(google_protobuf_FileOptions *msg, int32_t value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_java_multiple_files(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 4);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_go_package(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 5);
+  *UPB_PTR_AT(msg, UPB_SIZE(36, 56), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_cc_generic_services(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 6);
+  *UPB_PTR_AT(msg, UPB_SIZE(9, 9), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_java_generic_services(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 7);
+  *UPB_PTR_AT(msg, UPB_SIZE(10, 10), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_py_generic_services(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 8);
+  *UPB_PTR_AT(msg, UPB_SIZE(11, 11), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_java_generate_equals_and_hash(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 9);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_deprecated(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 10);
+  *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_java_string_check_utf8(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 11);
+  *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_cc_enable_arenas(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 12);
+  *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_objc_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 13);
+  *UPB_PTR_AT(msg, UPB_SIZE(44, 72), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_csharp_namespace(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 14);
+  *UPB_PTR_AT(msg, UPB_SIZE(52, 88), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_swift_prefix(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 15);
+  *UPB_PTR_AT(msg, UPB_SIZE(60, 104), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_php_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 16);
+  *UPB_PTR_AT(msg, UPB_SIZE(68, 120), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_php_namespace(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 17);
+  *UPB_PTR_AT(msg, UPB_SIZE(76, 136), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_php_generic_services(google_protobuf_FileOptions *msg, bool value) {
+  _upb_sethas(msg, 18);
+  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_php_metadata_namespace(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 19);
+  *UPB_PTR_AT(msg, UPB_SIZE(84, 152), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_FileOptions_set_ruby_package(google_protobuf_FileOptions *msg, upb_strview value) {
+  _upb_sethas(msg, 20);
+  *UPB_PTR_AT(msg, UPB_SIZE(92, 168), upb_strview) = value;
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_mutable_uninterpreted_option(google_protobuf_FileOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(100, 184), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_resize_uninterpreted_option(google_protobuf_FileOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(100, 184), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FileOptions_add_uninterpreted_option(google_protobuf_FileOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(100, 184), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.MessageOptions */
+
+UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_new(upb_arena *arena) {
+  return (google_protobuf_MessageOptions *)_upb_msg_new(&google_protobuf_MessageOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_MessageOptions *ret = google_protobuf_MessageOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_MessageOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_MessageOptions *ret = google_protobuf_MessageOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_MessageOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_MessageOptions_serialize(const google_protobuf_MessageOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_MessageOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_MessageOptions_has_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE bool google_protobuf_MessageOptions_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
+UPB_INLINE bool google_protobuf_MessageOptions_has_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_MessageOptions_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); }
+UPB_INLINE bool google_protobuf_MessageOptions_has_deprecated(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE bool google_protobuf_MessageOptions_deprecated(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool); }
+UPB_INLINE bool google_protobuf_MessageOptions_has_map_entry(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE bool google_protobuf_MessageOptions_map_entry(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool); }
+UPB_INLINE bool google_protobuf_MessageOptions_has_uninterpreted_option(const google_protobuf_MessageOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 8)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MessageOptions_uninterpreted_option(const google_protobuf_MessageOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(8, 8), len); }
+
+UPB_INLINE void google_protobuf_MessageOptions_set_message_set_wire_format(google_protobuf_MessageOptions *msg, bool value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
+}
+UPB_INLINE void google_protobuf_MessageOptions_set_no_standard_descriptor_accessor(google_protobuf_MessageOptions *msg, bool value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value;
+}
+UPB_INLINE void google_protobuf_MessageOptions_set_deprecated(google_protobuf_MessageOptions *msg, bool value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool) = value;
+}
+UPB_INLINE void google_protobuf_MessageOptions_set_map_entry(google_protobuf_MessageOptions *msg, bool value) {
+  _upb_sethas(msg, 4);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool) = value;
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_mutable_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 8), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_resize_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(8, 8), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MessageOptions_add_uninterpreted_option(google_protobuf_MessageOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(8, 8), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.FieldOptions */
+
+UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_new(upb_arena *arena) {
+  return (google_protobuf_FieldOptions *)_upb_msg_new(&google_protobuf_FieldOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_FieldOptions *ret = google_protobuf_FieldOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_FieldOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_FieldOptions *ret = google_protobuf_FieldOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_FieldOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_FieldOptions_serialize(const google_protobuf_FieldOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_FieldOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_FieldOptions_has_ctype(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE int32_t google_protobuf_FieldOptions_ctype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_packed(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_FieldOptions_packed(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_deprecated(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE bool google_protobuf_FieldOptions_deprecated(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_lazy(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE bool google_protobuf_FieldOptions_lazy(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_jstype(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE int32_t google_protobuf_FieldOptions_jstype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_weak(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 6); }
+UPB_INLINE bool google_protobuf_FieldOptions_weak(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_uninterpreted_option(const google_protobuf_FieldOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 16)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FieldOptions_uninterpreted_option(const google_protobuf_FieldOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(16, 16), len); }
+
+UPB_INLINE void google_protobuf_FieldOptions_set_ctype(google_protobuf_FieldOptions *msg, int32_t value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_FieldOptions_set_packed(google_protobuf_FieldOptions *msg, bool value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool) = value;
+}
+UPB_INLINE void google_protobuf_FieldOptions_set_deprecated(google_protobuf_FieldOptions *msg, bool value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool) = value;
+}
+UPB_INLINE void google_protobuf_FieldOptions_set_lazy(google_protobuf_FieldOptions *msg, bool value) {
+  _upb_sethas(msg, 4);
+  *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool) = value;
+}
+UPB_INLINE void google_protobuf_FieldOptions_set_jstype(google_protobuf_FieldOptions *msg, int32_t value) {
+  _upb_sethas(msg, 5);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_FieldOptions_set_weak(google_protobuf_FieldOptions *msg, bool value) {
+  _upb_sethas(msg, 6);
+  *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool) = value;
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_mutable_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 16), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_resize_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 16), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FieldOptions_add_uninterpreted_option(google_protobuf_FieldOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(16, 16), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.OneofOptions */
+
+UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_new(upb_arena *arena) {
+  return (google_protobuf_OneofOptions *)_upb_msg_new(&google_protobuf_OneofOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_OneofOptions *ret = google_protobuf_OneofOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_OneofOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_OneofOptions *ret = google_protobuf_OneofOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_OneofOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_OneofOptions_serialize(const google_protobuf_OneofOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_OneofOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_OneofOptions_has_uninterpreted_option(const google_protobuf_OneofOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_OneofOptions_uninterpreted_option(const google_protobuf_OneofOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
+
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_mutable_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_resize_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_OneofOptions_add_uninterpreted_option(google_protobuf_OneofOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.EnumOptions */
+
+UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_new(upb_arena *arena) {
+  return (google_protobuf_EnumOptions *)_upb_msg_new(&google_protobuf_EnumOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_EnumOptions *ret = google_protobuf_EnumOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_EnumOptions *ret = google_protobuf_EnumOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_EnumOptions_serialize(const google_protobuf_EnumOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_EnumOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_EnumOptions_has_allow_alias(const google_protobuf_EnumOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE bool google_protobuf_EnumOptions_allow_alias(const google_protobuf_EnumOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
+UPB_INLINE bool google_protobuf_EnumOptions_has_deprecated(const google_protobuf_EnumOptions *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_EnumOptions_deprecated(const google_protobuf_EnumOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); }
+UPB_INLINE bool google_protobuf_EnumOptions_has_uninterpreted_option(const google_protobuf_EnumOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumOptions_uninterpreted_option(const google_protobuf_EnumOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
+
+UPB_INLINE void google_protobuf_EnumOptions_set_allow_alias(google_protobuf_EnumOptions *msg, bool value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
+}
+UPB_INLINE void google_protobuf_EnumOptions_set_deprecated(google_protobuf_EnumOptions *msg, bool value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value;
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_mutable_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_resize_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumOptions_add_uninterpreted_option(google_protobuf_EnumOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.EnumValueOptions */
+
+UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_new(upb_arena *arena) {
+  return (google_protobuf_EnumValueOptions *)_upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_EnumValueOptions *ret = google_protobuf_EnumValueOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumValueOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_EnumValueOptions *ret = google_protobuf_EnumValueOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_EnumValueOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_EnumValueOptions_serialize(const google_protobuf_EnumValueOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_EnumValueOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_EnumValueOptions_has_deprecated(const google_protobuf_EnumValueOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE bool google_protobuf_EnumValueOptions_deprecated(const google_protobuf_EnumValueOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
+UPB_INLINE bool google_protobuf_EnumValueOptions_has_uninterpreted_option(const google_protobuf_EnumValueOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumValueOptions_uninterpreted_option(const google_protobuf_EnumValueOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
+
+UPB_INLINE void google_protobuf_EnumValueOptions_set_deprecated(google_protobuf_EnumValueOptions *msg, bool value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_mutable_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_resize_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumValueOptions_add_uninterpreted_option(google_protobuf_EnumValueOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.ServiceOptions */
+
+UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_new(upb_arena *arena) {
+  return (google_protobuf_ServiceOptions *)_upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_ServiceOptions *ret = google_protobuf_ServiceOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_ServiceOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_ServiceOptions *ret = google_protobuf_ServiceOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_ServiceOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_ServiceOptions_serialize(const google_protobuf_ServiceOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_ServiceOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_ServiceOptions_has_deprecated(const google_protobuf_ServiceOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE bool google_protobuf_ServiceOptions_deprecated(const google_protobuf_ServiceOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
+UPB_INLINE bool google_protobuf_ServiceOptions_has_uninterpreted_option(const google_protobuf_ServiceOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ServiceOptions_uninterpreted_option(const google_protobuf_ServiceOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
+
+UPB_INLINE void google_protobuf_ServiceOptions_set_deprecated(google_protobuf_ServiceOptions *msg, bool value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_mutable_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_resize_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ServiceOptions_add_uninterpreted_option(google_protobuf_ServiceOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.MethodOptions */
+
+UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_new(upb_arena *arena) {
+  return (google_protobuf_MethodOptions *)_upb_msg_new(&google_protobuf_MethodOptions_msginit, arena);
+}
+UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_MethodOptions *ret = google_protobuf_MethodOptions_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_MethodOptions_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_MethodOptions *ret = google_protobuf_MethodOptions_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_MethodOptions_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_MethodOptions_serialize(const google_protobuf_MethodOptions *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_MethodOptions_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_MethodOptions_has_deprecated(const google_protobuf_MethodOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE bool google_protobuf_MethodOptions_deprecated(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool); }
+UPB_INLINE bool google_protobuf_MethodOptions_has_idempotency_level(const google_protobuf_MethodOptions *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE int32_t google_protobuf_MethodOptions_idempotency_level(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_MethodOptions_has_uninterpreted_option(const google_protobuf_MethodOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(12, 16)); }
+UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MethodOptions_uninterpreted_option(const google_protobuf_MethodOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(12, 16), len); }
+
+UPB_INLINE void google_protobuf_MethodOptions_set_deprecated(google_protobuf_MethodOptions *msg, bool value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool) = value;
+}
+UPB_INLINE void google_protobuf_MethodOptions_set_idempotency_level(google_protobuf_MethodOptions *msg, int32_t value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_mutable_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 16), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_resize_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(12, 16), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MethodOptions_add_uninterpreted_option(google_protobuf_MethodOptions *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(12, 16), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.UninterpretedOption */
+
+UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_new(upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption *)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
+}
+UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_UninterpretedOption *ret = google_protobuf_UninterpretedOption_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_UninterpretedOption *ret = google_protobuf_UninterpretedOption_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_UninterpretedOption_serialize(const google_protobuf_UninterpretedOption *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_UninterpretedOption_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_name(const google_protobuf_UninterpretedOption *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(56, 80)); }
+UPB_INLINE const google_protobuf_UninterpretedOption_NamePart* const* google_protobuf_UninterpretedOption_name(const google_protobuf_UninterpretedOption *msg, size_t *len) { return (const google_protobuf_UninterpretedOption_NamePart* const*)_upb_array_accessor(msg, UPB_SIZE(56, 80), len); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_identifier_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_UninterpretedOption_identifier_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE uint64_t google_protobuf_UninterpretedOption_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE int64_t google_protobuf_UninterpretedOption_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_double_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE double google_protobuf_UninterpretedOption_double_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_string_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE upb_strview google_protobuf_UninterpretedOption_string_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_strview); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 6); }
+UPB_INLINE upb_strview google_protobuf_UninterpretedOption_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_strview); }
+
+UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_mutable_name(google_protobuf_UninterpretedOption *msg, size_t *len) {
+  return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 80), len);
+}
+UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_resize_name(google_protobuf_UninterpretedOption *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_resize_accessor2(msg, UPB_SIZE(56, 80), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_UninterpretedOption_NamePart* google_protobuf_UninterpretedOption_add_name(google_protobuf_UninterpretedOption *msg, upb_arena *arena) {
+  struct google_protobuf_UninterpretedOption_NamePart* sub = (struct google_protobuf_UninterpretedOption_NamePart*)_upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(56, 80), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_set_identifier_value(google_protobuf_UninterpretedOption *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_set_positive_int_value(google_protobuf_UninterpretedOption *msg, uint64_t value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t) = value;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_set_negative_int_value(google_protobuf_UninterpretedOption *msg, int64_t value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t) = value;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_set_double_value(google_protobuf_UninterpretedOption *msg, double value) {
+  _upb_sethas(msg, 4);
+  *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double) = value;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_set_string_value(google_protobuf_UninterpretedOption *msg, upb_strview value) {
+  _upb_sethas(msg, 5);
+  *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_set_aggregate_value(google_protobuf_UninterpretedOption *msg, upb_strview value) {
+  _upb_sethas(msg, 6);
+  *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_strview) = value;
+}
+
+/* google.protobuf.UninterpretedOption.NamePart */
+
+UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_new(upb_arena *arena) {
+  return (google_protobuf_UninterpretedOption_NamePart *)_upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena);
+}
+UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_UninterpretedOption_NamePart *ret = google_protobuf_UninterpretedOption_NamePart_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_UninterpretedOption_NamePart *ret = google_protobuf_UninterpretedOption_NamePart_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_UninterpretedOption_NamePart_serialize(const google_protobuf_UninterpretedOption_NamePart *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_UninterpretedOption_NamePart_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_UninterpretedOption_NamePart_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
+
+UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_name_part(google_protobuf_UninterpretedOption_NamePart *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_is_extension(google_protobuf_UninterpretedOption_NamePart *msg, bool value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
+}
+
+/* google.protobuf.SourceCodeInfo */
+
+UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_new(upb_arena *arena) {
+  return (google_protobuf_SourceCodeInfo *)_upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena);
+}
+UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_SourceCodeInfo *ret = google_protobuf_SourceCodeInfo_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_SourceCodeInfo *ret = google_protobuf_SourceCodeInfo_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_SourceCodeInfo_serialize(const google_protobuf_SourceCodeInfo *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_SourceCodeInfo_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_SourceCodeInfo_has_location(const google_protobuf_SourceCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
+UPB_INLINE const google_protobuf_SourceCodeInfo_Location* const* google_protobuf_SourceCodeInfo_location(const google_protobuf_SourceCodeInfo *msg, size_t *len) { return (const google_protobuf_SourceCodeInfo_Location* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
+
+UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_mutable_location(google_protobuf_SourceCodeInfo *msg, size_t *len) {
+  return (google_protobuf_SourceCodeInfo_Location**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
+}
+UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_resize_location(google_protobuf_SourceCodeInfo *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_SourceCodeInfo_Location**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_add_location(google_protobuf_SourceCodeInfo *msg, upb_arena *arena) {
+  struct google_protobuf_SourceCodeInfo_Location* sub = (struct google_protobuf_SourceCodeInfo_Location*)_upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.SourceCodeInfo.Location */
+
+UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_new(upb_arena *arena) {
+  return (google_protobuf_SourceCodeInfo_Location *)_upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena);
+}
+UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_SourceCodeInfo_Location *ret = google_protobuf_SourceCodeInfo_Location_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_SourceCodeInfo_Location *ret = google_protobuf_SourceCodeInfo_Location_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_SourceCodeInfo_Location_serialize(const google_protobuf_SourceCodeInfo_Location *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_SourceCodeInfo_Location_msginit, arena, len);
+}
+
+UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_path(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
+UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_span(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); }
+UPB_INLINE upb_strview const* google_protobuf_SourceCodeInfo_Location_leading_detached_comments(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); }
+
+UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_path(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
+}
+UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_path(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) {
+  return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(20, 40), len, 2, arena);
+}
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_path(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(20, 40), 2, &val,
+      arena);
+}
+UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_span(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
+}
+UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_span(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) {
+  return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(24, 48), len, 2, arena);
+}
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_span(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(24, 48), 2, &val,
+      arena);
+}
+UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_leading_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_trailing_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value;
+}
+UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_mutable_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
+  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len);
+}
+UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_resize_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) {
+  return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(28, 56), len, UPB_SIZE(3, 4), arena);
+}
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(28, 56), UPB_SIZE(3, 4), &val,
+      arena);
+}
+
+/* google.protobuf.GeneratedCodeInfo */
+
+UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_new(upb_arena *arena) {
+  return (google_protobuf_GeneratedCodeInfo *)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_msginit, arena);
+}
+UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_GeneratedCodeInfo *ret = google_protobuf_GeneratedCodeInfo_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_GeneratedCodeInfo *ret = google_protobuf_GeneratedCodeInfo_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_GeneratedCodeInfo_serialize(const google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_msginit, arena, len);
+}
+
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_has_annotation(const google_protobuf_GeneratedCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
+UPB_INLINE const google_protobuf_GeneratedCodeInfo_Annotation* const* google_protobuf_GeneratedCodeInfo_annotation(const google_protobuf_GeneratedCodeInfo *msg, size_t *len) { return (const google_protobuf_GeneratedCodeInfo_Annotation* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
+
+UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_mutable_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t *len) {
+  return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
+}
+UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_resize_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t len, upb_arena *arena) {
+  return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena);
+}
+UPB_INLINE struct google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_add_annotation(google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena) {
+  struct google_protobuf_GeneratedCodeInfo_Annotation* sub = (struct google_protobuf_GeneratedCodeInfo_Annotation*)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena);
+  bool ok = _upb_array_append_accessor2(
+      msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena);
+  if (!ok) return NULL;
+  return sub;
+}
+
+/* google.protobuf.GeneratedCodeInfo.Annotation */
+
+UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_new(upb_arena *arena) {
+  return (google_protobuf_GeneratedCodeInfo_Annotation *)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena);
+}
+UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_parse(const char *buf, size_t size,
+                        upb_arena *arena) {
+  google_protobuf_GeneratedCodeInfo_Annotation *ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena);
+  return (ret && upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena)) ? ret : NULL;
+}
+UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_parse_ex(const char *buf, size_t size,
+                           upb_arena *arena, int options) {
+  google_protobuf_GeneratedCodeInfo_Annotation *ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena);
+  return (ret && _upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena, options))
+      ? ret : NULL;
+}
+UPB_INLINE char *google_protobuf_GeneratedCodeInfo_Annotation_serialize(const google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_arena *arena, size_t *len) {
+  return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena, len);
+}
+
+UPB_INLINE int32_t const* google_protobuf_GeneratedCodeInfo_Annotation_path(const google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 32), len); }
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE upb_strview google_protobuf_GeneratedCodeInfo_Annotation_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview); }
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
+
+UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_mutable_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) {
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 32), len);
+}
+UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_resize_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t len, upb_arena *arena) {
+  return (int32_t*)_upb_array_resize_accessor2(msg, UPB_SIZE(20, 32), len, 2, arena);
+}
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_add_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t val, upb_arena *arena) {
+  return _upb_array_append_accessor2(msg, UPB_SIZE(20, 32), 2, &val,
+      arena);
+}
+UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_source_file(google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_strview value) {
+  _upb_sethas(msg, 1);
+  *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview) = value;
+}
+UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_begin(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) {
+  _upb_sethas(msg, 2);
+  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
+}
+UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_end(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) {
+  _upb_sethas(msg, 3);
+  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+
+#endif  /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ */
+/*
+** Defs are upb's internal representation of the constructs that can appear
+** in a .proto file:
+**
+** - upb_msgdef: describes a "message" construct.
+** - upb_fielddef: describes a message field.
+** - upb_filedef: describes a .proto file and its defs.
+** - upb_enumdef: describes an enum.
+** - upb_oneofdef: describes a oneof.
+**
+** TODO: definitions of services.
+*/
+
+#ifndef UPB_DEF_H_
+#define UPB_DEF_H_
+
+
+/* Must be last. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif  /* __cplusplus */
+
+struct upb_enumdef;
+typedef struct upb_enumdef upb_enumdef;
+struct upb_fielddef;
+typedef struct upb_fielddef upb_fielddef;
+struct upb_filedef;
+typedef struct upb_filedef upb_filedef;
+struct upb_msgdef;
+typedef struct upb_msgdef upb_msgdef;
+struct upb_oneofdef;
+typedef struct upb_oneofdef upb_oneofdef;
+struct upb_symtab;
+typedef struct upb_symtab upb_symtab;
+
+typedef enum {
+  UPB_SYNTAX_PROTO2 = 2,
+  UPB_SYNTAX_PROTO3 = 3
+} upb_syntax_t;
+
+/* All the different kind of well known type messages. For simplicity of check,
+ * number wrappers and string wrappers are grouped together. Make sure the
+ * order and merber of these groups are not changed.
+ */
+typedef enum {
+  UPB_WELLKNOWN_UNSPECIFIED,
+  UPB_WELLKNOWN_ANY,
+  UPB_WELLKNOWN_FIELDMASK,
+  UPB_WELLKNOWN_DURATION,
+  UPB_WELLKNOWN_TIMESTAMP,
+  /* number wrappers */
+  UPB_WELLKNOWN_DOUBLEVALUE,
+  UPB_WELLKNOWN_FLOATVALUE,
+  UPB_WELLKNOWN_INT64VALUE,
+  UPB_WELLKNOWN_UINT64VALUE,
+  UPB_WELLKNOWN_INT32VALUE,
+  UPB_WELLKNOWN_UINT32VALUE,
+  /* string wrappers */
+  UPB_WELLKNOWN_STRINGVALUE,
+  UPB_WELLKNOWN_BYTESVALUE,
+  UPB_WELLKNOWN_BOOLVALUE,
+  UPB_WELLKNOWN_VALUE,
+  UPB_WELLKNOWN_LISTVALUE,
+  UPB_WELLKNOWN_STRUCT
+} upb_wellknowntype_t;
+
+/* upb_fielddef ***************************************************************/
+
+/* Maximum field number allowed for FieldDefs.  This is an inherent limit of the
+ * protobuf wire format. */
+#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1)
+
+const char *upb_fielddef_fullname(const upb_fielddef *f);
+upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f);
+upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f);
+upb_label_t upb_fielddef_label(const upb_fielddef *f);
+uint32_t upb_fielddef_number(const upb_fielddef *f);
+const char *upb_fielddef_name(const upb_fielddef *f);
+const char *upb_fielddef_jsonname(const upb_fielddef *f);
+bool upb_fielddef_isextension(const upb_fielddef *f);
+bool upb_fielddef_lazy(const upb_fielddef *f);
+bool upb_fielddef_packed(const upb_fielddef *f);
+const upb_filedef *upb_fielddef_file(const upb_fielddef *f);
+const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f);
+const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f);
+const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f);
+uint32_t upb_fielddef_index(const upb_fielddef *f);
+bool upb_fielddef_issubmsg(const upb_fielddef *f);
+bool upb_fielddef_isstring(const upb_fielddef *f);
+bool upb_fielddef_isseq(const upb_fielddef *f);
+bool upb_fielddef_isprimitive(const upb_fielddef *f);
+bool upb_fielddef_ismap(const upb_fielddef *f);
+int64_t upb_fielddef_defaultint64(const upb_fielddef *f);
+int32_t upb_fielddef_defaultint32(const upb_fielddef *f);
+uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f);
+uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f);
+bool upb_fielddef_defaultbool(const upb_fielddef *f);
+float upb_fielddef_defaultfloat(const upb_fielddef *f);
+double upb_fielddef_defaultdouble(const upb_fielddef *f);
+const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len);
+bool upb_fielddef_hassubdef(const upb_fielddef *f);
+bool upb_fielddef_haspresence(const upb_fielddef *f);
+const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f);
+const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f);
+const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f);
+
+/* Internal only. */
+uint32_t upb_fielddef_selectorbase(const upb_fielddef *f);
+
+/* upb_oneofdef ***************************************************************/
+
+typedef upb_inttable_iter upb_oneof_iter;
+
+const char *upb_oneofdef_name(const upb_oneofdef *o);
+const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o);
+uint32_t upb_oneofdef_index(const upb_oneofdef *o);
+bool upb_oneofdef_issynthetic(const upb_oneofdef *o);
+int upb_oneofdef_fieldcount(const upb_oneofdef *o);
+const upb_fielddef *upb_oneofdef_field(const upb_oneofdef *o, int i);
+
+/* Oneof lookups:
+ * - ntof:  look up a field by name.
+ * - ntofz: look up a field by name (as a null-terminated string).
+ * - itof:  look up a field by number. */
+const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
+                                      const char *name, size_t length);
+UPB_INLINE const upb_fielddef *upb_oneofdef_ntofz(const upb_oneofdef *o,
+                                                  const char *name) {
+  return upb_oneofdef_ntof(o, name, strlen(name));
+}
+const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num);
+
+/* DEPRECATED, slated for removal. */
+int upb_oneofdef_numfields(const upb_oneofdef *o);
+void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o);
+void upb_oneof_next(upb_oneof_iter *iter);
+bool upb_oneof_done(upb_oneof_iter *iter);
+upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter);
+void upb_oneof_iter_setdone(upb_oneof_iter *iter);
+bool upb_oneof_iter_isequal(const upb_oneof_iter *iter1,
+                            const upb_oneof_iter *iter2);
+/* END DEPRECATED */
+
+/* upb_msgdef *****************************************************************/
+
+typedef upb_inttable_iter upb_msg_field_iter;
+typedef upb_strtable_iter upb_msg_oneof_iter;
+
+/* Well-known field tag numbers for map-entry messages. */
+#define UPB_MAPENTRY_KEY   1
+#define UPB_MAPENTRY_VALUE 2
+
+/* Well-known field tag numbers for Any messages. */
+#define UPB_ANY_TYPE 1
+#define UPB_ANY_VALUE 2
+
+/* Well-known field tag numbers for timestamp messages. */
+#define UPB_DURATION_SECONDS 1
+#define UPB_DURATION_NANOS 2
+
+/* Well-known field tag numbers for duration messages. */
+#define UPB_TIMESTAMP_SECONDS 1
+#define UPB_TIMESTAMP_NANOS 2
+
+const char *upb_msgdef_fullname(const upb_msgdef *m);
+const upb_filedef *upb_msgdef_file(const upb_msgdef *m);
+const char *upb_msgdef_name(const upb_msgdef *m);
+upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m);
+bool upb_msgdef_mapentry(const upb_msgdef *m);
+upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m);
+bool upb_msgdef_iswrapper(const upb_msgdef *m);
+bool upb_msgdef_isnumberwrapper(const upb_msgdef *m);
+int upb_msgdef_fieldcount(const upb_msgdef *m);
+int upb_msgdef_oneofcount(const upb_msgdef *m);
+const upb_fielddef *upb_msgdef_field(const upb_msgdef *m, int i);
+const upb_oneofdef *upb_msgdef_oneof(const upb_msgdef *m, int i);
+const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i);
+const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
+                                    size_t len);
+const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
+                                    size_t len);
+const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m);
+
+UPB_INLINE const upb_oneofdef *upb_msgdef_ntooz(const upb_msgdef *m,
+                                               const char *name) {
+  return upb_msgdef_ntoo(m, name, strlen(name));
+}
+
+UPB_INLINE const upb_fielddef *upb_msgdef_ntofz(const upb_msgdef *m,
+                                                const char *name) {
+  return upb_msgdef_ntof(m, name, strlen(name));
+}
+
+/* Internal-only. */
+size_t upb_msgdef_selectorcount(const upb_msgdef *m);
+uint32_t upb_msgdef_submsgfieldcount(const upb_msgdef *m);
+
+/* Lookup of either field or oneof by name.  Returns whether either was found.
+ * If the return is true, then the found def will be set, and the non-found
+ * one set to NULL. */
+bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
+                           const upb_fielddef **f, const upb_oneofdef **o);
+
+UPB_INLINE bool upb_msgdef_lookupnamez(const upb_msgdef *m, const char *name,
+                                       const upb_fielddef **f,
+                                       const upb_oneofdef **o) {
+  return upb_msgdef_lookupname(m, name, strlen(name), f, o);
+}
+
+/* Returns a field by either JSON name or regular proto name. */
+const upb_fielddef *upb_msgdef_lookupjsonname(const upb_msgdef *m,
+                                              const char *name, size_t len);
+
+/* DEPRECATED, slated for removal */
+int upb_msgdef_numfields(const upb_msgdef *m);
+int upb_msgdef_numoneofs(const upb_msgdef *m);
+int upb_msgdef_numrealoneofs(const upb_msgdef *m);
+void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m);
+void upb_msg_field_next(upb_msg_field_iter *iter);
+bool upb_msg_field_done(const upb_msg_field_iter *iter);
+upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter);
+void upb_msg_field_iter_setdone(upb_msg_field_iter *iter);
+bool upb_msg_field_iter_isequal(const upb_msg_field_iter * iter1,
+                                const upb_msg_field_iter * iter2);
+void upb_msg_oneof_begin(upb_msg_oneof_iter * iter, const upb_msgdef *m);
+void upb_msg_oneof_next(upb_msg_oneof_iter * iter);
+bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter);
+const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter);
+void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter * iter);
+bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1,
+                                const upb_msg_oneof_iter *iter2);
+/* END DEPRECATED */
+
+/* upb_enumdef ****************************************************************/
+
+typedef upb_strtable_iter upb_enum_iter;
+
+const char *upb_enumdef_fullname(const upb_enumdef *e);
+const char *upb_enumdef_name(const upb_enumdef *e);
+const upb_filedef *upb_enumdef_file(const upb_enumdef *e);
+int32_t upb_enumdef_default(const upb_enumdef *e);
+int upb_enumdef_numvals(const upb_enumdef *e);
+
+/* Enum lookups:
+ * - ntoi:  look up a name with specified length.
+ * - ntoiz: look up a name provided as a null-terminated string.
+ * - iton:  look up an integer, returning the name as a null-terminated
+ *          string. */
+bool upb_enumdef_ntoi(const upb_enumdef *e, const char *name, size_t len,
+                      int32_t *num);
+UPB_INLINE bool upb_enumdef_ntoiz(const upb_enumdef *e,
+                                  const char *name, int32_t *num) {
+  return upb_enumdef_ntoi(e, name, strlen(name), num);
+}
+const char *upb_enumdef_iton(const upb_enumdef *e, int32_t num);
+
+void upb_enum_begin(upb_enum_iter *iter, const upb_enumdef *e);
+void upb_enum_next(upb_enum_iter *iter);
+bool upb_enum_done(upb_enum_iter *iter);
+const char *upb_enum_iter_name(upb_enum_iter *iter);
+int32_t upb_enum_iter_number(upb_enum_iter *iter);
+
+/* upb_filedef ****************************************************************/
+
+const char *upb_filedef_name(const upb_filedef *f);
+const char *upb_filedef_package(const upb_filedef *f);
+const char *upb_filedef_phpprefix(const upb_filedef *f);
+const char *upb_filedef_phpnamespace(const upb_filedef *f);
+upb_syntax_t upb_filedef_syntax(const upb_filedef *f);
+int upb_filedef_depcount(const upb_filedef *f);
+int upb_filedef_msgcount(const upb_filedef *f);
+int upb_filedef_enumcount(const upb_filedef *f);
+const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i);
+const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i);
+const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i);
+const upb_symtab *upb_filedef_symtab(const upb_filedef *f);
+upb_arena *_upb_symtab_arena(const upb_symtab *s);
+
+/* upb_symtab *****************************************************************/
+
+upb_symtab *upb_symtab_new(void);
+void upb_symtab_free(upb_symtab* s);
+const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym);
+const upb_msgdef *upb_symtab_lookupmsg2(
+    const upb_symtab *s, const char *sym, size_t len);
+const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym);
+const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name);
+const upb_filedef *upb_symtab_lookupfile2(
+    const upb_symtab *s, const char *name, size_t len);
+int upb_symtab_filecount(const upb_symtab *s);
+const upb_filedef *upb_symtab_addfile(
+    upb_symtab *s, const google_protobuf_FileDescriptorProto *file,
+    upb_status *status);
+size_t _upb_symtab_bytesloaded(const upb_symtab *s);
+
+/* For generated code only: loads a generated descriptor. */
+typedef struct upb_def_init {
+  struct upb_def_init **deps;     /* Dependencies of this file. */
+  const upb_msglayout **layouts;  /* Pre-order layouts of all messages. */
+  const char *filename;
+  upb_strview descriptor;         /* Serialized descriptor. */
+} upb_def_init;
+
+bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init);
+
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif  /* __cplusplus */
+
+#endif /* UPB_DEF_H_ */
+
+#ifndef UPB_REFLECTION_H_
+#define UPB_REFLECTION_H_
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef union {
+  bool bool_val;
+  float float_val;
+  double double_val;
+  int32_t int32_val;
+  int64_t int64_val;
+  uint32_t uint32_val;
+  uint64_t uint64_val;
+  const upb_map* map_val;
+  const upb_msg* msg_val;
+  const upb_array* array_val;
+  upb_strview str_val;
+} upb_msgval;
+
+typedef union {
+  upb_map* map;
+  upb_msg* msg;
+  upb_array* array;
+} upb_mutmsgval;
+
+upb_msgval upb_fielddef_default(const upb_fielddef *f);
+
+/** upb_msg *******************************************************************/
+
+/* Creates a new message of the given type in the given arena. */
+upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a);
+
+/* Returns the value associated with this field. */
+upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f);
+
+/* Returns a mutable pointer to a map, array, or submessage value.  If the given
+ * arena is non-NULL this will construct a new object if it was not previously
+ * present.  May not be called for primitive fields. */
+upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f, upb_arena *a);
+
+/* May only be called for fields where upb_fielddef_haspresence(f) == true. */
+bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f);
+
+/* Returns the field that is set in the oneof, or NULL if none are set. */
+const upb_fielddef *upb_msg_whichoneof(const upb_msg *msg,
+                                       const upb_oneofdef *o);
+
+/* Sets the given field to the given value.  For a msg/array/map/string, the
+ * value must be in the same arena.  */
+void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val,
+                 upb_arena *a);
+
+/* Clears any field presence and sets the value back to its default. */
+void upb_msg_clearfield(upb_msg *msg, const upb_fielddef *f);
+
+/* Clear all data and unknown fields. */
+void upb_msg_clear(upb_msg *msg, const upb_msgdef *m);
+
+/* Iterate over present fields.
+ *
+ * size_t iter = UPB_MSG_BEGIN;
+ * const upb_fielddef *f;
+ * upb_msgval val;
+ * while (upb_msg_next(msg, m, ext_pool, &f, &val, &iter)) {
+ *   process_field(f, val);
+ * }
+ *
+ * If ext_pool is NULL, no extensions will be returned.  If the given symtab
+ * returns extensions that don't match what is in this message, those extensions
+ * will be skipped.
+ */
+
+#define UPB_MSG_BEGIN -1
+bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m,
+                  const upb_symtab *ext_pool, const upb_fielddef **f,
+                  upb_msgval *val, size_t *iter);
+
+/* Adds unknown data (serialized protobuf data) to the given message.  The data
+ * is copied into the message instance. */
+void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
+                        upb_arena *arena);
+
+/* Clears all unknown field data from this message and all submessages. */
+bool upb_msg_discardunknown(upb_msg *msg, const upb_msgdef *m, int maxdepth);
+
+/* Returns a reference to the message's unknown data. */
+const char *upb_msg_getunknown(const upb_msg *msg, size_t *len);
+
+/** upb_array *****************************************************************/
+
+/* Creates a new array on the given arena that holds elements of this type. */
+upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type);
+
+/* Returns the size of the array. */
+size_t upb_array_size(const upb_array *arr);
+
+/* Returns the given element, which must be within the array's current size. */
+upb_msgval upb_array_get(const upb_array *arr, size_t i);
+
+/* Sets the given element, which must be within the array's current size. */
+void upb_array_set(upb_array *arr, size_t i, upb_msgval val);
+
+/* Appends an element to the array.  Returns false on allocation failure. */
+bool upb_array_append(upb_array *array, upb_msgval val, upb_arena *arena);
+
+/* Changes the size of a vector.  New elements are initialized to empty/0.
+ * Returns false on allocation failure. */
+bool upb_array_resize(upb_array *array, size_t size, upb_arena *arena);
+
+/** upb_map *******************************************************************/
+
+/* Creates a new map on the given arena with the given key/value size. */
+upb_map *upb_map_new(upb_arena *a, upb_fieldtype_t key_type,
+                     upb_fieldtype_t value_type);
+
+/* Returns the number of entries in the map. */
+size_t upb_map_size(const upb_map *map);
+
+/* Stores a value for the given key into |*val| (or the zero value if the key is
+ * not present).  Returns whether the key was present.  The |val| pointer may be
+ * NULL, in which case the function tests whether the given key is present.  */
+bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val);
+
+/* Removes all entries in the map. */
+void upb_map_clear(upb_map *map);
+
+/* Sets the given key to the given value.  Returns true if this was a new key in
+ * the map, or false if an existing key was replaced. */
+bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val,
+                 upb_arena *arena);
+
+/* Deletes this key from the table.  Returns true if the key was present. */
+bool upb_map_delete(upb_map *map, upb_msgval key);
+
+/* Map iteration:
+ *
+ * size_t iter = UPB_MAP_BEGIN;
+ * while (upb_mapiter_next(map, &iter)) {
+ *   upb_msgval key = upb_mapiter_key(map, iter);
+ *   upb_msgval val = upb_mapiter_value(map, iter);
+ *
+ *   // If mutating is desired.
+ *   upb_mapiter_setvalue(map, iter, value2);
+ * }
+ */
+
+/* Advances to the next entry.  Returns false if no more entries are present. */
+bool upb_mapiter_next(const upb_map *map, size_t *iter);
+
+/* Returns true if the iterator still points to a valid entry, or false if the
+ * iterator is past the last element. It is an error to call this function with
+ * UPB_MAP_BEGIN (you must call next() at least once first). */
+bool upb_mapiter_done(const upb_map *map, size_t iter);
+
+/* Returns the key and value for this entry of the map. */
+upb_msgval upb_mapiter_key(const upb_map *map, size_t iter);
+upb_msgval upb_mapiter_value(const upb_map *map, size_t iter);
+
+/* Sets the value for this entry.  The iterator must not be done, and the
+ * iterator must not have been initialized const. */
+void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_H_ */
+
+#ifndef UPB_JSONDECODE_H_
+#define UPB_JSONDECODE_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+  UPB_JSONDEC_IGNOREUNKNOWN = 1
+};
+
+bool upb_json_decode(const char *buf, size_t size, upb_msg *msg,
+                     const upb_msgdef *m, const upb_symtab *any_pool,
+                     int options, upb_arena *arena, upb_status *status);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif  /* UPB_JSONDECODE_H_ */
+
+#ifndef UPB_JSONENCODE_H_
+#define UPB_JSONENCODE_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+  /* When set, emits 0/default values.  TODO(haberman): proto3 only? */
+  UPB_JSONENC_EMITDEFAULTS = 1,
+
+  /* When set, use normal (snake_caes) field names instead of JSON (camelCase)
+     names. */
+  UPB_JSONENC_PROTONAMES = 2
+};
+
+/* Encodes the given |msg| to JSON format.  The message's reflection is given in
+ * |m|.  The symtab in |symtab| is used to find extensions (if NULL, extensions
+ * will not be printed).
+ *
+ * Output is placed in the given buffer, and always NULL-terminated.  The output
+ * size (excluding NULL) is returned.  This means that a return value >= |size|
+ * implies that the output was truncated.  (These are the same semantics as
+ * snprintf()). */
+size_t upb_json_encode(const upb_msg *msg, const upb_msgdef *m,
+                       const upb_symtab *ext_pool, int options, char *buf,
+                       size_t size, upb_status *status);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif  /* UPB_JSONENCODE_H_ */
+/* See port_def.inc.  This should #undef all macros #defined there. */
+
+#undef UPB_MAPTYPE_STRING
+#undef UPB_SIZE
+#undef UPB_PTR_AT
+#undef UPB_READ_ONEOF
+#undef UPB_WRITE_ONEOF
+#undef UPB_INLINE
+#undef UPB_ALIGN_UP
+#undef UPB_ALIGN_DOWN
+#undef UPB_ALIGN_MALLOC
+#undef UPB_ALIGN_OF
+#undef UPB_FORCEINLINE
+#undef UPB_NOINLINE
+#undef UPB_NORETURN
+#undef UPB_MAX
+#undef UPB_MIN
+#undef UPB_UNUSED
+#undef UPB_ASSUME
+#undef UPB_ASSERT
+#undef UPB_UNREACHABLE
+#undef UPB_POISON_MEMORY_REGION
+#undef UPB_UNPOISON_MEMORY_REGION
+#undef UPB_ASAN
diff --git a/ruby/ext/google/protobuf_c/storage.c b/ruby/ext/google/protobuf_c/storage.c
deleted file mode 100644
index a3805c9..0000000
--- a/ruby/ext/google/protobuf_c/storage.c
+++ /dev/null
@@ -1,1198 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2014 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "protobuf.h"
-
-#include <math.h>
-
-#include <ruby/encoding.h>
-
-// -----------------------------------------------------------------------------
-// Ruby <-> native slot management.
-// -----------------------------------------------------------------------------
-
-#define CHARPTR_AT(msg, ofs) ((char*)msg + ofs)
-#define DEREF_OFFSET(msg, ofs, type) *(type*)CHARPTR_AT(msg, ofs)
-#define DEREF(memory, type) *(type*)(memory)
-
-size_t native_slot_size(upb_fieldtype_t type) {
-  switch (type) {
-    case UPB_TYPE_FLOAT:   return 4;
-    case UPB_TYPE_DOUBLE:  return 8;
-    case UPB_TYPE_BOOL:    return 1;
-    case UPB_TYPE_STRING:  return sizeof(VALUE);
-    case UPB_TYPE_BYTES:   return sizeof(VALUE);
-    case UPB_TYPE_MESSAGE: return sizeof(VALUE);
-    case UPB_TYPE_ENUM:    return 4;
-    case UPB_TYPE_INT32:   return 4;
-    case UPB_TYPE_INT64:   return 8;
-    case UPB_TYPE_UINT32:  return 4;
-    case UPB_TYPE_UINT64:  return 8;
-    default: return 0;
-  }
-}
-
-static bool is_ruby_num(VALUE value) {
-  return (TYPE(value) == T_FLOAT ||
-          TYPE(value) == T_FIXNUM ||
-          TYPE(value) == T_BIGNUM);
-}
-
-void native_slot_check_int_range_precision(const char* name, upb_fieldtype_t type, VALUE val) {
-  if (!is_ruby_num(val)) {
-    rb_raise(cTypeError, "Expected number type for integral field '%s' (given %s).",
-             name, rb_class2name(CLASS_OF(val)));
-  }
-
-  // NUM2{INT,UINT,LL,ULL} macros do the appropriate range checks on upper
-  // bound; we just need to do precision checks (i.e., disallow rounding) and
-  // check for < 0 on unsigned types.
-  if (TYPE(val) == T_FLOAT) {
-    double dbl_val = NUM2DBL(val);
-    if (floor(dbl_val) != dbl_val) {
-      rb_raise(rb_eRangeError,
-               "Non-integral floating point value assigned to integer field '%s' (given %s).",
-               name, rb_class2name(CLASS_OF(val)));
-    }
-  }
-  if (type == UPB_TYPE_UINT32 || type == UPB_TYPE_UINT64) {
-    if (NUM2DBL(val) < 0) {
-      rb_raise(rb_eRangeError,
-               "Assigning negative value to unsigned integer field '%s' (given %s).",
-               name, rb_class2name(CLASS_OF(val)));
-    }
-  }
-}
-
-VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value) {
-  rb_encoding* desired_encoding = (type == UPB_TYPE_STRING) ?
-      kRubyStringUtf8Encoding : kRubyString8bitEncoding;
-  VALUE desired_encoding_value = rb_enc_from_encoding(desired_encoding);
-
-  if (rb_obj_encoding(value) != desired_encoding_value || !OBJ_FROZEN(value)) {
-    // Note: this will not duplicate underlying string data unless necessary.
-    value = rb_str_encode(value, desired_encoding_value, 0, Qnil);
-
-    if (type == UPB_TYPE_STRING &&
-        rb_enc_str_coderange(value) == ENC_CODERANGE_BROKEN) {
-      rb_raise(rb_eEncodingError, "String is invalid UTF-8");
-    }
-
-    // Ensure the data remains valid.  Since we called #encode a moment ago,
-    // this does not freeze the string the user assigned.
-    rb_obj_freeze(value);
-  }
-
-  return value;
-}
-
-void native_slot_set(const char* name,
-                     upb_fieldtype_t type, VALUE type_class,
-                     void* memory, VALUE value) {
-  native_slot_set_value_and_case(name, type, type_class, memory, value, NULL, 0);
-}
-
-void native_slot_set_value_and_case(const char* name,
-                                    upb_fieldtype_t type, VALUE type_class,
-                                    void* memory, VALUE value,
-                                    uint32_t* case_memory,
-                                    uint32_t case_number) {
-  // Note that in order to atomically change the value in memory and the case
-  // value (w.r.t. Ruby VM calls), we must set the value at |memory| only after
-  // all Ruby VM calls are complete. The case is then set at the bottom of this
-  // function.
-  switch (type) {
-    case UPB_TYPE_FLOAT:
-      if (!is_ruby_num(value)) {
-        rb_raise(cTypeError, "Expected number type for float field '%s' (given %s).",
-                 name, rb_class2name(CLASS_OF(value)));
-      }
-      DEREF(memory, float) = NUM2DBL(value);
-      break;
-    case UPB_TYPE_DOUBLE:
-      if (!is_ruby_num(value)) {
-        rb_raise(cTypeError, "Expected number type for double field '%s' (given %s).",
-                 name, rb_class2name(CLASS_OF(value)));
-      }
-      DEREF(memory, double) = NUM2DBL(value);
-      break;
-    case UPB_TYPE_BOOL: {
-      int8_t val = -1;
-      if (value == Qtrue) {
-        val = 1;
-      } else if (value == Qfalse) {
-        val = 0;
-      } else {
-        rb_raise(cTypeError, "Invalid argument for boolean field '%s' (given %s).",
-                 name, rb_class2name(CLASS_OF(value)));
-      }
-      DEREF(memory, int8_t) = val;
-      break;
-    }
-    case UPB_TYPE_STRING:
-      if (CLASS_OF(value) == rb_cSymbol) {
-        value = rb_funcall(value, rb_intern("to_s"), 0);
-      } else if (CLASS_OF(value) != rb_cString) {
-        rb_raise(cTypeError, "Invalid argument for string field '%s' (given %s).",
-                 name, rb_class2name(CLASS_OF(value)));
-      }
-
-      DEREF(memory, VALUE) = native_slot_encode_and_freeze_string(type, value);
-      break;
-
-    case UPB_TYPE_BYTES: {
-      if (CLASS_OF(value) != rb_cString) {
-        rb_raise(cTypeError, "Invalid argument for bytes field '%s' (given %s).",
-                 name, rb_class2name(CLASS_OF(value)));
-      }
-
-      DEREF(memory, VALUE) = native_slot_encode_and_freeze_string(type, value);
-      break;
-    }
-    case UPB_TYPE_MESSAGE: {
-      if (CLASS_OF(value) == CLASS_OF(Qnil)) {
-        value = Qnil;
-      } else if (CLASS_OF(value) != type_class) {
-        // check for possible implicit conversions
-        VALUE converted_value = Qnil;
-        const char* field_type_name = rb_class2name(type_class);
-
-        if (strcmp(field_type_name, "Google::Protobuf::Timestamp") == 0 &&
-            rb_obj_is_kind_of(value, rb_cTime)) {
-          // Time -> Google::Protobuf::Timestamp
-          VALUE hash = rb_hash_new();
-          rb_hash_aset(hash, rb_str_new2("seconds"),
-                       rb_funcall(value, rb_intern("to_i"), 0));
-          rb_hash_aset(hash, rb_str_new2("nanos"),
-                       rb_funcall(value, rb_intern("nsec"), 0));
-          {
-            VALUE args[1] = {hash};
-            converted_value = rb_class_new_instance(1, args, type_class);
-          }
-        } else if (strcmp(field_type_name, "Google::Protobuf::Duration") == 0 &&
-                   rb_obj_is_kind_of(value, rb_cNumeric)) {
-          // Numeric -> Google::Protobuf::Duration
-          VALUE hash = rb_hash_new();
-          rb_hash_aset(hash, rb_str_new2("seconds"),
-                       rb_funcall(value, rb_intern("to_i"), 0));
-          {
-            VALUE n_value =
-                rb_funcall(value, rb_intern("remainder"), 1, INT2NUM(1));
-            n_value =
-                rb_funcall(n_value, rb_intern("*"), 1, INT2NUM(1000000000));
-            n_value = rb_funcall(n_value, rb_intern("round"), 0);
-            rb_hash_aset(hash, rb_str_new2("nanos"), n_value);
-          }
-          {
-            VALUE args[1] = { hash };
-            converted_value = rb_class_new_instance(1, args, type_class);
-          }
-        }
-
-        // raise if no suitable conversaion could be found
-        if (converted_value == Qnil) {
-          rb_raise(cTypeError,
-                   "Invalid type %s to assign to submessage field '%s'.",
-                  rb_class2name(CLASS_OF(value)), name);
-        } else {
-          value = converted_value;
-        }
-      }
-      DEREF(memory, VALUE) = value;
-      break;
-    }
-    case UPB_TYPE_ENUM: {
-      int32_t int_val = 0;
-      if (TYPE(value) == T_STRING) {
-        value = rb_funcall(value, rb_intern("to_sym"), 0);
-      } else if (!is_ruby_num(value) && TYPE(value) != T_SYMBOL) {
-        rb_raise(cTypeError,
-                 "Expected number or symbol type for enum field '%s'.", name);
-      }
-      if (TYPE(value) == T_SYMBOL) {
-        // Ensure that the given symbol exists in the enum module.
-        VALUE lookup = rb_funcall(type_class, rb_intern("resolve"), 1, value);
-        if (lookup == Qnil) {
-          rb_raise(rb_eRangeError, "Unknown symbol value for enum field '%s'.", name);
-        } else {
-          int_val = NUM2INT(lookup);
-        }
-      } else {
-        native_slot_check_int_range_precision(name, UPB_TYPE_INT32, value);
-        int_val = NUM2INT(value);
-      }
-      DEREF(memory, int32_t) = int_val;
-      break;
-    }
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_UINT64:
-      native_slot_check_int_range_precision(name, type, value);
-      switch (type) {
-      case UPB_TYPE_INT32:
-        DEREF(memory, int32_t) = NUM2INT(value);
-        break;
-      case UPB_TYPE_INT64:
-        DEREF(memory, int64_t) = NUM2LL(value);
-        break;
-      case UPB_TYPE_UINT32:
-        DEREF(memory, uint32_t) = NUM2UINT(value);
-        break;
-      case UPB_TYPE_UINT64:
-        DEREF(memory, uint64_t) = NUM2ULL(value);
-        break;
-      default:
-        break;
-      }
-      break;
-    default:
-      break;
-  }
-
-  if (case_memory != NULL) {
-    *case_memory = case_number;
-  }
-}
-
-VALUE native_slot_get(upb_fieldtype_t type,
-                      VALUE type_class,
-                      const void* memory) {
-  switch (type) {
-    case UPB_TYPE_FLOAT:
-      return DBL2NUM(DEREF(memory, float));
-    case UPB_TYPE_DOUBLE:
-      return DBL2NUM(DEREF(memory, double));
-    case UPB_TYPE_BOOL:
-      return DEREF(memory, int8_t) ? Qtrue : Qfalse;
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-      return DEREF(memory, VALUE);
-    case UPB_TYPE_MESSAGE: {
-      VALUE val = DEREF(memory, VALUE);
-
-      // Lazily expand wrapper type if necessary.
-      int type = TYPE(val);
-      if (type != T_DATA && type != T_NIL) {
-        // This must be a wrapper type.
-        val = ruby_wrapper_type(type_class, val);
-        DEREF(memory, VALUE) = val;
-      }
-
-      return val;
-    }
-    case UPB_TYPE_ENUM: {
-      int32_t val = DEREF(memory, int32_t);
-      VALUE symbol = enum_lookup(type_class, INT2NUM(val));
-      if (symbol == Qnil) {
-        return INT2NUM(val);
-      } else {
-        return symbol;
-      }
-    }
-    case UPB_TYPE_INT32:
-      return INT2NUM(DEREF(memory, int32_t));
-    case UPB_TYPE_INT64:
-      return LL2NUM(DEREF(memory, int64_t));
-    case UPB_TYPE_UINT32:
-      return UINT2NUM(DEREF(memory, uint32_t));
-    case UPB_TYPE_UINT64:
-      return ULL2NUM(DEREF(memory, uint64_t));
-    default:
-      return Qnil;
-  }
-}
-
-void native_slot_init(upb_fieldtype_t type, void* memory) {
-  switch (type) {
-    case UPB_TYPE_FLOAT:
-      DEREF(memory, float) = 0.0;
-      break;
-    case UPB_TYPE_DOUBLE:
-      DEREF(memory, double) = 0.0;
-      break;
-    case UPB_TYPE_BOOL:
-      DEREF(memory, int8_t) = 0;
-      break;
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-      DEREF(memory, VALUE) = rb_str_new2("");
-      rb_enc_associate(DEREF(memory, VALUE), (type == UPB_TYPE_BYTES) ?
-                       kRubyString8bitEncoding : kRubyStringUtf8Encoding);
-      break;
-    case UPB_TYPE_MESSAGE:
-      DEREF(memory, VALUE) = Qnil;
-      break;
-    case UPB_TYPE_ENUM:
-    case UPB_TYPE_INT32:
-      DEREF(memory, int32_t) = 0;
-      break;
-    case UPB_TYPE_INT64:
-      DEREF(memory, int64_t) = 0;
-      break;
-    case UPB_TYPE_UINT32:
-      DEREF(memory, uint32_t) = 0;
-      break;
-    case UPB_TYPE_UINT64:
-      DEREF(memory, uint64_t) = 0;
-      break;
-    default:
-      break;
-  }
-}
-
-void native_slot_mark(upb_fieldtype_t type, void* memory) {
-  switch (type) {
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-    case UPB_TYPE_MESSAGE:
-      rb_gc_mark(DEREF(memory, VALUE));
-      break;
-    default:
-      break;
-  }
-}
-
-void native_slot_dup(upb_fieldtype_t type, void* to, void* from) {
-  memcpy(to, from, native_slot_size(type));
-}
-
-void native_slot_deep_copy(upb_fieldtype_t type, VALUE type_class, void* to,
-                           void* from) {
-  switch (type) {
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      VALUE from_val = DEREF(from, VALUE);
-      DEREF(to, VALUE) = (from_val != Qnil) ?
-          rb_funcall(from_val, rb_intern("dup"), 0) : Qnil;
-      break;
-    }
-    case UPB_TYPE_MESSAGE: {
-      VALUE from_val = native_slot_get(type, type_class, from);
-      DEREF(to, VALUE) = (from_val != Qnil) ?
-          Message_deep_copy(from_val) : Qnil;
-      break;
-    }
-    default:
-      memcpy(to, from, native_slot_size(type));
-  }
-}
-
-bool native_slot_eq(upb_fieldtype_t type, VALUE type_class, void* mem1,
-                    void* mem2) {
-  switch (type) {
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-    case UPB_TYPE_MESSAGE: {
-      VALUE val1 = native_slot_get(type, type_class, mem1);
-      VALUE val2 = native_slot_get(type, type_class, mem2);
-      VALUE ret = rb_funcall(val1, rb_intern("=="), 1, val2);
-      return ret == Qtrue;
-    }
-    default:
-      return !memcmp(mem1, mem2, native_slot_size(type));
-  }
-}
-
-// -----------------------------------------------------------------------------
-// Map field utilities.
-// -----------------------------------------------------------------------------
-
-const upb_msgdef* tryget_map_entry_msgdef(const upb_fielddef* field) {
-  const upb_msgdef* subdef;
-  if (upb_fielddef_label(field) != UPB_LABEL_REPEATED ||
-      upb_fielddef_type(field) != UPB_TYPE_MESSAGE) {
-    return NULL;
-  }
-  subdef = upb_fielddef_msgsubdef(field);
-  return upb_msgdef_mapentry(subdef) ? subdef : NULL;
-}
-
-const upb_msgdef *map_entry_msgdef(const upb_fielddef* field) {
-  const upb_msgdef* subdef = tryget_map_entry_msgdef(field);
-  assert(subdef);
-  return subdef;
-}
-
-bool is_map_field(const upb_fielddef *field) {
-  const upb_msgdef* subdef = tryget_map_entry_msgdef(field);
-  if (subdef == NULL) return false;
-
-  // Map fields are a proto3 feature.
-  // If we're using proto2 syntax we need to fallback to the repeated field.
-  return upb_msgdef_syntax(subdef) == UPB_SYNTAX_PROTO3;
-}
-
-const upb_fielddef* map_field_key(const upb_fielddef* field) {
-  const upb_msgdef* subdef = map_entry_msgdef(field);
-  return map_entry_key(subdef);
-}
-
-const upb_fielddef* map_field_value(const upb_fielddef* field) {
-  const upb_msgdef* subdef = map_entry_msgdef(field);
-  return map_entry_value(subdef);
-}
-
-const upb_fielddef* map_entry_key(const upb_msgdef* msgdef) {
-  const upb_fielddef* key_field = upb_msgdef_itof(msgdef, MAP_KEY_FIELD);
-  assert(key_field != NULL);
-  return key_field;
-}
-
-const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) {
-  const upb_fielddef* value_field = upb_msgdef_itof(msgdef, MAP_VALUE_FIELD);
-  assert(value_field != NULL);
-  return value_field;
-}
-
-// -----------------------------------------------------------------------------
-// Memory layout management.
-// -----------------------------------------------------------------------------
-
-bool field_contains_hasbit(MessageLayout* layout,
-                            const upb_fielddef* field) {
-  return layout->fields[upb_fielddef_index(field)].hasbit !=
-      MESSAGE_FIELD_NO_HASBIT;
-}
-
-static size_t align_up_to(size_t offset, size_t granularity) {
-  // Granularity must be a power of two.
-  return (offset + granularity - 1) & ~(granularity - 1);
-}
-
-bool is_value_field(const upb_fielddef* f) {
-  return upb_fielddef_isseq(f) || upb_fielddef_issubmsg(f) ||
-         upb_fielddef_isstring(f);
-}
-
-void create_layout(Descriptor* desc) {
-  const upb_msgdef *msgdef = desc->msgdef;
-  MessageLayout* layout = ALLOC(MessageLayout);
-  int nfields = upb_msgdef_numfields(msgdef);
-  int noneofs = upb_msgdef_numrealoneofs(msgdef);
-  upb_msg_field_iter it;
-  upb_msg_oneof_iter oit;
-  size_t off = 0;
-  size_t hasbit = 0;
-  int i;
-
-  (void)i;
-
-  layout->empty_template = NULL;
-  layout->desc = desc;
-  desc->layout = layout;
-
-  layout->fields = ALLOC_N(MessageField, nfields);
-  layout->oneofs = NULL;
-
-  if (noneofs > 0) {
-    layout->oneofs = ALLOC_N(MessageOneof, noneofs);
-  }
-
-#ifndef NDEBUG
-  for (i = 0; i < nfields; i++) {
-    layout->fields[i].offset = -1;
-  }
-
-  for (i = 0; i < noneofs; i++) {
-    layout->oneofs[i].offset = -1;
-  }
-#endif
-
-  for (upb_msg_field_begin(&it, msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    if (upb_fielddef_haspresence(field) &&
-        !upb_fielddef_realcontainingoneof(field)) {
-      layout->fields[upb_fielddef_index(field)].hasbit = hasbit++;
-    } else {
-      layout->fields[upb_fielddef_index(field)].hasbit =
-          MESSAGE_FIELD_NO_HASBIT;
-    }
-  }
-
-  if (hasbit != 0) {
-    off += (hasbit + 8 - 1) / 8;
-  }
-
-  off = align_up_to(off, sizeof(VALUE));
-  layout->value_offset = off;
-  layout->repeated_count = 0;
-  layout->map_count = 0;
-  layout->value_count = 0;
-
-  // Place all VALUE fields for repeated fields.
-  for (upb_msg_field_begin(&it, msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    if (upb_fielddef_realcontainingoneof(field) || !upb_fielddef_isseq(field) ||
-        upb_fielddef_ismap(field)) {
-      continue;
-    }
-
-    layout->fields[upb_fielddef_index(field)].offset = off;
-    off += sizeof(VALUE);
-    layout->repeated_count++;
-  }
-
-  // Place all VALUE fields for map fields.
-  for (upb_msg_field_begin(&it, msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    if (upb_fielddef_realcontainingoneof(field) || !upb_fielddef_isseq(field) ||
-        !upb_fielddef_ismap(field)) {
-      continue;
-    }
-
-    layout->fields[upb_fielddef_index(field)].offset = off;
-    off += sizeof(VALUE);
-    layout->map_count++;
-  }
-
-  layout->value_count = layout->repeated_count + layout->map_count;
-
-  // Next place all other (non-oneof) VALUE fields.
-  for (upb_msg_field_begin(&it, msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    if (upb_fielddef_realcontainingoneof(field) || !is_value_field(field) ||
-        upb_fielddef_isseq(field)) {
-      continue;
-    }
-
-    layout->fields[upb_fielddef_index(field)].offset = off;
-    off += sizeof(VALUE);
-    layout->value_count++;
-  }
-
-  // Now place all other (non-oneof) fields.
-  for (upb_msg_field_begin(&it, msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    size_t field_size;
-
-    if (upb_fielddef_realcontainingoneof(field) || is_value_field(field)) {
-      continue;
-    }
-
-    // Allocate |field_size| bytes for this field in the layout.
-    field_size = native_slot_size(upb_fielddef_type(field));
-
-    // Align current offset up to |size| granularity.
-    off = align_up_to(off, field_size);
-    layout->fields[upb_fielddef_index(field)].offset = off;
-    off += field_size;
-  }
-
-  // Handle oneofs now -- we iterate over oneofs specifically and allocate only
-  // one slot per oneof.
-  //
-  // We assign all value slots first, then pack the 'case' fields at the end,
-  // since in the common case (modern 64-bit platform) these are 8 bytes and 4
-  // bytes respectively and we want to avoid alignment overhead.
-  //
-  // Note that we reserve 4 bytes (a uint32) per 'case' slot because the value
-  // space for oneof cases is conceptually as wide as field tag numbers. In
-  // practice, it's unlikely that a oneof would have more than e.g. 256 or 64K
-  // members (8 or 16 bits respectively), so conceivably we could assign
-  // consecutive case numbers and then pick a smaller oneof case slot size, but
-  // the complexity to implement this indirection is probably not worthwhile.
-  for (upb_msg_oneof_begin(&oit, msgdef);
-       !upb_msg_oneof_done(&oit);
-       upb_msg_oneof_next(&oit)) {
-    const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
-    upb_oneof_iter fit;
-
-    // Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between
-    // all fields.
-    size_t field_size = NATIVE_SLOT_MAX_SIZE;
-
-    if (upb_oneofdef_issynthetic(oneof)) continue;
-    assert(upb_oneofdef_index(oneof) < noneofs);
-
-    // Align the offset.
-    off = align_up_to(off, field_size);
-    // Assign all fields in the oneof this same offset.
-    for (upb_oneof_begin(&fit, oneof);
-         !upb_oneof_done(&fit);
-         upb_oneof_next(&fit)) {
-      const upb_fielddef* field = upb_oneof_iter_field(&fit);
-      layout->fields[upb_fielddef_index(field)].offset = off;
-      layout->oneofs[upb_oneofdef_index(oneof)].offset = off;
-    }
-    off += field_size;
-  }
-
-  // Now the case fields.
-  for (upb_msg_oneof_begin(&oit, msgdef);
-       !upb_msg_oneof_done(&oit);
-       upb_msg_oneof_next(&oit)) {
-    const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
-    size_t field_size = sizeof(uint32_t);
-    if (upb_oneofdef_issynthetic(oneof)) continue;
-    assert(upb_oneofdef_index(oneof) < noneofs);
-    // Align the offset.
-    off = (off + field_size - 1) & ~(field_size - 1);
-    layout->oneofs[upb_oneofdef_index(oneof)].case_offset = off;
-    off += field_size;
-  }
-
-  layout->size = off;
-  layout->msgdef = msgdef;
-
-#ifndef NDEBUG
-  for (i = 0; i < nfields; i++) {
-    assert(layout->fields[i].offset != -1);
-  }
-
-  for (i = 0; i < noneofs; i++) {
-    assert(layout->oneofs[i].offset != -1);
-  }
-#endif
-
-  // Create the empty message template.
-  layout->empty_template = ALLOC_N(char, layout->size);
-  memset(layout->empty_template, 0, layout->size);
-
-  for (upb_msg_field_begin(&it, layout->msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    layout_clear(layout, layout->empty_template, upb_msg_iter_field(&it));
-  }
-}
-
-void free_layout(MessageLayout* layout) {
-  xfree(layout->empty_template);
-  xfree(layout->fields);
-  xfree(layout->oneofs);
-  xfree(layout);
-}
-
-VALUE field_type_class(const MessageLayout* layout, const upb_fielddef* field) {
-  VALUE type_class = Qnil;
-  if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
-    VALUE submsgdesc = get_msgdef_obj(layout->desc->descriptor_pool,
-                                      upb_fielddef_msgsubdef(field));
-    type_class = Descriptor_msgclass(submsgdesc);
-  } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) {
-    VALUE subenumdesc = get_enumdef_obj(layout->desc->descriptor_pool,
-                                        upb_fielddef_enumsubdef(field));
-    type_class = EnumDescriptor_enummodule(subenumdesc);
-  }
-  return type_class;
-}
-
-static void* slot_memory(MessageLayout* layout,
-                         const void* storage,
-                         const upb_fielddef* field) {
-  return ((uint8_t *)storage) +
-      layout->fields[upb_fielddef_index(field)].offset;
-}
-
-static uint32_t* slot_oneof_case(MessageLayout* layout,
-                                 const void* storage,
-                                 const upb_oneofdef* oneof) {
-  return (uint32_t*)(((uint8_t*)storage) +
-                     layout->oneofs[upb_oneofdef_index(oneof)].case_offset);
-}
-
-uint32_t slot_read_oneof_case(MessageLayout* layout, const void* storage,
-                              const upb_oneofdef* oneof) {
-  uint32_t* ptr = slot_oneof_case(layout, storage, oneof);
-  return *ptr & ~ONEOF_CASE_MASK;
-}
-
-static void slot_set_hasbit(MessageLayout* layout,
-                            const void* storage,
-                            const upb_fielddef* field) {
-  size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit;
-  assert(hasbit != MESSAGE_FIELD_NO_HASBIT);
-
-  ((uint8_t*)storage)[hasbit / 8] |= 1 << (hasbit % 8);
-}
-
-static void slot_clear_hasbit(MessageLayout* layout,
-                              const void* storage,
-                              const upb_fielddef* field) {
-  size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit;
-  assert(hasbit != MESSAGE_FIELD_NO_HASBIT);
-  ((uint8_t*)storage)[hasbit / 8] &= ~(1 << (hasbit % 8));
-}
-
-static bool slot_is_hasbit_set(MessageLayout* layout,
-                            const void* storage,
-                            const upb_fielddef* field) {
-  size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit;
-  assert(field_contains_hasbit(layout, field));
-  return DEREF_OFFSET(
-      (uint8_t*)storage, hasbit / 8, char) & (1 << (hasbit % 8));
-}
-
-VALUE layout_has(MessageLayout* layout,
-                 const void* storage,
-                 const upb_fielddef* field) {
-  const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
-  assert(upb_fielddef_haspresence(field));
-  if (oneof) {
-    uint32_t oneof_case = slot_read_oneof_case(layout, storage, oneof);
-    return oneof_case == upb_fielddef_number(field) ? Qtrue : Qfalse;
-  } else {
-    return slot_is_hasbit_set(layout, storage, field) ? Qtrue : Qfalse;
-  }
-}
-
-void layout_clear(MessageLayout* layout,
-                 const void* storage,
-                 const upb_fielddef* field) {
-  void* memory = slot_memory(layout, storage, field);
-  const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
-
-  if (field_contains_hasbit(layout, field)) {
-    slot_clear_hasbit(layout, storage, field);
-  }
-
-  if (oneof) {
-    uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof);
-    memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
-    *oneof_case = ONEOF_CASE_NONE;
-  } else if (is_map_field(field)) {
-    VALUE map = Qnil;
-
-    const upb_fielddef* key_field = map_field_key(field);
-    const upb_fielddef* value_field = map_field_value(field);
-    VALUE type_class = field_type_class(layout, value_field);
-
-    if (type_class != Qnil) {
-      VALUE args[3] = {
-        fieldtype_to_ruby(upb_fielddef_type(key_field)),
-        fieldtype_to_ruby(upb_fielddef_type(value_field)),
-        type_class,
-      };
-      map = rb_class_new_instance(3, args, cMap);
-    } else {
-      VALUE args[2] = {
-        fieldtype_to_ruby(upb_fielddef_type(key_field)),
-        fieldtype_to_ruby(upb_fielddef_type(value_field)),
-      };
-      map = rb_class_new_instance(2, args, cMap);
-    }
-
-    DEREF(memory, VALUE) = map;
-  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
-    VALUE ary = Qnil;
-
-    VALUE type_class = field_type_class(layout, field);
-
-    if (type_class != Qnil) {
-      VALUE args[2] = {
-        fieldtype_to_ruby(upb_fielddef_type(field)),
-        type_class,
-      };
-      ary = rb_class_new_instance(2, args, cRepeatedField);
-    } else {
-      VALUE args[1] = { fieldtype_to_ruby(upb_fielddef_type(field)) };
-      ary = rb_class_new_instance(1, args, cRepeatedField);
-    }
-
-    DEREF(memory, VALUE) = ary;
-  } else {
-    native_slot_set(upb_fielddef_name(field), upb_fielddef_type(field),
-                    field_type_class(layout, field), memory,
-                    layout_get_default(field));
-  }
-}
-
-VALUE layout_get_default(const upb_fielddef *field) {
-  switch (upb_fielddef_type(field)) {
-    case UPB_TYPE_FLOAT:   return DBL2NUM(upb_fielddef_defaultfloat(field));
-    case UPB_TYPE_DOUBLE:  return DBL2NUM(upb_fielddef_defaultdouble(field));
-    case UPB_TYPE_BOOL:
-      return upb_fielddef_defaultbool(field) ? Qtrue : Qfalse;
-    case UPB_TYPE_MESSAGE: return Qnil;
-    case UPB_TYPE_ENUM: {
-      const upb_enumdef *enumdef = upb_fielddef_enumsubdef(field);
-      int32_t num = upb_fielddef_defaultint32(field);
-      const char *label = upb_enumdef_iton(enumdef, num);
-      if (label) {
-        return ID2SYM(rb_intern(label));
-      } else {
-        return INT2NUM(num);
-      }
-    }
-    case UPB_TYPE_INT32:   return INT2NUM(upb_fielddef_defaultint32(field));
-    case UPB_TYPE_INT64:   return LL2NUM(upb_fielddef_defaultint64(field));;
-    case UPB_TYPE_UINT32:  return UINT2NUM(upb_fielddef_defaultuint32(field));
-    case UPB_TYPE_UINT64:  return ULL2NUM(upb_fielddef_defaultuint64(field));
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      size_t size;
-      const char *str = upb_fielddef_defaultstr(field, &size);
-      return get_frozen_string(str, size,
-                               upb_fielddef_type(field) == UPB_TYPE_BYTES);
-    }
-    default: return Qnil;
-  }
-}
-
-VALUE layout_get(MessageLayout* layout,
-                 const void* storage,
-                 const upb_fielddef* field) {
-  void* memory = slot_memory(layout, storage, field);
-  const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
-  bool field_set;
-  if (field_contains_hasbit(layout, field)) {
-    field_set = slot_is_hasbit_set(layout, storage, field);
-  } else {
-    field_set = true;
-  }
-
-  if (oneof) {
-    uint32_t oneof_case = slot_read_oneof_case(layout, storage, oneof);
-    if (oneof_case != upb_fielddef_number(field)) {
-      return layout_get_default(field);
-    }
-    return native_slot_get(upb_fielddef_type(field),
-                           field_type_class(layout, field), memory);
-  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
-    return *((VALUE *)memory);
-  } else if (!field_set) {
-    return layout_get_default(field);
-  } else {
-    return native_slot_get(upb_fielddef_type(field),
-                           field_type_class(layout, field), memory);
-  }
-}
-
-static void check_repeated_field_type(const MessageLayout* layout, VALUE val,
-                                      const upb_fielddef* field) {
-  RepeatedField* self;
-  assert(upb_fielddef_label(field) == UPB_LABEL_REPEATED);
-
-  if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
-      RTYPEDDATA_TYPE(val) != &RepeatedField_type) {
-    rb_raise(cTypeError, "Expected repeated field array");
-  }
-
-  self = ruby_to_RepeatedField(val);
-  if (self->field_type != upb_fielddef_type(field)) {
-    rb_raise(cTypeError, "Repeated field array has wrong element type");
-  }
-
-  if (self->field_type_class != field_type_class(layout, field)) {
-    rb_raise(cTypeError, "Repeated field array has wrong message/enum class");
-  }
-}
-
-static void check_map_field_type(const MessageLayout* layout, VALUE val,
-                                 const upb_fielddef* field) {
-  const upb_fielddef* key_field = map_field_key(field);
-  const upb_fielddef* value_field = map_field_value(field);
-  Map* self;
-
-  if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
-      RTYPEDDATA_TYPE(val) != &Map_type) {
-    rb_raise(cTypeError, "Expected Map instance");
-  }
-
-  self = ruby_to_Map(val);
-  if (self->key_type != upb_fielddef_type(key_field)) {
-    rb_raise(cTypeError, "Map key type does not match field's key type");
-  }
-  if (self->value_type != upb_fielddef_type(value_field)) {
-    rb_raise(cTypeError, "Map value type does not match field's value type");
-  }
-  if (self->value_type_class != field_type_class(layout, value_field)) {
-    rb_raise(cTypeError, "Map value type has wrong message/enum class");
-  }
-}
-
-void layout_set(MessageLayout* layout,
-                void* storage,
-                const upb_fielddef* field,
-                VALUE val) {
-  void* memory = slot_memory(layout, storage, field);
-  const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
-
-  if (oneof) {
-    uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof);
-    if (val == Qnil) {
-      // Assigning nil to a oneof field clears the oneof completely.
-      *oneof_case = ONEOF_CASE_NONE;
-      memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
-    } else {
-      // The transition between field types for a single oneof (union) slot is
-      // somewhat complex because we need to ensure that a GC triggered at any
-      // point by a call into the Ruby VM sees a valid state for this field and
-      // does not either go off into the weeds (following what it thinks is a
-      // VALUE but is actually a different field type) or miss an object (seeing
-      // what it thinks is a primitive field but is actually a VALUE for the new
-      // field type).
-      //
-      // In order for the transition to be safe, the oneof case slot must be in
-      // sync with the value slot whenever the Ruby VM has been called. Thus, we
-      // use native_slot_set_value_and_case(), which ensures that both the value
-      // and case number are altered atomically (w.r.t. the Ruby VM).
-      uint32_t case_value = upb_fielddef_number(field);
-      if (upb_fielddef_issubmsg(field) || upb_fielddef_isstring(field)) {
-        case_value |= ONEOF_CASE_MASK;
-      }
-
-      native_slot_set_value_and_case(
-          upb_fielddef_name(field), upb_fielddef_type(field),
-          field_type_class(layout, field), memory, val, oneof_case, case_value);
-    }
-  } else if (is_map_field(field)) {
-    check_map_field_type(layout, val, field);
-    DEREF(memory, VALUE) = val;
-  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
-    check_repeated_field_type(layout, val, field);
-    DEREF(memory, VALUE) = val;
-  } else {
-    native_slot_set(upb_fielddef_name(field), upb_fielddef_type(field),
-                    field_type_class(layout, field), memory, val);
-  }
-
-  if (layout->fields[upb_fielddef_index(field)].hasbit !=
-      MESSAGE_FIELD_NO_HASBIT) {
-    if (val == Qnil) {
-      // No other field type has a hasbit and allows nil assignment.
-      if (upb_fielddef_type(field) != UPB_TYPE_MESSAGE) {
-        fprintf(stderr, "field: %s\n", upb_fielddef_fullname(field));
-      }
-      assert(upb_fielddef_type(field) == UPB_TYPE_MESSAGE);
-      slot_clear_hasbit(layout, storage, field);
-    } else {
-      slot_set_hasbit(layout, storage, field);
-    }
-  }
-}
-
-void layout_init(MessageLayout* layout, void* storage) {
-  VALUE* value = (VALUE*)CHARPTR_AT(storage, layout->value_offset);
-  int i;
-
-  for (i = 0; i < layout->repeated_count; i++, value++) {
-    *value = RepeatedField_new_this_type(*value);
-  }
-
-  for (i = 0; i < layout->map_count; i++, value++) {
-    *value = Map_new_this_type(*value);
-  }
-}
-
-void layout_mark(MessageLayout* layout, void* storage) {
-  VALUE* values = (VALUE*)CHARPTR_AT(storage, layout->value_offset);
-  int noneofs = upb_msgdef_numrealoneofs(layout->msgdef);
-  int i;
-
-  for (i = 0; i < layout->value_count; i++) {
-    rb_gc_mark(values[i]);
-  }
-
-  for (i = 0; i < noneofs; i++) {
-    MessageOneof* oneof = &layout->oneofs[i];
-    uint32_t* case_ptr = (uint32_t*)CHARPTR_AT(storage, oneof->case_offset);
-    if (*case_ptr & ONEOF_CASE_MASK) {
-      rb_gc_mark(DEREF_OFFSET(storage, oneof->offset, VALUE));
-    }
-  }
-}
-
-void layout_dup(MessageLayout* layout, void* to, void* from) {
-  upb_msg_field_iter it;
-  for (upb_msg_field_begin(&it, layout->msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
-
-    void* to_memory = slot_memory(layout, to, field);
-    void* from_memory = slot_memory(layout, from, field);
-
-    if (oneof) {
-      uint32_t* to_oneof_case = slot_oneof_case(layout, to, oneof);
-      uint32_t* from_oneof_case = slot_oneof_case(layout, from, oneof);
-      if (slot_read_oneof_case(layout, from, oneof) ==
-          upb_fielddef_number(field)) {
-        *to_oneof_case = *from_oneof_case;
-        native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
-      }
-    } else if (is_map_field(field)) {
-      DEREF(to_memory, VALUE) = Map_dup(DEREF(from_memory, VALUE));
-    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
-      DEREF(to_memory, VALUE) = RepeatedField_dup(DEREF(from_memory, VALUE));
-    } else {
-      if (field_contains_hasbit(layout, field)) {
-        if (!slot_is_hasbit_set(layout, from, field)) continue;
-        slot_set_hasbit(layout, to, field);
-      }
-
-      native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
-    }
-  }
-}
-
-void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
-  upb_msg_field_iter it;
-  for (upb_msg_field_begin(&it, layout->msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
-
-    void* to_memory = slot_memory(layout, to, field);
-    void* from_memory = slot_memory(layout, from, field);
-
-    if (oneof) {
-      uint32_t* to_oneof_case = slot_oneof_case(layout, to, oneof);
-      uint32_t* from_oneof_case = slot_oneof_case(layout, from, oneof);
-      if (slot_read_oneof_case(layout, from, oneof) ==
-          upb_fielddef_number(field)) {
-        *to_oneof_case = *from_oneof_case;
-        native_slot_deep_copy(upb_fielddef_type(field),
-                              field_type_class(layout, field), to_memory,
-                              from_memory);
-      }
-    } else if (is_map_field(field)) {
-      DEREF(to_memory, VALUE) =
-          Map_deep_copy(DEREF(from_memory, VALUE));
-    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
-      DEREF(to_memory, VALUE) =
-          RepeatedField_deep_copy(DEREF(from_memory, VALUE));
-    } else {
-      if (field_contains_hasbit(layout, field)) {
-        if (!slot_is_hasbit_set(layout, from, field)) continue;
-        slot_set_hasbit(layout, to, field);
-      }
-
-      native_slot_deep_copy(upb_fielddef_type(field),
-                            field_type_class(layout, field), to_memory,
-                            from_memory);
-    }
-  }
-}
-
-VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
-  upb_msg_field_iter it;
-  for (upb_msg_field_begin(&it, layout->msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
-
-    void* msg1_memory = slot_memory(layout, msg1, field);
-    void* msg2_memory = slot_memory(layout, msg2, field);
-
-    if (oneof) {
-      uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, oneof);
-      uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, oneof);
-      if (*msg1_oneof_case != *msg2_oneof_case ||
-          (slot_read_oneof_case(layout, msg1, oneof) ==
-               upb_fielddef_number(field) &&
-           !native_slot_eq(upb_fielddef_type(field),
-                           field_type_class(layout, field), msg1_memory,
-                           msg2_memory))) {
-        return Qfalse;
-      }
-    } else if (is_map_field(field)) {
-      if (!Map_eq(DEREF(msg1_memory, VALUE),
-                  DEREF(msg2_memory, VALUE))) {
-        return Qfalse;
-      }
-    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
-      if (!RepeatedField_eq(DEREF(msg1_memory, VALUE),
-                            DEREF(msg2_memory, VALUE))) {
-        return Qfalse;
-      }
-    } else {
-      if (field_contains_hasbit(layout, field) &&
-          slot_is_hasbit_set(layout, msg1, field) !=
-              slot_is_hasbit_set(layout, msg2, field)) {
-        // TODO(haberman): I don't think we should actually care about hasbits
-        // here: an unset default should be able to equal a set default. But we
-        // can address this later (will also have to make sure defaults are
-        // being properly set when hasbit is clear).
-        return Qfalse;
-      }
-      if (!native_slot_eq(upb_fielddef_type(field),
-                          field_type_class(layout, field), msg1_memory,
-                          msg2_memory)) {
-        return Qfalse;
-      }
-    }
-  }
-  return Qtrue;
-}
-
-VALUE layout_hash(MessageLayout* layout, void* storage) {
-  upb_msg_field_iter it;
-  st_index_t h = rb_hash_start(0);
-  VALUE hash_sym = rb_intern("hash");
-  for (upb_msg_field_begin(&it, layout->msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    VALUE field_val = layout_get(layout, storage, field);
-    h = rb_hash_uint(h, NUM2LONG(rb_funcall(field_val, hash_sym, 0)));
-  }
-  h = rb_hash_end(h);
-
-  return INT2FIX(h);
-}
-
-VALUE layout_inspect(MessageLayout* layout, void* storage) {
-  VALUE str = rb_str_new2("");
-
-  upb_msg_field_iter it;
-  bool first = true;
-  for (upb_msg_field_begin(&it, layout->msgdef);
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* field = upb_msg_iter_field(&it);
-    VALUE field_val = layout_get(layout, storage, field);
-
-    if (!first) {
-      str = rb_str_cat2(str, ", ");
-    } else {
-      first = false;
-    }
-    str = rb_str_cat2(str, upb_fielddef_name(field));
-    str = rb_str_cat2(str, ": ");
-
-    str = rb_str_append(str, rb_funcall(field_val, rb_intern("inspect"), 0));
-  }
-
-  return str;
-}
diff --git a/ruby/ext/google/protobuf_c/upb.c b/ruby/ext/google/protobuf_c/upb.c
deleted file mode 100644
index fb5009c..0000000
--- a/ruby/ext/google/protobuf_c/upb.c
+++ /dev/null
@@ -1,13817 +0,0 @@
-/* Amalgamated source file */
-#include "upb.h"
-/*
-* This is where we define macros used across upb.
-*
-* All of these macros are undef'd in port_undef.inc to avoid leaking them to
-* users.
-*
-* The correct usage is:
-*
-*   #include "upb/foobar.h"
-*   #include "upb/baz.h"
-*
-*   // MUST be last included header.
-*   #include "upb/port_def.inc"
-*
-*   // Code for this file.
-*   // <...>
-*
-*   // Can be omitted for .c files, required for .h.
-*   #include "upb/port_undef.inc"
-*
-* This file is private and must not be included by users!
-*/
-#include <stdint.h>
-
-#if UINTPTR_MAX == 0xffffffff
-#define UPB_SIZE(size32, size64) size32
-#else
-#define UPB_SIZE(size32, size64) size64
-#endif
-
-/* If we always read/write as a consistent type to each address, this shouldn't
- * violate aliasing.
- */
-#define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs)))
-
-#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \
-  *UPB_PTR_AT(msg, case_offset, int) == case_val                              \
-      ? *UPB_PTR_AT(msg, offset, fieldtype)                                   \
-      : default
-
-#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \
-  *UPB_PTR_AT(msg, case_offset, int) = case_val;                             \
-  *UPB_PTR_AT(msg, offset, fieldtype) = value;
-
-#define UPB_MAPTYPE_STRING 0
-
-/* UPB_INLINE: inline if possible, emit standalone code if required. */
-#ifdef __cplusplus
-#define UPB_INLINE inline
-#elif defined (__GNUC__) || defined(__clang__)
-#define UPB_INLINE static __inline__
-#else
-#define UPB_INLINE static
-#endif
-
-/* Hints to the compiler about likely/unlikely branches. */
-#if defined (__GNUC__) || defined(__clang__)
-#define UPB_LIKELY(x) __builtin_expect((x),1)
-#define UPB_UNLIKELY(x) __builtin_expect((x),0)
-#else
-#define UPB_LIKELY(x) (x)
-#define UPB_UNLIKELY(x) (x)
-#endif
-
-/* Define UPB_BIG_ENDIAN manually if you're on big endian and your compiler
- * doesn't provide these preprocessor symbols. */
-#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
-#define UPB_BIG_ENDIAN
-#endif
-
-/* Macros for function attributes on compilers that support them. */
-#ifdef __GNUC__
-#define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
-#define UPB_NOINLINE __attribute__((noinline))
-#define UPB_NORETURN __attribute__((__noreturn__))
-#else  /* !defined(__GNUC__) */
-#define UPB_FORCEINLINE
-#define UPB_NOINLINE
-#define UPB_NORETURN
-#endif
-
-#if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L
-/* C99/C++11 versions. */
-#include <stdio.h>
-#define _upb_snprintf snprintf
-#define _upb_vsnprintf vsnprintf
-#define _upb_va_copy(a, b) va_copy(a, b)
-#elif defined(_MSC_VER)
-/* Microsoft C/C++ versions. */
-#include <stdarg.h>
-#include <stdio.h>
-#if _MSC_VER < 1900
-int msvc_snprintf(char* s, size_t n, const char* format, ...);
-int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg);
-#define UPB_MSVC_VSNPRINTF
-#define _upb_snprintf msvc_snprintf
-#define _upb_vsnprintf msvc_vsnprintf
-#else
-#define _upb_snprintf snprintf
-#define _upb_vsnprintf vsnprintf
-#endif
-#define _upb_va_copy(a, b) va_copy(a, b)
-#elif defined __GNUC__
-/* A few hacky workarounds for functions not in C89.
- * For internal use only!
- * TODO(haberman): fix these by including our own implementations, or finding
- * another workaround.
- */
-#define _upb_snprintf __builtin_snprintf
-#define _upb_vsnprintf __builtin_vsnprintf
-#define _upb_va_copy(a, b) __va_copy(a, b)
-#else
-#error Need implementations of [v]snprintf and va_copy
-#endif
-
-#ifdef __cplusplus
-#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || \
-    (defined(_MSC_VER) && _MSC_VER >= 1900)
-/* C++11 is present */
-#else
-#error upb requires C++11 for C++ support
-#endif
-#endif
-
-#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
-#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
-
-#define UPB_UNUSED(var) (void)var
-
-/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true.
- */
-#ifdef NDEBUG
-#ifdef __GNUC__
-#define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable()
-#else
-#define UPB_ASSUME(expr) do {} if (false && (expr))
-#endif
-#else
-#define UPB_ASSUME(expr) assert(expr)
-#endif
-
-/* UPB_ASSERT(): in release mode, we use the expression without letting it be
- * evaluated.  This prevents "unused variable" warnings. */
-#ifdef NDEBUG
-#define UPB_ASSERT(expr) do {} while (false && (expr))
-#else
-#define UPB_ASSERT(expr) assert(expr)
-#endif
-
-/* UPB_ASSERT_DEBUGVAR(): assert that uses functions or variables that only
- * exist in debug mode.  This turns into regular assert. */
-#define UPB_ASSERT_DEBUGVAR(expr) assert(expr)
-
-#if defined(__GNUC__) || defined(__clang__)
-#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0)
-#else
-#define UPB_UNREACHABLE() do { assert(0); } while(0)
-#endif
-
-/* UPB_INFINITY representing floating-point positive infinity. */
-#include <math.h>
-#ifdef INFINITY
-#define UPB_INFINITY INFINITY
-#else
-#define UPB_INFINITY (1.0 / 0.0)
-#endif
-
-#include <setjmp.h>
-#include <string.h>
-
-
-
-/* Maps descriptor type -> upb field type.  */
-static const uint8_t desctype_to_fieldtype[] = {
-    -1,               /* invalid descriptor type */
-    UPB_TYPE_DOUBLE,  /* DOUBLE */
-    UPB_TYPE_FLOAT,   /* FLOAT */
-    UPB_TYPE_INT64,   /* INT64 */
-    UPB_TYPE_UINT64,  /* UINT64 */
-    UPB_TYPE_INT32,   /* INT32 */
-    UPB_TYPE_UINT64,  /* FIXED64 */
-    UPB_TYPE_UINT32,  /* FIXED32 */
-    UPB_TYPE_BOOL,    /* BOOL */
-    UPB_TYPE_STRING,  /* STRING */
-    UPB_TYPE_MESSAGE, /* GROUP */
-    UPB_TYPE_MESSAGE, /* MESSAGE */
-    UPB_TYPE_BYTES,   /* BYTES */
-    UPB_TYPE_UINT32,  /* UINT32 */
-    UPB_TYPE_ENUM,    /* ENUM */
-    UPB_TYPE_INT32,   /* SFIXED32 */
-    UPB_TYPE_INT64,   /* SFIXED64 */
-    UPB_TYPE_INT32,   /* SINT32 */
-    UPB_TYPE_INT64,   /* SINT64 */
-};
-
-/* Maps descriptor type -> upb map size.  */
-static const uint8_t desctype_to_mapsize[] = {
-    -1,                 /* invalid descriptor type */
-    8,                  /* DOUBLE */
-    4,                  /* FLOAT */
-    8,                  /* INT64 */
-    8,                  /* UINT64 */
-    4,                  /* INT32 */
-    8,                  /* FIXED64 */
-    4,                  /* FIXED32 */
-    1,                  /* BOOL */
-    UPB_MAPTYPE_STRING, /* STRING */
-    sizeof(void *),     /* GROUP */
-    sizeof(void *),     /* MESSAGE */
-    UPB_MAPTYPE_STRING, /* BYTES */
-    4,                  /* UINT32 */
-    4,                  /* ENUM */
-    4,                  /* SFIXED32 */
-    8,                  /* SFIXED64 */
-    4,                  /* SINT32 */
-    8,                  /* SINT64 */
-};
-
-static const unsigned fixed32_ok = (1 << UPB_DTYPE_FLOAT) |
-                                   (1 << UPB_DTYPE_FIXED32) |
-                                   (1 << UPB_DTYPE_SFIXED32);
-
-static const unsigned fixed64_ok = (1 << UPB_DTYPE_DOUBLE) |
-                                   (1 << UPB_DTYPE_FIXED64) |
-                                   (1 << UPB_DTYPE_SFIXED64);
-
-/* Op: an action to be performed for a wire-type/field-type combination. */
-#define OP_SCALAR_LG2(n) (n)
-#define OP_FIXPCK_LG2(n) (n + 4)
-#define OP_VARPCK_LG2(n) (n + 8)
-#define OP_STRING 4
-#define OP_SUBMSG 5
-
-static const int8_t varint_ops[19] = {
-    -1,               /* field not found */
-    -1,               /* DOUBLE */
-    -1,               /* FLOAT */
-    OP_SCALAR_LG2(3), /* INT64 */
-    OP_SCALAR_LG2(3), /* UINT64 */
-    OP_SCALAR_LG2(2), /* INT32 */
-    -1,               /* FIXED64 */
-    -1,               /* FIXED32 */
-    OP_SCALAR_LG2(0), /* BOOL */
-    -1,               /* STRING */
-    -1,               /* GROUP */
-    -1,               /* MESSAGE */
-    -1,               /* BYTES */
-    OP_SCALAR_LG2(2), /* UINT32 */
-    OP_SCALAR_LG2(2), /* ENUM */
-    -1,               /* SFIXED32 */
-    -1,               /* SFIXED64 */
-    OP_SCALAR_LG2(2), /* SINT32 */
-    OP_SCALAR_LG2(3), /* SINT64 */
-};
-
-static const int8_t delim_ops[37] = {
-    /* For non-repeated field type. */
-    -1,        /* field not found */
-    -1,        /* DOUBLE */
-    -1,        /* FLOAT */
-    -1,        /* INT64 */
-    -1,        /* UINT64 */
-    -1,        /* INT32 */
-    -1,        /* FIXED64 */
-    -1,        /* FIXED32 */
-    -1,        /* BOOL */
-    OP_STRING, /* STRING */
-    -1,        /* GROUP */
-    OP_SUBMSG, /* MESSAGE */
-    OP_STRING, /* BYTES */
-    -1,        /* UINT32 */
-    -1,        /* ENUM */
-    -1,        /* SFIXED32 */
-    -1,        /* SFIXED64 */
-    -1,        /* SINT32 */
-    -1,        /* SINT64 */
-    /* For repeated field type. */
-    OP_FIXPCK_LG2(3), /* REPEATED DOUBLE */
-    OP_FIXPCK_LG2(2), /* REPEATED FLOAT */
-    OP_VARPCK_LG2(3), /* REPEATED INT64 */
-    OP_VARPCK_LG2(3), /* REPEATED UINT64 */
-    OP_VARPCK_LG2(2), /* REPEATED INT32 */
-    OP_FIXPCK_LG2(3), /* REPEATED FIXED64 */
-    OP_FIXPCK_LG2(2), /* REPEATED FIXED32 */
-    OP_VARPCK_LG2(0), /* REPEATED BOOL */
-    OP_STRING,        /* REPEATED STRING */
-    OP_SUBMSG,        /* REPEATED GROUP */
-    OP_SUBMSG,        /* REPEATED MESSAGE */
-    OP_STRING,        /* REPEATED BYTES */
-    OP_VARPCK_LG2(2), /* REPEATED UINT32 */
-    OP_VARPCK_LG2(2), /* REPEATED ENUM */
-    OP_FIXPCK_LG2(2), /* REPEATED SFIXED32 */
-    OP_FIXPCK_LG2(3), /* REPEATED SFIXED64 */
-    OP_VARPCK_LG2(2), /* REPEATED SINT32 */
-    OP_VARPCK_LG2(3), /* REPEATED SINT64 */
-};
-
-/* Data pertaining to the parse. */
-typedef struct {
-  const char *limit;       /* End of delimited region or end of buffer. */
-  upb_arena *arena;
-  int depth;
-  uint32_t end_group; /* Set to field number of END_GROUP tag, if any. */
-  jmp_buf err;
-} upb_decstate;
-
-typedef union {
-  bool bool_val;
-  int32_t int32_val;
-  int64_t int64_val;
-  uint32_t uint32_val;
-  uint64_t uint64_val;
-  upb_strview str_val;
-} wireval;
-
-static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
-                              const upb_msglayout *layout);
-
-UPB_NORETURN static void decode_err(upb_decstate *d) { longjmp(d->err, 1); }
-
-static bool decode_reserve(upb_decstate *d, upb_array *arr, int elem) {
-  bool need_realloc = arr->size - arr->len < elem;
-  if (need_realloc && !_upb_array_realloc(arr, arr->len + elem, d->arena)) {
-    decode_err(d);
-  }
-  return need_realloc;
-}
-
-UPB_NOINLINE
-static const char *decode_longvarint64(upb_decstate *d, const char *ptr,
-                                       const char *limit, uint64_t *val) {
-  uint8_t byte;
-  int bitpos = 0;
-  uint64_t out = 0;
-
-  do {
-    if (bitpos >= 70 || ptr == limit) decode_err(d);
-    byte = *ptr;
-    out |= (uint64_t)(byte & 0x7F) << bitpos;
-    ptr++;
-    bitpos += 7;
-  } while (byte & 0x80);
-
-  *val = out;
-  return ptr;
-}
-
-UPB_FORCEINLINE
-static const char *decode_varint64(upb_decstate *d, const char *ptr,
-                                   const char *limit, uint64_t *val) {
-  if (UPB_LIKELY(ptr < limit && (*ptr & 0x80) == 0)) {
-    *val = (uint8_t)*ptr;
-    return ptr + 1;
-  } else {
-    return decode_longvarint64(d, ptr, limit, val);
-  }
-}
-
-static const char *decode_varint32(upb_decstate *d, const char *ptr,
-                                   const char *limit, uint32_t *val) {
-  uint64_t u64;
-  ptr = decode_varint64(d, ptr, limit, &u64);
-  if (u64 > UINT32_MAX) decode_err(d);
-  *val = (uint32_t)u64;
-  return ptr;
-}
-
-static void decode_munge(int type, wireval *val) {
-  switch (type) {
-    case UPB_DESCRIPTOR_TYPE_BOOL:
-      val->bool_val = val->uint64_val != 0;
-      break;
-    case UPB_DESCRIPTOR_TYPE_SINT32: {
-      uint32_t n = val->uint32_val;
-      val->int32_val = (n >> 1) ^ -(int32_t)(n & 1);
-      break;
-    }
-    case UPB_DESCRIPTOR_TYPE_SINT64: {
-      uint64_t n = val->uint64_val;
-      val->int64_val = (n >> 1) ^ -(int64_t)(n & 1);
-      break;
-    }
-  }
-}
-
-static const upb_msglayout_field *upb_find_field(const upb_msglayout *l,
-                                                 uint32_t field_number) {
-  static upb_msglayout_field none = {0};
-
-  /* Lots of optimization opportunities here. */
-  int i;
-  if (l == NULL) return &none;
-  for (i = 0; i < l->field_count; i++) {
-    if (l->fields[i].number == field_number) {
-      return &l->fields[i];
-    }
-  }
-
-  return &none; /* Unknown field. */
-}
-
-static upb_msg *decode_newsubmsg(upb_decstate *d, const upb_msglayout *layout,
-                                 const upb_msglayout_field *field) {
-  const upb_msglayout *subl = layout->submsgs[field->submsg_index];
-  return _upb_msg_new(subl, d->arena);
-}
-
-static void decode_tosubmsg(upb_decstate *d, upb_msg *submsg,
-                            const upb_msglayout *layout,
-                            const upb_msglayout_field *field, upb_strview val) {
-  const upb_msglayout *subl = layout->submsgs[field->submsg_index];
-  const char *saved_limit = d->limit;
-  if (--d->depth < 0) decode_err(d);
-  d->limit = val.data + val.size;
-  decode_msg(d, val.data, submsg, subl);
-  d->limit = saved_limit;
-  if (d->end_group != 0) decode_err(d);
-  d->depth++;
-}
-
-static const char *decode_group(upb_decstate *d, const char *ptr,
-                                upb_msg *submsg, const upb_msglayout *subl,
-                                uint32_t number) {
-  if (--d->depth < 0) decode_err(d);
-  ptr = decode_msg(d, ptr, submsg, subl);
-  if (d->end_group != number) decode_err(d);
-  d->end_group = 0;
-  d->depth++;
-  return ptr;
-}
-
-static const char *decode_togroup(upb_decstate *d, const char *ptr,
-                                  upb_msg *submsg, const upb_msglayout *layout,
-                                  const upb_msglayout_field *field) {
-  const upb_msglayout *subl = layout->submsgs[field->submsg_index];
-  return decode_group(d, ptr, submsg, subl, field->number);
-}
-
-static const char *decode_toarray(upb_decstate *d, const char *ptr,
-                                  upb_msg *msg, const upb_msglayout *layout,
-                                  const upb_msglayout_field *field, wireval val,
-                                  int op) {
-  upb_array **arrp = UPB_PTR_AT(msg, field->offset, void);
-  upb_array *arr = *arrp;
-  void *mem;
-
-  if (!arr) {
-    upb_fieldtype_t type = desctype_to_fieldtype[field->descriptortype];
-    arr = _upb_array_new(d->arena, type);
-    if (!arr) decode_err(d);
-    *arrp = arr;
-  }
-
-  decode_reserve(d, arr, 1);
-
-  switch (op) {
-    case OP_SCALAR_LG2(0):
-    case OP_SCALAR_LG2(2):
-    case OP_SCALAR_LG2(3):
-      /* Append scalar value. */
-      mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << op, void);
-      arr->len++;
-      memcpy(mem, &val, 1 << op);
-      return ptr;
-    case OP_STRING:
-      /* Append string. */
-      mem =
-          UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(upb_strview), void);
-      arr->len++;
-      memcpy(mem, &val, sizeof(upb_strview));
-      return ptr;
-    case OP_SUBMSG: {
-      /* Append submessage / group. */
-      upb_msg *submsg = decode_newsubmsg(d, layout, field);
-      *UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(void *), upb_msg *) =
-          submsg;
-      arr->len++;
-      if (UPB_UNLIKELY(field->descriptortype == UPB_DTYPE_GROUP)) {
-        ptr = decode_togroup(d, ptr, submsg, layout, field);
-      } else {
-        decode_tosubmsg(d, submsg, layout, field, val.str_val);
-      }
-      return ptr;
-    }
-    case OP_FIXPCK_LG2(2):
-    case OP_FIXPCK_LG2(3): {
-      /* Fixed packed. */
-      int lg2 = op - OP_FIXPCK_LG2(0);
-      int mask = (1 << lg2) - 1;
-      int count = val.str_val.size >> lg2;
-      if ((val.str_val.size & mask) != 0) {
-        decode_err(d); /* Length isn't a round multiple of elem size. */
-      }
-      decode_reserve(d, arr, count);
-      mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
-      arr->len += count;
-      memcpy(mem, val.str_val.data, count << op);
-      return ptr;
-    }
-    case OP_VARPCK_LG2(0):
-    case OP_VARPCK_LG2(2):
-    case OP_VARPCK_LG2(3): {
-      /* Varint packed. */
-      int lg2 = op - OP_VARPCK_LG2(0);
-      int scale = 1 << lg2;
-      const char *ptr = val.str_val.data;
-      const char *end = ptr + val.str_val.size;
-      char *out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
-      while (ptr < end) {
-        wireval elem;
-        ptr = decode_varint64(d, ptr, end, &elem.uint64_val);
-        decode_munge(field->descriptortype, &elem);
-        if (decode_reserve(d, arr, 1)) {
-          out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
-        }
-        arr->len++;
-        memcpy(out, &elem, scale);
-        out += scale;
-      }
-      if (ptr != end) decode_err(d);
-      return ptr;
-    }
-    default:
-      UPB_UNREACHABLE();
-  }
-}
-
-static void decode_tomap(upb_decstate *d, upb_msg *msg,
-                         const upb_msglayout *layout,
-                         const upb_msglayout_field *field, wireval val) {
-  upb_map **map_p = UPB_PTR_AT(msg, field->offset, upb_map *);
-  upb_map *map = *map_p;
-  upb_map_entry ent;
-  const upb_msglayout *entry = layout->submsgs[field->submsg_index];
-
-  if (!map) {
-    /* Lazily create map. */
-    const upb_msglayout *entry = layout->submsgs[field->submsg_index];
-    const upb_msglayout_field *key_field = &entry->fields[0];
-    const upb_msglayout_field *val_field = &entry->fields[1];
-    char key_size = desctype_to_mapsize[key_field->descriptortype];
-    char val_size = desctype_to_mapsize[val_field->descriptortype];
-    UPB_ASSERT(key_field->offset == 0);
-    UPB_ASSERT(val_field->offset == sizeof(upb_strview));
-    map = _upb_map_new(d->arena, key_size, val_size);
-    *map_p = map;
-  }
-
-  /* Parse map entry. */
-  memset(&ent, 0, sizeof(ent));
-
-  if (entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE ||
-      entry->fields[1].descriptortype == UPB_DESCRIPTOR_TYPE_GROUP) {
-    /* Create proactively to handle the case where it doesn't appear. */
-    ent.v.val.val = (uint64_t)_upb_msg_new(entry->submsgs[0], d->arena);
-  }
-
-  decode_tosubmsg(d, &ent.k, layout, field, val.str_val);
-
-  /* Insert into map. */
-  _upb_map_set(map, &ent.k, map->key_size, &ent.v, map->val_size, d->arena);
-}
-
-static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg,
-                                const upb_msglayout *layout,
-                                const upb_msglayout_field *field, wireval val,
-                                int op) {
-  void *mem = UPB_PTR_AT(msg, field->offset, void);
-  int type = field->descriptortype;
-
-  /* Set presence if necessary. */
-  if (field->presence < 0) {
-    /* Oneof case */
-    *UPB_PTR_AT(msg, -field->presence, int32_t) = field->number;
-  } else if (field->presence > 0) {
-    /* Hasbit */
-    uint32_t hasbit = field->presence;
-    *UPB_PTR_AT(msg, hasbit / 8, uint8_t) |= (1 << (hasbit % 8));
-  }
-
-  /* Store into message. */
-  switch (op) {
-    case OP_SUBMSG: {
-      upb_msg **submsgp = mem;
-      upb_msg *submsg = *submsgp;
-      if (!submsg) {
-        submsg = decode_newsubmsg(d, layout, field);
-        *submsgp = submsg;
-      }
-      if (UPB_UNLIKELY(type == UPB_DTYPE_GROUP)) {
-        ptr = decode_togroup(d, ptr, submsg, layout, field);
-      } else {
-        decode_tosubmsg(d, submsg, layout, field, val.str_val);
-      }
-      break;
-    }
-    case OP_STRING:
-      memcpy(mem, &val, sizeof(upb_strview));
-      break;
-    case OP_SCALAR_LG2(3):
-      memcpy(mem, &val, 8);
-      break;
-    case OP_SCALAR_LG2(2):
-      memcpy(mem, &val, 4);
-      break;
-    case OP_SCALAR_LG2(0):
-      memcpy(mem, &val, 1);
-      break;
-    default:
-      UPB_UNREACHABLE();
-  }
-
-  return ptr;
-}
-
-static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
-                              const upb_msglayout *layout) {
-  while (ptr < d->limit) {
-    uint32_t tag;
-    const upb_msglayout_field *field;
-    int field_number;
-    int wire_type;
-    const char *field_start = ptr;
-    wireval val;
-    int op;
-
-    ptr = decode_varint32(d, ptr, d->limit, &tag);
-    field_number = tag >> 3;
-    wire_type = tag & 7;
-
-    field = upb_find_field(layout, field_number);
-
-    switch (wire_type) {
-      case UPB_WIRE_TYPE_VARINT:
-        ptr = decode_varint64(d, ptr, d->limit, &val.uint64_val);
-        op = varint_ops[field->descriptortype];
-        decode_munge(field->descriptortype, &val);
-        break;
-      case UPB_WIRE_TYPE_32BIT:
-        if (d->limit - ptr < 4) decode_err(d);
-        memcpy(&val, ptr, 4);
-        ptr += 4;
-        op = OP_SCALAR_LG2(2);
-        if (((1 << field->descriptortype) & fixed32_ok) == 0) goto unknown;
-        break;
-      case UPB_WIRE_TYPE_64BIT:
-        if (d->limit - ptr < 8) decode_err(d);
-        memcpy(&val, ptr, 8);
-        ptr += 8;
-        op = OP_SCALAR_LG2(3);
-        if (((1 << field->descriptortype) & fixed64_ok) == 0) goto unknown;
-        break;
-      case UPB_WIRE_TYPE_DELIMITED: {
-        uint32_t size;
-        int ndx = field->descriptortype;
-        if (_upb_isrepeated(field)) ndx += 18;
-        ptr = decode_varint32(d, ptr, d->limit, &size);
-        if (size >= INT32_MAX || (size_t)(d->limit - ptr) < size) {
-          decode_err(d); /* Length overflow. */
-        }
-        val.str_val.data = ptr;
-        val.str_val.size = size;
-        ptr += size;
-        op = delim_ops[ndx];
-        break;
-      }
-      case UPB_WIRE_TYPE_START_GROUP:
-        val.int32_val = field_number;
-        op = OP_SUBMSG;
-        if (field->descriptortype != UPB_DTYPE_GROUP) goto unknown;
-        break;
-      case UPB_WIRE_TYPE_END_GROUP:
-        d->end_group = field_number;
-        return ptr;
-      default:
-        decode_err(d);
-    }
-
-    if (op >= 0) {
-      /* Parse, using op for dispatch. */
-      switch (field->label) {
-        case UPB_LABEL_REPEATED:
-        case _UPB_LABEL_PACKED:
-          ptr = decode_toarray(d, ptr, msg, layout, field, val, op);
-          break;
-        case _UPB_LABEL_MAP:
-          decode_tomap(d, msg, layout, field, val);
-          break;
-        default:
-          ptr = decode_tomsg(d, ptr, msg, layout, field, val, op);
-          break;
-      }
-    } else {
-    unknown:
-      /* Skip unknown field. */
-      if (field_number == 0) decode_err(d);
-      if (wire_type == UPB_WIRE_TYPE_START_GROUP) {
-        ptr = decode_group(d, ptr, NULL, NULL, field_number);
-      }
-      if (msg) {
-        if (!_upb_msg_addunknown(msg, field_start, ptr - field_start,
-                                 d->arena)) {
-          decode_err(d);
-        }
-      }
-    }
-  }
-
-  if (ptr != d->limit) decode_err(d);
-  return ptr;
-}
-
-bool upb_decode(const char *buf, size_t size, void *msg, const upb_msglayout *l,
-                upb_arena *arena) {
-  upb_decstate state;
-  state.limit = buf + size;
-  state.arena = arena;
-  state.depth = 64;
-  state.end_group = 0;
-
-  if (setjmp(state.err)) return false;
-
-  if (size == 0) return true;
-  decode_msg(&state, buf, msg, l);
-
-  return state.end_group == 0;
-}
-
-#undef OP_SCALAR_LG2
-#undef OP_FIXPCK_LG2
-#undef OP_VARPCK_LG2
-#undef OP_STRING
-#undef OP_SUBMSG
-/* We encode backwards, to avoid pre-computing lengths (one-pass encode). */
-
-
-#include <string.h>
-
-
-
-#define UPB_PB_VARINT_MAX_LEN 10
-#define CHK(x) do { if (!(x)) { return false; } } while(0)
-
-static size_t upb_encode_varint(uint64_t val, char *buf) {
-  size_t i;
-  if (val < 128) { buf[0] = val; return 1; }
-  i = 0;
-  while (val) {
-    uint8_t byte = val & 0x7fU;
-    val >>= 7;
-    if (val) byte |= 0x80U;
-    buf[i++] = byte;
-  }
-  return i;
-}
-
-static uint32_t upb_zzencode_32(int32_t n) { return ((uint32_t)n << 1) ^ (n >> 31); }
-static uint64_t upb_zzencode_64(int64_t n) { return ((uint64_t)n << 1) ^ (n >> 63); }
-
-typedef struct {
-  upb_alloc *alloc;
-  char *buf, *ptr, *limit;
-} upb_encstate;
-
-static size_t upb_roundup_pow2(size_t bytes) {
-  size_t ret = 128;
-  while (ret < bytes) {
-    ret *= 2;
-  }
-  return ret;
-}
-
-static bool upb_encode_growbuffer(upb_encstate *e, size_t bytes) {
-  size_t old_size = e->limit - e->buf;
-  size_t new_size = upb_roundup_pow2(bytes + (e->limit - e->ptr));
-  char *new_buf = upb_realloc(e->alloc, e->buf, old_size, new_size);
-  CHK(new_buf);
-
-  /* We want previous data at the end, realloc() put it at the beginning. */
-  if (old_size > 0) {
-    memmove(new_buf + new_size - old_size, e->buf, old_size);
-  }
-
-  e->ptr = new_buf + new_size - (e->limit - e->ptr);
-  e->limit = new_buf + new_size;
-  e->buf = new_buf;
-  return true;
-}
-
-/* Call to ensure that at least "bytes" bytes are available for writing at
- * e->ptr.  Returns false if the bytes could not be allocated. */
-static bool upb_encode_reserve(upb_encstate *e, size_t bytes) {
-  CHK(UPB_LIKELY((size_t)(e->ptr - e->buf) >= bytes) ||
-      upb_encode_growbuffer(e, bytes));
-
-  e->ptr -= bytes;
-  return true;
-}
-
-/* Writes the given bytes to the buffer, handling reserve/advance. */
-static bool upb_put_bytes(upb_encstate *e, const void *data, size_t len) {
-  if (len == 0) return true;
-  CHK(upb_encode_reserve(e, len));
-  memcpy(e->ptr, data, len);
-  return true;
-}
-
-static bool upb_put_fixed64(upb_encstate *e, uint64_t val) {
-  /* TODO(haberman): byte-swap for big endian. */
-  return upb_put_bytes(e, &val, sizeof(uint64_t));
-}
-
-static bool upb_put_fixed32(upb_encstate *e, uint32_t val) {
-  /* TODO(haberman): byte-swap for big endian. */
-  return upb_put_bytes(e, &val, sizeof(uint32_t));
-}
-
-static bool upb_put_varint(upb_encstate *e, uint64_t val) {
-  size_t len;
-  char *start;
-  CHK(upb_encode_reserve(e, UPB_PB_VARINT_MAX_LEN));
-  len = upb_encode_varint(val, e->ptr);
-  start = e->ptr + UPB_PB_VARINT_MAX_LEN - len;
-  memmove(start, e->ptr, len);
-  e->ptr = start;
-  return true;
-}
-
-static bool upb_put_double(upb_encstate *e, double d) {
-  uint64_t u64;
-  UPB_ASSERT(sizeof(double) == sizeof(uint64_t));
-  memcpy(&u64, &d, sizeof(uint64_t));
-  return upb_put_fixed64(e, u64);
-}
-
-static bool upb_put_float(upb_encstate *e, float d) {
-  uint32_t u32;
-  UPB_ASSERT(sizeof(float) == sizeof(uint32_t));
-  memcpy(&u32, &d, sizeof(uint32_t));
-  return upb_put_fixed32(e, u32);
-}
-
-static uint32_t upb_readcase(const char *msg, const upb_msglayout_field *f) {
-  uint32_t ret;
-  memcpy(&ret, msg - f->presence, sizeof(ret));
-  return ret;
-}
-
-static bool upb_readhasbit(const char *msg, const upb_msglayout_field *f) {
-  uint32_t hasbit = f->presence;
-  UPB_ASSERT(f->presence > 0);
-  return (*UPB_PTR_AT(msg, hasbit / 8, uint8_t)) & (1 << (hasbit % 8));
-}
-
-static bool upb_put_tag(upb_encstate *e, int field_number, int wire_type) {
-  return upb_put_varint(e, (field_number << 3) | wire_type);
-}
-
-static bool upb_put_fixedarray(upb_encstate *e, const upb_array *arr,
-                               size_t elem_size, uint32_t tag) {
-  size_t bytes = arr->len * elem_size;
-  const char* data = _upb_array_constptr(arr);
-  const char* ptr = data + bytes - elem_size;
-  if (tag) {
-    while (true) {
-      CHK(upb_put_bytes(e, ptr, elem_size) && upb_put_varint(e, tag));
-      if (ptr == data) break;
-      ptr -= elem_size;
-    }
-    return true;
-  } else {
-    return upb_put_bytes(e, data, bytes) && upb_put_varint(e, bytes);
-  }
-}
-
-bool upb_encode_message(upb_encstate *e, const char *msg,
-                        const upb_msglayout *m, size_t *size);
-
-static bool upb_encode_scalarfield(upb_encstate *e, const void *_field_mem,
-                                   const upb_msglayout *m,
-                                   const upb_msglayout_field *f,
-                                   bool skip_zero_value) {
-  const char *field_mem = _field_mem;
-#define CASE(ctype, type, wire_type, encodeval) do { \
-  ctype val = *(ctype*)field_mem; \
-  if (skip_zero_value && val == 0) { \
-    return true; \
-  } \
-  return upb_put_ ## type(e, encodeval) && \
-      upb_put_tag(e, f->number, wire_type); \
-} while(0)
-
-  switch (f->descriptortype) {
-    case UPB_DESCRIPTOR_TYPE_DOUBLE:
-      CASE(double, double, UPB_WIRE_TYPE_64BIT, val);
-    case UPB_DESCRIPTOR_TYPE_FLOAT:
-      CASE(float, float, UPB_WIRE_TYPE_32BIT, val);
-    case UPB_DESCRIPTOR_TYPE_INT64:
-    case UPB_DESCRIPTOR_TYPE_UINT64:
-      CASE(uint64_t, varint, UPB_WIRE_TYPE_VARINT, val);
-    case UPB_DESCRIPTOR_TYPE_UINT32:
-      CASE(uint32_t, varint, UPB_WIRE_TYPE_VARINT, val);
-    case UPB_DESCRIPTOR_TYPE_INT32:
-    case UPB_DESCRIPTOR_TYPE_ENUM:
-      CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, (int64_t)val);
-    case UPB_DESCRIPTOR_TYPE_SFIXED64:
-    case UPB_DESCRIPTOR_TYPE_FIXED64:
-      CASE(uint64_t, fixed64, UPB_WIRE_TYPE_64BIT, val);
-    case UPB_DESCRIPTOR_TYPE_FIXED32:
-    case UPB_DESCRIPTOR_TYPE_SFIXED32:
-      CASE(uint32_t, fixed32, UPB_WIRE_TYPE_32BIT, val);
-    case UPB_DESCRIPTOR_TYPE_BOOL:
-      CASE(bool, varint, UPB_WIRE_TYPE_VARINT, val);
-    case UPB_DESCRIPTOR_TYPE_SINT32:
-      CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_32(val));
-    case UPB_DESCRIPTOR_TYPE_SINT64:
-      CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, upb_zzencode_64(val));
-    case UPB_DESCRIPTOR_TYPE_STRING:
-    case UPB_DESCRIPTOR_TYPE_BYTES: {
-      upb_strview view = *(upb_strview*)field_mem;
-      if (skip_zero_value && view.size == 0) {
-        return true;
-      }
-      return upb_put_bytes(e, view.data, view.size) &&
-          upb_put_varint(e, view.size) &&
-          upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
-    }
-    case UPB_DESCRIPTOR_TYPE_GROUP: {
-      size_t size;
-      void *submsg = *(void **)field_mem;
-      const upb_msglayout *subm = m->submsgs[f->submsg_index];
-      if (submsg == NULL) {
-        return true;
-      }
-      return upb_put_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP) &&
-          upb_encode_message(e, submsg, subm, &size) &&
-          upb_put_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP);
-    }
-    case UPB_DESCRIPTOR_TYPE_MESSAGE: {
-      size_t size;
-      void *submsg = *(void **)field_mem;
-      const upb_msglayout *subm = m->submsgs[f->submsg_index];
-      if (submsg == NULL) {
-        return true;
-      }
-      return upb_encode_message(e, submsg, subm, &size) &&
-          upb_put_varint(e, size) &&
-          upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
-    }
-  }
-#undef CASE
-  UPB_UNREACHABLE();
-}
-
-static bool upb_encode_array(upb_encstate *e, const char *field_mem,
-                             const upb_msglayout *m,
-                             const upb_msglayout_field *f) {
-  const upb_array *arr = *(const upb_array**)field_mem;
-  bool packed = f->label == _UPB_LABEL_PACKED;
-
-  if (arr == NULL || arr->len == 0) {
-    return true;
-  }
-
-#define VARINT_CASE(ctype, encode)                                       \
-  {                                                                      \
-    const ctype *start = _upb_array_constptr(arr);                       \
-    const ctype *ptr = start + arr->len;                                 \
-    size_t pre_len = e->limit - e->ptr;                                  \
-    uint32_t tag = packed ? 0 : (f->number << 3) | UPB_WIRE_TYPE_VARINT; \
-    do {                                                                 \
-      ptr--;                                                             \
-      CHK(upb_put_varint(e, encode));                                    \
-      if (tag) CHK(upb_put_varint(e, tag));                              \
-    } while (ptr != start);                                              \
-    if (!tag) CHK(upb_put_varint(e, e->limit - e->ptr - pre_len));       \
-  }                                                                      \
-  break;                                                                 \
-  do {                                                                   \
-    ;                                                                    \
-  } while (0)
-
-#define TAG(wire_type) (packed ? 0 : (f->number << 3 | wire_type))
-
-  switch (f->descriptortype) {
-    case UPB_DESCRIPTOR_TYPE_DOUBLE:
-      CHK(upb_put_fixedarray(e, arr, sizeof(double), TAG(UPB_WIRE_TYPE_64BIT)));
-      break;
-    case UPB_DESCRIPTOR_TYPE_FLOAT:
-      CHK(upb_put_fixedarray(e, arr, sizeof(float), TAG(UPB_WIRE_TYPE_32BIT)));
-      break;
-    case UPB_DESCRIPTOR_TYPE_SFIXED64:
-    case UPB_DESCRIPTOR_TYPE_FIXED64:
-      CHK(upb_put_fixedarray(e, arr, sizeof(uint64_t), TAG(UPB_WIRE_TYPE_64BIT)));
-      break;
-    case UPB_DESCRIPTOR_TYPE_FIXED32:
-    case UPB_DESCRIPTOR_TYPE_SFIXED32:
-      CHK(upb_put_fixedarray(e, arr, sizeof(uint32_t), TAG(UPB_WIRE_TYPE_32BIT)));
-      break;
-    case UPB_DESCRIPTOR_TYPE_INT64:
-    case UPB_DESCRIPTOR_TYPE_UINT64:
-      VARINT_CASE(uint64_t, *ptr);
-    case UPB_DESCRIPTOR_TYPE_UINT32:
-      VARINT_CASE(uint32_t, *ptr);
-    case UPB_DESCRIPTOR_TYPE_INT32:
-    case UPB_DESCRIPTOR_TYPE_ENUM:
-      VARINT_CASE(int32_t, (int64_t)*ptr);
-    case UPB_DESCRIPTOR_TYPE_BOOL:
-      VARINT_CASE(bool, *ptr);
-    case UPB_DESCRIPTOR_TYPE_SINT32:
-      VARINT_CASE(int32_t, upb_zzencode_32(*ptr));
-    case UPB_DESCRIPTOR_TYPE_SINT64:
-      VARINT_CASE(int64_t, upb_zzencode_64(*ptr));
-    case UPB_DESCRIPTOR_TYPE_STRING:
-    case UPB_DESCRIPTOR_TYPE_BYTES: {
-      const upb_strview *start = _upb_array_constptr(arr);
-      const upb_strview *ptr = start + arr->len;
-      do {
-        ptr--;
-        CHK(upb_put_bytes(e, ptr->data, ptr->size) &&
-            upb_put_varint(e, ptr->size) &&
-            upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED));
-      } while (ptr != start);
-      return true;
-    }
-    case UPB_DESCRIPTOR_TYPE_GROUP: {
-      const void *const*start = _upb_array_constptr(arr);
-      const void *const*ptr = start + arr->len;
-      const upb_msglayout *subm = m->submsgs[f->submsg_index];
-      do {
-        size_t size;
-        ptr--;
-        CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP) &&
-            upb_encode_message(e, *ptr, subm, &size) &&
-            upb_put_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP));
-      } while (ptr != start);
-      return true;
-    }
-    case UPB_DESCRIPTOR_TYPE_MESSAGE: {
-      const void *const*start = _upb_array_constptr(arr);
-      const void *const*ptr = start + arr->len;
-      const upb_msglayout *subm = m->submsgs[f->submsg_index];
-      do {
-        size_t size;
-        ptr--;
-        CHK(upb_encode_message(e, *ptr, subm, &size) &&
-            upb_put_varint(e, size) &&
-            upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED));
-      } while (ptr != start);
-      return true;
-    }
-  }
-#undef VARINT_CASE
-
-  if (packed) {
-    CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED));
-  }
-  return true;
-}
-
-static bool upb_encode_map(upb_encstate *e, const char *field_mem,
-                           const upb_msglayout *m,
-                           const upb_msglayout_field *f) {
-  const upb_map *map = *(const upb_map**)field_mem;
-  const upb_msglayout *entry = m->submsgs[f->submsg_index];
-  const upb_msglayout_field *key_field = &entry->fields[0];
-  const upb_msglayout_field *val_field = &entry->fields[1];
-  upb_strtable_iter i;
-  if (map == NULL) {
-    return true;
-  }
-
-  upb_strtable_begin(&i, &map->table);
-  for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
-    size_t pre_len = e->limit - e->ptr;
-    size_t size;
-    upb_strview key = upb_strtable_iter_key(&i);
-    const upb_value val = upb_strtable_iter_value(&i);
-    const void *keyp =
-        map->key_size == UPB_MAPTYPE_STRING ? (void *)&key : key.data;
-    const void *valp =
-        map->val_size == UPB_MAPTYPE_STRING ? upb_value_getptr(val) : &val;
-
-    CHK(upb_encode_scalarfield(e, valp, entry, val_field, false));
-    CHK(upb_encode_scalarfield(e, keyp, entry, key_field, false));
-    size = (e->limit - e->ptr) - pre_len;
-    CHK(upb_put_varint(e, size));
-    CHK(upb_put_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED));
-  }
-
-  return true;
-}
-
-
-bool upb_encode_message(upb_encstate *e, const char *msg,
-                        const upb_msglayout *m, size_t *size) {
-  int i;
-  size_t pre_len = e->limit - e->ptr;
-  const char *unknown;
-  size_t unknown_size;
-
-  unknown = upb_msg_getunknown(msg, &unknown_size);
-
-  if (unknown) {
-    upb_put_bytes(e, unknown, unknown_size);
-  }
-
-  for (i = m->field_count - 1; i >= 0; i--) {
-    const upb_msglayout_field *f = &m->fields[i];
-
-    if (_upb_isrepeated(f)) {
-      CHK(upb_encode_array(e, msg + f->offset, m, f));
-    } else if (f->label == _UPB_LABEL_MAP) {
-      CHK(upb_encode_map(e, msg + f->offset, m, f));
-    } else {
-      bool skip_empty = false;
-      if (f->presence == 0) {
-        /* Proto3 presence. */
-        skip_empty = true;
-      } else if (f->presence > 0) {
-        /* Proto2 presence: hasbit. */
-        if (!upb_readhasbit(msg, f)) {
-          continue;
-        }
-      } else {
-        /* Field is in a oneof. */
-        if (upb_readcase(msg, f) != f->number) {
-          continue;
-        }
-      }
-      CHK(upb_encode_scalarfield(e, msg + f->offset, m, f, skip_empty));
-    }
-  }
-
-  *size = (e->limit - e->ptr) - pre_len;
-  return true;
-}
-
-char *upb_encode(const void *msg, const upb_msglayout *m, upb_arena *arena,
-                 size_t *size) {
-  upb_encstate e;
-  e.alloc = upb_arena_alloc(arena);
-  e.buf = NULL;
-  e.limit = NULL;
-  e.ptr = NULL;
-
-  if (!upb_encode_message(&e, msg, m, size)) {
-    *size = 0;
-    return NULL;
-  }
-
-  *size = e.limit - e.ptr;
-
-  if (*size == 0) {
-    static char ch;
-    return &ch;
-  } else {
-    UPB_ASSERT(e.ptr);
-    return e.ptr;
-  }
-}
-
-#undef CHK
-
-
-
-
-/** upb_msg *******************************************************************/
-
-static const char _upb_fieldtype_to_sizelg2[12] = {
-  0,
-  0,  /* UPB_TYPE_BOOL */
-  2,  /* UPB_TYPE_FLOAT */
-  2,  /* UPB_TYPE_INT32 */
-  2,  /* UPB_TYPE_UINT32 */
-  2,  /* UPB_TYPE_ENUM */
-  UPB_SIZE(2, 3),  /* UPB_TYPE_MESSAGE */
-  3,  /* UPB_TYPE_DOUBLE */
-  3,  /* UPB_TYPE_INT64 */
-  3,  /* UPB_TYPE_UINT64 */
-  UPB_SIZE(3, 4),  /* UPB_TYPE_STRING */
-  UPB_SIZE(3, 4),  /* UPB_TYPE_BYTES */
-};
-
-static uintptr_t tag_arrptr(void* ptr, int elem_size_lg2) {
-  UPB_ASSERT(elem_size_lg2 <= 4);
-  return (uintptr_t)ptr | elem_size_lg2;
-}
-
-static int upb_msg_internalsize(const upb_msglayout *l) {
-  return sizeof(upb_msg_internal) - l->extendable * sizeof(void *);
-}
-
-static size_t upb_msg_sizeof(const upb_msglayout *l) {
-  return l->size + upb_msg_internalsize(l);
-}
-
-static upb_msg_internal *upb_msg_getinternal(upb_msg *msg) {
-  return UPB_PTR_AT(msg, -sizeof(upb_msg_internal), upb_msg_internal);
-}
-
-static const upb_msg_internal *upb_msg_getinternal_const(const upb_msg *msg) {
-  return UPB_PTR_AT(msg, -sizeof(upb_msg_internal), upb_msg_internal);
-}
-
-static upb_msg_internal_withext *upb_msg_getinternalwithext(
-    upb_msg *msg, const upb_msglayout *l) {
-  UPB_ASSERT(l->extendable);
-  return UPB_PTR_AT(msg, -sizeof(upb_msg_internal_withext),
-                    upb_msg_internal_withext);
-}
-
-upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a) {
-  void *mem = upb_arena_malloc(a, upb_msg_sizeof(l));
-  upb_msg_internal *in;
-  upb_msg *msg;
-
-  if (!mem) {
-    return NULL;
-  }
-
-  msg = UPB_PTR_AT(mem, upb_msg_internalsize(l), upb_msg);
-
-  /* Initialize normal members. */
-  memset(msg, 0, l->size);
-
-  /* Initialize internal members. */
-  in = upb_msg_getinternal(msg);
-  in->unknown = NULL;
-  in->unknown_len = 0;
-  in->unknown_size = 0;
-
-  if (l->extendable) {
-    upb_msg_getinternalwithext(msg, l)->extdict = NULL;
-  }
-
-  return msg;
-}
-
-bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
-                         upb_arena *arena) {
-  upb_msg_internal *in = upb_msg_getinternal(msg);
-  if (len > in->unknown_size - in->unknown_len) {
-    upb_alloc *alloc = upb_arena_alloc(arena);
-    size_t need = in->unknown_size + len;
-    size_t newsize = UPB_MAX(in->unknown_size * 2, need);
-    void *mem = upb_realloc(alloc, in->unknown, in->unknown_size, newsize);
-    if (!mem) return false;
-    in->unknown = mem;
-    in->unknown_size = newsize;
-  }
-  memcpy(in->unknown + in->unknown_len, data, len);
-  in->unknown_len += len;
-  return true;
-}
-
-const char *upb_msg_getunknown(const upb_msg *msg, size_t *len) {
-  const upb_msg_internal *in = upb_msg_getinternal_const(msg);
-  *len = in->unknown_len;
-  return in->unknown;
-}
-
-/** upb_array *****************************************************************/
-
-upb_array *_upb_array_new(upb_arena *a, upb_fieldtype_t type) {
-  upb_array *arr = upb_arena_malloc(a, sizeof(upb_array));
-
-  if (!arr) {
-    return NULL;
-  }
-
-  arr->data = tag_arrptr(NULL, _upb_fieldtype_to_sizelg2[type]);
-  arr->len = 0;
-  arr->size = 0;
-
-  return arr;
-}
-
-bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena) {
-  size_t new_size = UPB_MAX(arr->size, 4);
-  int elem_size_lg2 = arr->data & 7;
-  size_t old_bytes = arr->size << elem_size_lg2;
-  size_t new_bytes;
-  void* ptr = _upb_array_ptr(arr);
-
-  /* Log2 ceiling of size. */
-  while (new_size < min_size) new_size *= 2;
-
-  new_bytes = new_size << elem_size_lg2;
-  ptr = upb_arena_realloc(arena, ptr, old_bytes, new_bytes);
-
-  if (!ptr) {
-    return false;
-  }
-
-  arr->data = tag_arrptr(ptr, elem_size_lg2);
-  arr->size = new_size;
-  return true;
-}
-
-static upb_array *getorcreate_array(upb_array **arr_ptr, upb_fieldtype_t type,
-                                    upb_arena *arena) {
-  upb_array *arr = *arr_ptr;
-  if (!arr) {
-    arr = _upb_array_new(arena, type);
-    if (!arr) return NULL;
-    *arr_ptr = arr;
-  }
-  return arr;
-}
-
-static bool resize_array(upb_array *arr, size_t size, upb_arena *arena) {
-  if (size > arr->size && !_upb_array_realloc(arr, size, arena)) {
-    return false;
-  }
-
-  arr->len = size;
-  return true;
-}
-
-void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size,
-                                 upb_fieldtype_t type, upb_arena *arena) {
-  upb_array *arr = getorcreate_array(arr_ptr, type, arena);
-  return arr && resize_array(arr, size, arena) ? _upb_array_ptr(arr) : NULL;
-}
-
-bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value,
-                                upb_fieldtype_t type, upb_arena *arena) {
-  upb_array *arr = getorcreate_array(arr_ptr, type, arena);
-  size_t elem = arr->len;
-  int lg2 = _upb_fieldtype_to_sizelg2[type];
-  char *data;
-
-  if (!arr || !resize_array(arr, elem + 1, arena)) return false;
-
-  data = _upb_array_ptr(arr);
-  memcpy(data + (elem << lg2), value, 1 << lg2);
-  return true;
-}
-
-/** upb_map *******************************************************************/
-
-upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size) {
-  upb_map *map = upb_arena_malloc(a, sizeof(upb_map));
-
-  if (!map) {
-    return NULL;
-  }
-
-  upb_strtable_init2(&map->table, UPB_CTYPE_INT32, upb_arena_alloc(a));
-  map->key_size = key_size;
-  map->val_size = value_size;
-
-  return map;
-}
-/*
-** upb_table Implementation
-**
-** Implementation is heavily inspired by Lua's ltable.c.
-*/
-
-
-#include <string.h>
-
-
-#define UPB_MAXARRSIZE 16  /* 64k. */
-
-/* From Chromium. */
-#define ARRAY_SIZE(x) \
-    ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
-
-static const double MAX_LOAD = 0.85;
-
-/* The minimum utilization of the array part of a mixed hash/array table.  This
- * is a speed/memory-usage tradeoff (though it's not straightforward because of
- * cache effects).  The lower this is, the more memory we'll use. */
-static const double MIN_DENSITY = 0.1;
-
-bool is_pow2(uint64_t v) { return v == 0 || (v & (v - 1)) == 0; }
-
-int log2ceil(uint64_t v) {
-  int ret = 0;
-  bool pow2 = is_pow2(v);
-  while (v >>= 1) ret++;
-  ret = pow2 ? ret : ret + 1;  /* Ceiling. */
-  return UPB_MIN(UPB_MAXARRSIZE, ret);
-}
-
-char *upb_strdup(const char *s, upb_alloc *a) {
-  return upb_strdup2(s, strlen(s), a);
-}
-
-char *upb_strdup2(const char *s, size_t len, upb_alloc *a) {
-  size_t n;
-  char *p;
-
-  /* Prevent overflow errors. */
-  if (len == SIZE_MAX) return NULL;
-  /* Always null-terminate, even if binary data; but don't rely on the input to
-   * have a null-terminating byte since it may be a raw binary buffer. */
-  n = len + 1;
-  p = upb_malloc(a, n);
-  if (p) {
-    memcpy(p, s, len);
-    p[len] = 0;
-  }
-  return p;
-}
-
-/* A type to represent the lookup key of either a strtable or an inttable. */
-typedef union {
-  uintptr_t num;
-  struct {
-    const char *str;
-    size_t len;
-  } str;
-} lookupkey_t;
-
-static lookupkey_t strkey2(const char *str, size_t len) {
-  lookupkey_t k;
-  k.str.str = str;
-  k.str.len = len;
-  return k;
-}
-
-static lookupkey_t intkey(uintptr_t key) {
-  lookupkey_t k;
-  k.num = key;
-  return k;
-}
-
-typedef uint32_t hashfunc_t(upb_tabkey key);
-typedef bool eqlfunc_t(upb_tabkey k1, lookupkey_t k2);
-
-/* Base table (shared code) ***************************************************/
-
-/* For when we need to cast away const. */
-static upb_tabent *mutable_entries(upb_table *t) {
-  return (upb_tabent*)t->entries;
-}
-
-static bool isfull(upb_table *t) {
-  if (upb_table_size(t) == 0) {
-    return true;
-  } else {
-    return ((double)(t->count + 1) / upb_table_size(t)) > MAX_LOAD;
-  }
-}
-
-static bool init(upb_table *t, uint8_t size_lg2, upb_alloc *a) {
-  size_t bytes;
-
-  t->count = 0;
-  t->size_lg2 = size_lg2;
-  t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0;
-  bytes = upb_table_size(t) * sizeof(upb_tabent);
-  if (bytes > 0) {
-    t->entries = upb_malloc(a, bytes);
-    if (!t->entries) return false;
-    memset(mutable_entries(t), 0, bytes);
-  } else {
-    t->entries = NULL;
-  }
-  return true;
-}
-
-static void uninit(upb_table *t, upb_alloc *a) {
-  upb_free(a, mutable_entries(t));
-}
-
-static upb_tabent *emptyent(upb_table *t) {
-  upb_tabent *e = mutable_entries(t) + upb_table_size(t);
-  while (1) { if (upb_tabent_isempty(--e)) return e; UPB_ASSERT(e > t->entries); }
-}
-
-static upb_tabent *getentry_mutable(upb_table *t, uint32_t hash) {
-  return (upb_tabent*)upb_getentry(t, hash);
-}
-
-static const upb_tabent *findentry(const upb_table *t, lookupkey_t key,
-                                   uint32_t hash, eqlfunc_t *eql) {
-  const upb_tabent *e;
-
-  if (t->size_lg2 == 0) return NULL;
-  e = upb_getentry(t, hash);
-  if (upb_tabent_isempty(e)) return NULL;
-  while (1) {
-    if (eql(e->key, key)) return e;
-    if ((e = e->next) == NULL) return NULL;
-  }
-}
-
-static upb_tabent *findentry_mutable(upb_table *t, lookupkey_t key,
-                                     uint32_t hash, eqlfunc_t *eql) {
-  return (upb_tabent*)findentry(t, key, hash, eql);
-}
-
-static bool lookup(const upb_table *t, lookupkey_t key, upb_value *v,
-                   uint32_t hash, eqlfunc_t *eql) {
-  const upb_tabent *e = findentry(t, key, hash, eql);
-  if (e) {
-    if (v) {
-      _upb_value_setval(v, e->val.val);
-    }
-    return true;
-  } else {
-    return false;
-  }
-}
-
-/* The given key must not already exist in the table. */
-static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey,
-                   upb_value val, uint32_t hash,
-                   hashfunc_t *hashfunc, eqlfunc_t *eql) {
-  upb_tabent *mainpos_e;
-  upb_tabent *our_e;
-
-  UPB_ASSERT(findentry(t, key, hash, eql) == NULL);
-
-  t->count++;
-  mainpos_e = getentry_mutable(t, hash);
-  our_e = mainpos_e;
-
-  if (upb_tabent_isempty(mainpos_e)) {
-    /* Our main position is empty; use it. */
-    our_e->next = NULL;
-  } else {
-    /* Collision. */
-    upb_tabent *new_e = emptyent(t);
-    /* Head of collider's chain. */
-    upb_tabent *chain = getentry_mutable(t, hashfunc(mainpos_e->key));
-    if (chain == mainpos_e) {
-      /* Existing ent is in its main posisiton (it has the same hash as us, and
-       * is the head of our chain).  Insert to new ent and append to this chain. */
-      new_e->next = mainpos_e->next;
-      mainpos_e->next = new_e;
-      our_e = new_e;
-    } else {
-      /* Existing ent is not in its main position (it is a node in some other
-       * chain).  This implies that no existing ent in the table has our hash.
-       * Evict it (updating its chain) and use its ent for head of our chain. */
-      *new_e = *mainpos_e;  /* copies next. */
-      while (chain->next != mainpos_e) {
-        chain = (upb_tabent*)chain->next;
-        UPB_ASSERT(chain);
-      }
-      chain->next = new_e;
-      our_e = mainpos_e;
-      our_e->next = NULL;
-    }
-  }
-  our_e->key = tabkey;
-  our_e->val.val = val.val;
-  UPB_ASSERT(findentry(t, key, hash, eql) == our_e);
-}
-
-static bool rm(upb_table *t, lookupkey_t key, upb_value *val,
-               upb_tabkey *removed, uint32_t hash, eqlfunc_t *eql) {
-  upb_tabent *chain = getentry_mutable(t, hash);
-  if (upb_tabent_isempty(chain)) return false;
-  if (eql(chain->key, key)) {
-    /* Element to remove is at the head of its chain. */
-    t->count--;
-    if (val) _upb_value_setval(val, chain->val.val);
-    if (removed) *removed = chain->key;
-    if (chain->next) {
-      upb_tabent *move = (upb_tabent*)chain->next;
-      *chain = *move;
-      move->key = 0;  /* Make the slot empty. */
-    } else {
-      chain->key = 0;  /* Make the slot empty. */
-    }
-    return true;
-  } else {
-    /* Element to remove is either in a non-head position or not in the
-     * table. */
-    while (chain->next && !eql(chain->next->key, key)) {
-      chain = (upb_tabent*)chain->next;
-    }
-    if (chain->next) {
-      /* Found element to remove. */
-      upb_tabent *rm = (upb_tabent*)chain->next;
-      t->count--;
-      if (val) _upb_value_setval(val, chain->next->val.val);
-      if (removed) *removed = rm->key;
-      rm->key = 0;  /* Make the slot empty. */
-      chain->next = rm->next;
-      return true;
-    } else {
-      /* Element to remove is not in the table. */
-      return false;
-    }
-  }
-}
-
-static size_t next(const upb_table *t, size_t i) {
-  do {
-    if (++i >= upb_table_size(t))
-      return SIZE_MAX;
-  } while(upb_tabent_isempty(&t->entries[i]));
-
-  return i;
-}
-
-static size_t begin(const upb_table *t) {
-  return next(t, -1);
-}
-
-
-/* upb_strtable ***************************************************************/
-
-/* A simple "subclass" of upb_table that only adds a hash function for strings. */
-
-static upb_tabkey strcopy(lookupkey_t k2, upb_alloc *a) {
-  uint32_t len = (uint32_t) k2.str.len;
-  char *str = upb_malloc(a, k2.str.len + sizeof(uint32_t) + 1);
-  if (str == NULL) return 0;
-  memcpy(str, &len, sizeof(uint32_t));
-  memcpy(str + sizeof(uint32_t), k2.str.str, k2.str.len);
-  str[sizeof(uint32_t) + k2.str.len] = '\0';
-  return (uintptr_t)str;
-}
-
-static uint32_t strhash(upb_tabkey key) {
-  uint32_t len;
-  char *str = upb_tabstr(key, &len);
-  return upb_murmur_hash2(str, len, 0);
-}
-
-static bool streql(upb_tabkey k1, lookupkey_t k2) {
-  uint32_t len;
-  char *str = upb_tabstr(k1, &len);
-  return len == k2.str.len && memcmp(str, k2.str.str, len) == 0;
-}
-
-bool upb_strtable_init2(upb_strtable *t, upb_ctype_t ctype, upb_alloc *a) {
-  return init(&t->t, 2, a);
-}
-
-void upb_strtable_clear(upb_strtable *t) {
-  size_t bytes = upb_table_size(&t->t) * sizeof(upb_tabent);
-  t->t.count = 0;
-  memset((char*)t->t.entries, 0, bytes);
-}
-
-void upb_strtable_uninit2(upb_strtable *t, upb_alloc *a) {
-  size_t i;
-  for (i = 0; i < upb_table_size(&t->t); i++)
-    upb_free(a, (void*)t->t.entries[i].key);
-  uninit(&t->t, a);
-}
-
-bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a) {
-  upb_strtable new_table;
-  upb_strtable_iter i;
-
-  if (!init(&new_table.t, size_lg2, a))
-    return false;
-  upb_strtable_begin(&i, t);
-  for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) {
-    upb_strview key = upb_strtable_iter_key(&i);
-    upb_strtable_insert3(
-        &new_table, key.data, key.size,
-        upb_strtable_iter_value(&i), a);
-  }
-  upb_strtable_uninit2(t, a);
-  *t = new_table;
-  return true;
-}
-
-bool upb_strtable_insert3(upb_strtable *t, const char *k, size_t len,
-                          upb_value v, upb_alloc *a) {
-  lookupkey_t key;
-  upb_tabkey tabkey;
-  uint32_t hash;
-
-  if (isfull(&t->t)) {
-    /* Need to resize.  New table of double the size, add old elements to it. */
-    if (!upb_strtable_resize(t, t->t.size_lg2 + 1, a)) {
-      return false;
-    }
-  }
-
-  key = strkey2(k, len);
-  tabkey = strcopy(key, a);
-  if (tabkey == 0) return false;
-
-  hash = upb_murmur_hash2(key.str.str, key.str.len, 0);
-  insert(&t->t, key, tabkey, v, hash, &strhash, &streql);
-  return true;
-}
-
-bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
-                          upb_value *v) {
-  uint32_t hash = upb_murmur_hash2(key, len, 0);
-  return lookup(&t->t, strkey2(key, len), v, hash, &streql);
-}
-
-bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len,
-                         upb_value *val, upb_alloc *alloc) {
-  uint32_t hash = upb_murmur_hash2(key, len, 0);
-  upb_tabkey tabkey;
-  if (rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql)) {
-    if (alloc) {
-      /* Arena-based allocs don't need to free and won't pass this. */
-      upb_free(alloc, (void*)tabkey);
-    }
-    return true;
-  } else {
-    return false;
-  }
-}
-
-/* Iteration */
-
-void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t) {
-  i->t = t;
-  i->index = begin(&t->t);
-}
-
-void upb_strtable_next(upb_strtable_iter *i) {
-  i->index = next(&i->t->t, i->index);
-}
-
-bool upb_strtable_done(const upb_strtable_iter *i) {
-  if (!i->t) return true;
-  return i->index >= upb_table_size(&i->t->t) ||
-         upb_tabent_isempty(str_tabent(i));
-}
-
-upb_strview upb_strtable_iter_key(const upb_strtable_iter *i) {
-  upb_strview key;
-  uint32_t len;
-  UPB_ASSERT(!upb_strtable_done(i));
-  key.data = upb_tabstr(str_tabent(i)->key, &len);
-  key.size = len;
-  return key;
-}
-
-upb_value upb_strtable_iter_value(const upb_strtable_iter *i) {
-  UPB_ASSERT(!upb_strtable_done(i));
-  return _upb_value_val(str_tabent(i)->val.val);
-}
-
-void upb_strtable_iter_setdone(upb_strtable_iter *i) {
-  i->t = NULL;
-  i->index = SIZE_MAX;
-}
-
-bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
-                               const upb_strtable_iter *i2) {
-  if (upb_strtable_done(i1) && upb_strtable_done(i2))
-    return true;
-  return i1->t == i2->t && i1->index == i2->index;
-}
-
-
-/* upb_inttable ***************************************************************/
-
-/* For inttables we use a hybrid structure where small keys are kept in an
- * array and large keys are put in the hash table. */
-
-static uint32_t inthash(upb_tabkey key) { return upb_inthash(key); }
-
-static bool inteql(upb_tabkey k1, lookupkey_t k2) {
-  return k1 == k2.num;
-}
-
-static upb_tabval *mutable_array(upb_inttable *t) {
-  return (upb_tabval*)t->array;
-}
-
-static upb_tabval *inttable_val(upb_inttable *t, uintptr_t key) {
-  if (key < t->array_size) {
-    return upb_arrhas(t->array[key]) ? &(mutable_array(t)[key]) : NULL;
-  } else {
-    upb_tabent *e =
-        findentry_mutable(&t->t, intkey(key), upb_inthash(key), &inteql);
-    return e ? &e->val : NULL;
-  }
-}
-
-static const upb_tabval *inttable_val_const(const upb_inttable *t,
-                                            uintptr_t key) {
-  return inttable_val((upb_inttable*)t, key);
-}
-
-size_t upb_inttable_count(const upb_inttable *t) {
-  return t->t.count + t->array_count;
-}
-
-static void check(upb_inttable *t) {
-  UPB_UNUSED(t);
-#if defined(UPB_DEBUG_TABLE) && !defined(NDEBUG)
-  {
-    /* This check is very expensive (makes inserts/deletes O(N)). */
-    size_t count = 0;
-    upb_inttable_iter i;
-    upb_inttable_begin(&i, t);
-    for(; !upb_inttable_done(&i); upb_inttable_next(&i), count++) {
-      UPB_ASSERT(upb_inttable_lookup(t, upb_inttable_iter_key(&i), NULL));
-    }
-    UPB_ASSERT(count == upb_inttable_count(t));
-  }
-#endif
-}
-
-bool upb_inttable_sizedinit(upb_inttable *t, size_t asize, int hsize_lg2,
-                            upb_alloc *a) {
-  size_t array_bytes;
-
-  if (!init(&t->t, hsize_lg2, a)) return false;
-  /* Always make the array part at least 1 long, so that we know key 0
-   * won't be in the hash part, which simplifies things. */
-  t->array_size = UPB_MAX(1, asize);
-  t->array_count = 0;
-  array_bytes = t->array_size * sizeof(upb_value);
-  t->array = upb_malloc(a, array_bytes);
-  if (!t->array) {
-    uninit(&t->t, a);
-    return false;
-  }
-  memset(mutable_array(t), 0xff, array_bytes);
-  check(t);
-  return true;
-}
-
-bool upb_inttable_init2(upb_inttable *t, upb_ctype_t ctype, upb_alloc *a) {
-  return upb_inttable_sizedinit(t, 0, 4, a);
-}
-
-void upb_inttable_uninit2(upb_inttable *t, upb_alloc *a) {
-  uninit(&t->t, a);
-  upb_free(a, mutable_array(t));
-}
-
-bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val,
-                          upb_alloc *a) {
-  upb_tabval tabval;
-  tabval.val = val.val;
-  UPB_ASSERT(upb_arrhas(tabval));  /* This will reject (uint64_t)-1.  Fix this. */
-
-  if (key < t->array_size) {
-    UPB_ASSERT(!upb_arrhas(t->array[key]));
-    t->array_count++;
-    mutable_array(t)[key].val = val.val;
-  } else {
-    if (isfull(&t->t)) {
-      /* Need to resize the hash part, but we re-use the array part. */
-      size_t i;
-      upb_table new_table;
-
-      if (!init(&new_table, t->t.size_lg2 + 1, a)) {
-        return false;
-      }
-
-      for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) {
-        const upb_tabent *e = &t->t.entries[i];
-        uint32_t hash;
-        upb_value v;
-
-        _upb_value_setval(&v, e->val.val);
-        hash = upb_inthash(e->key);
-        insert(&new_table, intkey(e->key), e->key, v, hash, &inthash, &inteql);
-      }
-
-      UPB_ASSERT(t->t.count == new_table.count);
-
-      uninit(&t->t, a);
-      t->t = new_table;
-    }
-    insert(&t->t, intkey(key), key, val, upb_inthash(key), &inthash, &inteql);
-  }
-  check(t);
-  return true;
-}
-
-bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v) {
-  const upb_tabval *table_v = inttable_val_const(t, key);
-  if (!table_v) return false;
-  if (v) _upb_value_setval(v, table_v->val);
-  return true;
-}
-
-bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val) {
-  upb_tabval *table_v = inttable_val(t, key);
-  if (!table_v) return false;
-  table_v->val = val.val;
-  return true;
-}
-
-bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) {
-  bool success;
-  if (key < t->array_size) {
-    if (upb_arrhas(t->array[key])) {
-      upb_tabval empty = UPB_TABVALUE_EMPTY_INIT;
-      t->array_count--;
-      if (val) {
-        _upb_value_setval(val, t->array[key].val);
-      }
-      mutable_array(t)[key] = empty;
-      success = true;
-    } else {
-      success = false;
-    }
-  } else {
-    success = rm(&t->t, intkey(key), val, NULL, upb_inthash(key), &inteql);
-  }
-  check(t);
-  return success;
-}
-
-bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a) {
-  return upb_inttable_insert2(t, upb_inttable_count(t), val, a);
-}
-
-upb_value upb_inttable_pop(upb_inttable *t) {
-  upb_value val;
-  bool ok = upb_inttable_remove(t, upb_inttable_count(t) - 1, &val);
-  UPB_ASSERT(ok);
-  return val;
-}
-
-bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val,
-                             upb_alloc *a) {
-  return upb_inttable_insert2(t, (uintptr_t)key, val, a);
-}
-
-bool upb_inttable_lookupptr(const upb_inttable *t, const void *key,
-                            upb_value *v) {
-  return upb_inttable_lookup(t, (uintptr_t)key, v);
-}
-
-bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val) {
-  return upb_inttable_remove(t, (uintptr_t)key, val);
-}
-
-void upb_inttable_compact2(upb_inttable *t, upb_alloc *a) {
-  /* A power-of-two histogram of the table keys. */
-  size_t counts[UPB_MAXARRSIZE + 1] = {0};
-
-  /* The max key in each bucket. */
-  uintptr_t max[UPB_MAXARRSIZE + 1] = {0};
-
-  upb_inttable_iter i;
-  size_t arr_count;
-  int size_lg2;
-  upb_inttable new_t;
-
-  upb_inttable_begin(&i, t);
-  for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
-    uintptr_t key = upb_inttable_iter_key(&i);
-    int bucket = log2ceil(key);
-    max[bucket] = UPB_MAX(max[bucket], key);
-    counts[bucket]++;
-  }
-
-  /* Find the largest power of two that satisfies the MIN_DENSITY
-   * definition (while actually having some keys). */
-  arr_count = upb_inttable_count(t);
-
-  for (size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 0; size_lg2--) {
-    if (counts[size_lg2] == 0) {
-      /* We can halve again without losing any entries. */
-      continue;
-    } else if (arr_count >= (1 << size_lg2) * MIN_DENSITY) {
-      break;
-    }
-
-    arr_count -= counts[size_lg2];
-  }
-
-  UPB_ASSERT(arr_count <= upb_inttable_count(t));
-
-  {
-    /* Insert all elements into new, perfectly-sized table. */
-    size_t arr_size = max[size_lg2] + 1;  /* +1 so arr[max] will fit. */
-    size_t hash_count = upb_inttable_count(t) - arr_count;
-    size_t hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0;
-    int hashsize_lg2 = log2ceil(hash_size);
-
-    upb_inttable_sizedinit(&new_t, arr_size, hashsize_lg2, a);
-    upb_inttable_begin(&i, t);
-    for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
-      uintptr_t k = upb_inttable_iter_key(&i);
-      upb_inttable_insert2(&new_t, k, upb_inttable_iter_value(&i), a);
-    }
-    UPB_ASSERT(new_t.array_size == arr_size);
-    UPB_ASSERT(new_t.t.size_lg2 == hashsize_lg2);
-  }
-  upb_inttable_uninit2(t, a);
-  *t = new_t;
-}
-
-/* Iteration. */
-
-static const upb_tabent *int_tabent(const upb_inttable_iter *i) {
-  UPB_ASSERT(!i->array_part);
-  return &i->t->t.entries[i->index];
-}
-
-static upb_tabval int_arrent(const upb_inttable_iter *i) {
-  UPB_ASSERT(i->array_part);
-  return i->t->array[i->index];
-}
-
-void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t) {
-  i->t = t;
-  i->index = -1;
-  i->array_part = true;
-  upb_inttable_next(i);
-}
-
-void upb_inttable_next(upb_inttable_iter *iter) {
-  const upb_inttable *t = iter->t;
-  if (iter->array_part) {
-    while (++iter->index < t->array_size) {
-      if (upb_arrhas(int_arrent(iter))) {
-        return;
-      }
-    }
-    iter->array_part = false;
-    iter->index = begin(&t->t);
-  } else {
-    iter->index = next(&t->t, iter->index);
-  }
-}
-
-bool upb_inttable_done(const upb_inttable_iter *i) {
-  if (!i->t) return true;
-  if (i->array_part) {
-    return i->index >= i->t->array_size ||
-           !upb_arrhas(int_arrent(i));
-  } else {
-    return i->index >= upb_table_size(&i->t->t) ||
-           upb_tabent_isempty(int_tabent(i));
-  }
-}
-
-uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) {
-  UPB_ASSERT(!upb_inttable_done(i));
-  return i->array_part ? i->index : int_tabent(i)->key;
-}
-
-upb_value upb_inttable_iter_value(const upb_inttable_iter *i) {
-  UPB_ASSERT(!upb_inttable_done(i));
-  return _upb_value_val(
-      i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val);
-}
-
-void upb_inttable_iter_setdone(upb_inttable_iter *i) {
-  i->t = NULL;
-  i->index = SIZE_MAX;
-  i->array_part = false;
-}
-
-bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
-                                          const upb_inttable_iter *i2) {
-  if (upb_inttable_done(i1) && upb_inttable_done(i2))
-    return true;
-  return i1->t == i2->t && i1->index == i2->index &&
-         i1->array_part == i2->array_part;
-}
-
-#if defined(UPB_UNALIGNED_READS_OK) || defined(__s390x__)
-/* -----------------------------------------------------------------------------
- * MurmurHash2, by Austin Appleby (released as public domain).
- * Reformatted and C99-ified by Joshua Haberman.
- * Note - This code makes a few assumptions about how your machine behaves -
- *   1. We can read a 4-byte value from any address without crashing
- *   2. sizeof(int) == 4 (in upb this limitation is removed by using uint32_t
- * And it has a few limitations -
- *   1. It will not work incrementally.
- *   2. It will not produce the same results on little-endian and big-endian
- *      machines. */
-uint32_t upb_murmur_hash2(const void *key, size_t len, uint32_t seed) {
-  /* 'm' and 'r' are mixing constants generated offline.
-   * They're not really 'magic', they just happen to work well. */
-  const uint32_t m = 0x5bd1e995;
-  const int32_t r = 24;
-
-  /* Initialize the hash to a 'random' value */
-  uint32_t h = seed ^ len;
-
-  /* Mix 4 bytes at a time into the hash */
-  const uint8_t * data = (const uint8_t *)key;
-  while(len >= 4) {
-    uint32_t k;
-    memcpy(&k, data, sizeof(k));
-
-    k *= m;
-    k ^= k >> r;
-    k *= m;
-
-    h *= m;
-    h ^= k;
-
-    data += 4;
-    len -= 4;
-  }
-
-  /* Handle the last few bytes of the input array */
-  switch(len) {
-    case 3: h ^= data[2] << 16;
-    case 2: h ^= data[1] << 8;
-    case 1: h ^= data[0]; h *= m;
-  };
-
-  /* Do a few final mixes of the hash to ensure the last few
-   * bytes are well-incorporated. */
-  h ^= h >> 13;
-  h *= m;
-  h ^= h >> 15;
-
-  return h;
-}
-
-#else /* !UPB_UNALIGNED_READS_OK */
-
-/* -----------------------------------------------------------------------------
- * MurmurHashAligned2, by Austin Appleby
- * Same algorithm as MurmurHash2, but only does aligned reads - should be safer
- * on certain platforms.
- * Performance will be lower than MurmurHash2 */
-
-#define MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }
-
-uint32_t upb_murmur_hash2(const void * key, size_t len, uint32_t seed) {
-  const uint32_t m = 0x5bd1e995;
-  const int32_t r = 24;
-  const uint8_t * data = (const uint8_t *)key;
-  uint32_t h = (uint32_t)(seed ^ len);
-  uint8_t align = (uintptr_t)data & 3;
-
-  if(align && (len >= 4)) {
-    /* Pre-load the temp registers */
-    uint32_t t = 0, d = 0;
-    int32_t sl;
-    int32_t sr;
-
-    switch(align) {
-      case 1: t |= data[2] << 16;
-      case 2: t |= data[1] << 8;
-      case 3: t |= data[0];
-    }
-
-    t <<= (8 * align);
-
-    data += 4-align;
-    len -= 4-align;
-
-    sl = 8 * (4-align);
-    sr = 8 * align;
-
-    /* Mix */
-
-    while(len >= 4) {
-      uint32_t k;
-
-      d = *(uint32_t *)data;
-      t = (t >> sr) | (d << sl);
-
-      k = t;
-
-      MIX(h,k,m);
-
-      t = d;
-
-      data += 4;
-      len -= 4;
-    }
-
-    /* Handle leftover data in temp registers */
-
-    d = 0;
-
-    if(len >= align) {
-      uint32_t k;
-
-      switch(align) {
-        case 3: d |= data[2] << 16;
-        case 2: d |= data[1] << 8;
-        case 1: d |= data[0];
-      }
-
-      k = (t >> sr) | (d << sl);
-      MIX(h,k,m);
-
-      data += align;
-      len -= align;
-
-      /* ----------
-       * Handle tail bytes */
-
-      switch(len) {
-        case 3: h ^= data[2] << 16;
-        case 2: h ^= data[1] << 8;
-        case 1: h ^= data[0]; h *= m;
-      };
-    } else {
-      switch(len) {
-        case 3: d |= data[2] << 16;
-        case 2: d |= data[1] << 8;
-        case 1: d |= data[0];
-        case 0: h ^= (t >> sr) | (d << sl); h *= m;
-      }
-    }
-
-    h ^= h >> 13;
-    h *= m;
-    h ^= h >> 15;
-
-    return h;
-  } else {
-    while(len >= 4) {
-      uint32_t k = *(uint32_t *)data;
-
-      MIX(h,k,m);
-
-      data += 4;
-      len -= 4;
-    }
-
-    /* ----------
-     * Handle tail bytes */
-
-    switch(len) {
-      case 3: h ^= data[2] << 16;
-      case 2: h ^= data[1] << 8;
-      case 1: h ^= data[0]; h *= m;
-    };
-
-    h ^= h >> 13;
-    h *= m;
-    h ^= h >> 15;
-
-    return h;
-  }
-}
-#undef MIX
-
-#endif /* UPB_UNALIGNED_READS_OK */
-
-
-#include <errno.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-/* upb_status *****************************************************************/
-
-void upb_status_clear(upb_status *status) {
-  if (!status) return;
-  status->ok = true;
-  status->msg[0] = '\0';
-}
-
-bool upb_ok(const upb_status *status) { return status->ok; }
-
-const char *upb_status_errmsg(const upb_status *status) { return status->msg; }
-
-void upb_status_seterrmsg(upb_status *status, const char *msg) {
-  if (!status) return;
-  status->ok = false;
-  strncpy(status->msg, msg, UPB_STATUS_MAX_MESSAGE - 1);
-  status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0';
-}
-
-void upb_status_seterrf(upb_status *status, const char *fmt, ...) {
-  va_list args;
-  va_start(args, fmt);
-  upb_status_vseterrf(status, fmt, args);
-  va_end(args);
-}
-
-void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) {
-  if (!status) return;
-  status->ok = false;
-  _upb_vsnprintf(status->msg, sizeof(status->msg), fmt, args);
-  status->msg[UPB_STATUS_MAX_MESSAGE - 1] = '\0';
-}
-
-/* upb_alloc ******************************************************************/
-
-static void *upb_global_allocfunc(upb_alloc *alloc, void *ptr, size_t oldsize,
-                                  size_t size) {
-  UPB_UNUSED(alloc);
-  UPB_UNUSED(oldsize);
-  if (size == 0) {
-    free(ptr);
-    return NULL;
-  } else {
-    return realloc(ptr, size);
-  }
-}
-
-upb_alloc upb_alloc_global = {&upb_global_allocfunc};
-
-/* upb_arena ******************************************************************/
-
-/* Be conservative and choose 16 in case anyone is using SSE. */
-
-struct upb_arena {
-  _upb_arena_head head;
-  char *start;
-
-  /* Allocator to allocate arena blocks.  We are responsible for freeing these
-   * when we are destroyed. */
-  upb_alloc *block_alloc;
-
-  size_t bytes_allocated;
-  size_t next_block_size;
-  size_t max_block_size;
-
-  /* Linked list of blocks.  Points to an arena_block, defined in env.c */
-  void *block_head;
-
-  /* Cleanup entries.  Pointer to a cleanup_ent, defined in env.c */
-  void *cleanup_head;
-};
-
-typedef struct mem_block {
-  struct mem_block *next;
-  bool owned;
-  /* Data follows. */
-} mem_block;
-
-typedef struct cleanup_ent {
-  struct cleanup_ent *next;
-  upb_cleanup_func *cleanup;
-  void *ud;
-} cleanup_ent;
-
-static void upb_arena_addblock(upb_arena *a, void *ptr, size_t size,
-                               bool owned) {
-  mem_block *block = ptr;
-
-  if (a->block_head) {
-    a->bytes_allocated += a->head.ptr - a->start;
-  }
-
-  block->next = a->block_head;
-  block->owned = owned;
-
-  a->block_head = block;
-  a->start = (char*)block + _upb_arena_alignup(sizeof(mem_block));
-  a->head.ptr = a->start;
-  a->head.end = (char*)block + size;
-
-  /* TODO(haberman): ASAN poison. */
-}
-
-static mem_block *upb_arena_allocblock(upb_arena *a, size_t size) {
-  size_t block_size = UPB_MAX(size, a->next_block_size) + _upb_arena_alignup(sizeof(mem_block));
-  mem_block *block = upb_malloc(a->block_alloc, block_size);
-
-  if (!block) {
-    return NULL;
-  }
-
-  upb_arena_addblock(a, block, block_size, true);
-  a->next_block_size = UPB_MIN(block_size * 2, a->max_block_size);
-
-  return block;
-}
-
-void *_upb_arena_slowmalloc(upb_arena *a, size_t size) {
-  mem_block *block = upb_arena_allocblock(a, size);
-  if (!block) return NULL;  /* Out of memory. */
-  return upb_arena_malloc(a, size);
-}
-
-static void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize,
-                               size_t size) {
-  upb_arena *a = (upb_arena*)alloc;  /* upb_alloc is initial member. */
-  void *ret;
-
-  if (size == 0) {
-    return NULL;  /* We are an arena, don't need individual frees. */
-  }
-
-  ret = upb_arena_malloc(a, size);
-  if (!ret) return NULL;
-
-  /* TODO(haberman): special-case if this is a realloc of the last alloc? */
-
-  if (oldsize > 0) {
-    memcpy(ret, ptr, oldsize);  /* Preserve existing data. */
-  }
-
-  /* TODO(haberman): ASAN unpoison. */
-  return ret;
-}
-
-/* Public Arena API ***********************************************************/
-
-#define upb_alignof(type) offsetof (struct { char c; type member; }, member)
-
-upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc) {
-  const size_t first_block_overhead = sizeof(upb_arena) + sizeof(mem_block);
-  upb_arena *a;
-  bool owned = false;
-
-  /* Round block size down to alignof(*a) since we will allocate the arena
-   * itself at the end. */
-  n &= ~(upb_alignof(upb_arena) - 1);
-
-  if (n < first_block_overhead) {
-    /* We need to malloc the initial block. */
-    n = first_block_overhead + 256;
-    owned = true;
-    if (!alloc || !(mem = upb_malloc(alloc, n))) {
-      return NULL;
-    }
-  }
-
-  a = (void*)((char*)mem + n - sizeof(*a));
-  n -= sizeof(*a);
-
-  a->head.alloc.func = &upb_arena_doalloc;
-  a->head.ptr = NULL;
-  a->head.end = NULL;
-  a->start = NULL;
-  a->block_alloc = &upb_alloc_global;
-  a->bytes_allocated = 0;
-  a->next_block_size = 256;
-  a->max_block_size = 16384;
-  a->cleanup_head = NULL;
-  a->block_head = NULL;
-  a->block_alloc = alloc;
-
-  upb_arena_addblock(a, mem, n, owned);
-
-  return a;
-}
-
-#undef upb_alignof
-
-void upb_arena_free(upb_arena *a) {
-  cleanup_ent *ent = a->cleanup_head;
-  mem_block *block = a->block_head;
-
-  while (ent) {
-    ent->cleanup(ent->ud);
-    ent = ent->next;
-  }
-
-  /* Must do this after running cleanup functions, because this will delete
-   * the memory we store our cleanup entries in! */
-  while (block) {
-    /* Load first since we are deleting block. */
-    mem_block *next = block->next;
-
-    if (block->owned) {
-      upb_free(a->block_alloc, block);
-    }
-
-    block = next;
-  }
-}
-
-bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func) {
-  cleanup_ent *ent = upb_malloc(&a->head.alloc, sizeof(cleanup_ent));
-  if (!ent) {
-    return false;  /* Out of memory. */
-  }
-
-  ent->cleanup = func;
-  ent->ud = ud;
-  ent->next = a->cleanup_head;
-  a->cleanup_head = ent;
-
-  return true;
-}
-
-size_t upb_arena_bytesallocated(const upb_arena *a) {
-  return a->bytes_allocated + (a->head.ptr - a->start);
-}
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     google/protobuf/descriptor.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#include <stddef.h>
-
-
-static const upb_msglayout *const google_protobuf_FileDescriptorSet_submsgs[1] = {
-  &google_protobuf_FileDescriptorProto_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_FileDescriptorSet__fields[1] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_FileDescriptorSet_msginit = {
-  &google_protobuf_FileDescriptorSet_submsgs[0],
-  &google_protobuf_FileDescriptorSet__fields[0],
-  UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout *const google_protobuf_FileDescriptorProto_submsgs[6] = {
-  &google_protobuf_DescriptorProto_msginit,
-  &google_protobuf_EnumDescriptorProto_msginit,
-  &google_protobuf_FieldDescriptorProto_msginit,
-  &google_protobuf_FileOptions_msginit,
-  &google_protobuf_ServiceDescriptorProto_msginit,
-  &google_protobuf_SourceCodeInfo_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_FileDescriptorProto__fields[12] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
-  {2, UPB_SIZE(12, 24), 2, 0, 9, 1},
-  {3, UPB_SIZE(36, 72), 0, 0, 9, 3},
-  {4, UPB_SIZE(40, 80), 0, 0, 11, 3},
-  {5, UPB_SIZE(44, 88), 0, 1, 11, 3},
-  {6, UPB_SIZE(48, 96), 0, 4, 11, 3},
-  {7, UPB_SIZE(52, 104), 0, 2, 11, 3},
-  {8, UPB_SIZE(28, 56), 4, 3, 11, 1},
-  {9, UPB_SIZE(32, 64), 5, 5, 11, 1},
-  {10, UPB_SIZE(56, 112), 0, 0, 5, 3},
-  {11, UPB_SIZE(60, 120), 0, 0, 5, 3},
-  {12, UPB_SIZE(20, 40), 3, 0, 9, 1},
-};
-
-const upb_msglayout google_protobuf_FileDescriptorProto_msginit = {
-  &google_protobuf_FileDescriptorProto_submsgs[0],
-  &google_protobuf_FileDescriptorProto__fields[0],
-  UPB_SIZE(64, 128), 12, false,
-};
-
-static const upb_msglayout *const google_protobuf_DescriptorProto_submsgs[8] = {
-  &google_protobuf_DescriptorProto_msginit,
-  &google_protobuf_DescriptorProto_ExtensionRange_msginit,
-  &google_protobuf_DescriptorProto_ReservedRange_msginit,
-  &google_protobuf_EnumDescriptorProto_msginit,
-  &google_protobuf_FieldDescriptorProto_msginit,
-  &google_protobuf_MessageOptions_msginit,
-  &google_protobuf_OneofDescriptorProto_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_DescriptorProto__fields[10] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
-  {2, UPB_SIZE(16, 32), 0, 4, 11, 3},
-  {3, UPB_SIZE(20, 40), 0, 0, 11, 3},
-  {4, UPB_SIZE(24, 48), 0, 3, 11, 3},
-  {5, UPB_SIZE(28, 56), 0, 1, 11, 3},
-  {6, UPB_SIZE(32, 64), 0, 4, 11, 3},
-  {7, UPB_SIZE(12, 24), 2, 5, 11, 1},
-  {8, UPB_SIZE(36, 72), 0, 6, 11, 3},
-  {9, UPB_SIZE(40, 80), 0, 2, 11, 3},
-  {10, UPB_SIZE(44, 88), 0, 0, 9, 3},
-};
-
-const upb_msglayout google_protobuf_DescriptorProto_msginit = {
-  &google_protobuf_DescriptorProto_submsgs[0],
-  &google_protobuf_DescriptorProto__fields[0],
-  UPB_SIZE(48, 96), 10, false,
-};
-
-static const upb_msglayout *const google_protobuf_DescriptorProto_ExtensionRange_submsgs[1] = {
-  &google_protobuf_ExtensionRangeOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_DescriptorProto_ExtensionRange__fields[3] = {
-  {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
-  {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
-  {3, UPB_SIZE(12, 16), 3, 0, 11, 1},
-};
-
-const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit = {
-  &google_protobuf_DescriptorProto_ExtensionRange_submsgs[0],
-  &google_protobuf_DescriptorProto_ExtensionRange__fields[0],
-  UPB_SIZE(16, 24), 3, false,
-};
-
-static const upb_msglayout_field google_protobuf_DescriptorProto_ReservedRange__fields[2] = {
-  {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
-  {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
-};
-
-const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit = {
-  NULL,
-  &google_protobuf_DescriptorProto_ReservedRange__fields[0],
-  UPB_SIZE(12, 12), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_ExtensionRangeOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_ExtensionRangeOptions__fields[1] = {
-  {999, UPB_SIZE(0, 0), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit = {
-  &google_protobuf_ExtensionRangeOptions_submsgs[0],
-  &google_protobuf_ExtensionRangeOptions__fields[0],
-  UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout *const google_protobuf_FieldDescriptorProto_submsgs[1] = {
-  &google_protobuf_FieldOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_FieldDescriptorProto__fields[11] = {
-  {1, UPB_SIZE(36, 40), 6, 0, 9, 1},
-  {2, UPB_SIZE(44, 56), 7, 0, 9, 1},
-  {3, UPB_SIZE(24, 24), 3, 0, 5, 1},
-  {4, UPB_SIZE(8, 8), 1, 0, 14, 1},
-  {5, UPB_SIZE(16, 16), 2, 0, 14, 1},
-  {6, UPB_SIZE(52, 72), 8, 0, 9, 1},
-  {7, UPB_SIZE(60, 88), 9, 0, 9, 1},
-  {8, UPB_SIZE(76, 120), 11, 0, 11, 1},
-  {9, UPB_SIZE(28, 28), 4, 0, 5, 1},
-  {10, UPB_SIZE(68, 104), 10, 0, 9, 1},
-  {17, UPB_SIZE(32, 32), 5, 0, 8, 1},
-};
-
-const upb_msglayout google_protobuf_FieldDescriptorProto_msginit = {
-  &google_protobuf_FieldDescriptorProto_submsgs[0],
-  &google_protobuf_FieldDescriptorProto__fields[0],
-  UPB_SIZE(80, 128), 11, false,
-};
-
-static const upb_msglayout *const google_protobuf_OneofDescriptorProto_submsgs[1] = {
-  &google_protobuf_OneofOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_OneofDescriptorProto__fields[2] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
-  {2, UPB_SIZE(12, 24), 2, 0, 11, 1},
-};
-
-const upb_msglayout google_protobuf_OneofDescriptorProto_msginit = {
-  &google_protobuf_OneofDescriptorProto_submsgs[0],
-  &google_protobuf_OneofDescriptorProto__fields[0],
-  UPB_SIZE(16, 32), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_EnumDescriptorProto_submsgs[3] = {
-  &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit,
-  &google_protobuf_EnumOptions_msginit,
-  &google_protobuf_EnumValueDescriptorProto_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_EnumDescriptorProto__fields[5] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
-  {2, UPB_SIZE(16, 32), 0, 2, 11, 3},
-  {3, UPB_SIZE(12, 24), 2, 1, 11, 1},
-  {4, UPB_SIZE(20, 40), 0, 0, 11, 3},
-  {5, UPB_SIZE(24, 48), 0, 0, 9, 3},
-};
-
-const upb_msglayout google_protobuf_EnumDescriptorProto_msginit = {
-  &google_protobuf_EnumDescriptorProto_submsgs[0],
-  &google_protobuf_EnumDescriptorProto__fields[0],
-  UPB_SIZE(32, 64), 5, false,
-};
-
-static const upb_msglayout_field google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = {
-  {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
-  {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
-};
-
-const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit = {
-  NULL,
-  &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0],
-  UPB_SIZE(12, 12), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_EnumValueDescriptorProto_submsgs[1] = {
-  &google_protobuf_EnumValueOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_EnumValueDescriptorProto__fields[3] = {
-  {1, UPB_SIZE(8, 8), 2, 0, 9, 1},
-  {2, UPB_SIZE(4, 4), 1, 0, 5, 1},
-  {3, UPB_SIZE(16, 24), 3, 0, 11, 1},
-};
-
-const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit = {
-  &google_protobuf_EnumValueDescriptorProto_submsgs[0],
-  &google_protobuf_EnumValueDescriptorProto__fields[0],
-  UPB_SIZE(24, 32), 3, false,
-};
-
-static const upb_msglayout *const google_protobuf_ServiceDescriptorProto_submsgs[2] = {
-  &google_protobuf_MethodDescriptorProto_msginit,
-  &google_protobuf_ServiceOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_ServiceDescriptorProto__fields[3] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 9, 1},
-  {2, UPB_SIZE(16, 32), 0, 0, 11, 3},
-  {3, UPB_SIZE(12, 24), 2, 1, 11, 1},
-};
-
-const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit = {
-  &google_protobuf_ServiceDescriptorProto_submsgs[0],
-  &google_protobuf_ServiceDescriptorProto__fields[0],
-  UPB_SIZE(24, 48), 3, false,
-};
-
-static const upb_msglayout *const google_protobuf_MethodDescriptorProto_submsgs[1] = {
-  &google_protobuf_MethodOptions_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_MethodDescriptorProto__fields[6] = {
-  {1, UPB_SIZE(4, 8), 3, 0, 9, 1},
-  {2, UPB_SIZE(12, 24), 4, 0, 9, 1},
-  {3, UPB_SIZE(20, 40), 5, 0, 9, 1},
-  {4, UPB_SIZE(28, 56), 6, 0, 11, 1},
-  {5, UPB_SIZE(1, 1), 1, 0, 8, 1},
-  {6, UPB_SIZE(2, 2), 2, 0, 8, 1},
-};
-
-const upb_msglayout google_protobuf_MethodDescriptorProto_msginit = {
-  &google_protobuf_MethodDescriptorProto_submsgs[0],
-  &google_protobuf_MethodDescriptorProto__fields[0],
-  UPB_SIZE(32, 64), 6, false,
-};
-
-static const upb_msglayout *const google_protobuf_FileOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_FileOptions__fields[21] = {
-  {1, UPB_SIZE(28, 32), 11, 0, 9, 1},
-  {8, UPB_SIZE(36, 48), 12, 0, 9, 1},
-  {9, UPB_SIZE(8, 8), 1, 0, 14, 1},
-  {10, UPB_SIZE(16, 16), 2, 0, 8, 1},
-  {11, UPB_SIZE(44, 64), 13, 0, 9, 1},
-  {16, UPB_SIZE(17, 17), 3, 0, 8, 1},
-  {17, UPB_SIZE(18, 18), 4, 0, 8, 1},
-  {18, UPB_SIZE(19, 19), 5, 0, 8, 1},
-  {20, UPB_SIZE(20, 20), 6, 0, 8, 1},
-  {23, UPB_SIZE(21, 21), 7, 0, 8, 1},
-  {27, UPB_SIZE(22, 22), 8, 0, 8, 1},
-  {31, UPB_SIZE(23, 23), 9, 0, 8, 1},
-  {36, UPB_SIZE(52, 80), 14, 0, 9, 1},
-  {37, UPB_SIZE(60, 96), 15, 0, 9, 1},
-  {39, UPB_SIZE(68, 112), 16, 0, 9, 1},
-  {40, UPB_SIZE(76, 128), 17, 0, 9, 1},
-  {41, UPB_SIZE(84, 144), 18, 0, 9, 1},
-  {42, UPB_SIZE(24, 24), 10, 0, 8, 1},
-  {44, UPB_SIZE(92, 160), 19, 0, 9, 1},
-  {45, UPB_SIZE(100, 176), 20, 0, 9, 1},
-  {999, UPB_SIZE(108, 192), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_FileOptions_msginit = {
-  &google_protobuf_FileOptions_submsgs[0],
-  &google_protobuf_FileOptions__fields[0],
-  UPB_SIZE(112, 208), 21, false,
-};
-
-static const upb_msglayout *const google_protobuf_MessageOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_MessageOptions__fields[5] = {
-  {1, UPB_SIZE(1, 1), 1, 0, 8, 1},
-  {2, UPB_SIZE(2, 2), 2, 0, 8, 1},
-  {3, UPB_SIZE(3, 3), 3, 0, 8, 1},
-  {7, UPB_SIZE(4, 4), 4, 0, 8, 1},
-  {999, UPB_SIZE(8, 8), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_MessageOptions_msginit = {
-  &google_protobuf_MessageOptions_submsgs[0],
-  &google_protobuf_MessageOptions__fields[0],
-  UPB_SIZE(12, 16), 5, false,
-};
-
-static const upb_msglayout *const google_protobuf_FieldOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_FieldOptions__fields[7] = {
-  {1, UPB_SIZE(8, 8), 1, 0, 14, 1},
-  {2, UPB_SIZE(24, 24), 3, 0, 8, 1},
-  {3, UPB_SIZE(25, 25), 4, 0, 8, 1},
-  {5, UPB_SIZE(26, 26), 5, 0, 8, 1},
-  {6, UPB_SIZE(16, 16), 2, 0, 14, 1},
-  {10, UPB_SIZE(27, 27), 6, 0, 8, 1},
-  {999, UPB_SIZE(28, 32), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_FieldOptions_msginit = {
-  &google_protobuf_FieldOptions_submsgs[0],
-  &google_protobuf_FieldOptions__fields[0],
-  UPB_SIZE(32, 40), 7, false,
-};
-
-static const upb_msglayout *const google_protobuf_OneofOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_OneofOptions__fields[1] = {
-  {999, UPB_SIZE(0, 0), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_OneofOptions_msginit = {
-  &google_protobuf_OneofOptions_submsgs[0],
-  &google_protobuf_OneofOptions__fields[0],
-  UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout *const google_protobuf_EnumOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_EnumOptions__fields[3] = {
-  {2, UPB_SIZE(1, 1), 1, 0, 8, 1},
-  {3, UPB_SIZE(2, 2), 2, 0, 8, 1},
-  {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_EnumOptions_msginit = {
-  &google_protobuf_EnumOptions_submsgs[0],
-  &google_protobuf_EnumOptions__fields[0],
-  UPB_SIZE(8, 16), 3, false,
-};
-
-static const upb_msglayout *const google_protobuf_EnumValueOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_EnumValueOptions__fields[2] = {
-  {1, UPB_SIZE(1, 1), 1, 0, 8, 1},
-  {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_EnumValueOptions_msginit = {
-  &google_protobuf_EnumValueOptions_submsgs[0],
-  &google_protobuf_EnumValueOptions__fields[0],
-  UPB_SIZE(8, 16), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_ServiceOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_ServiceOptions__fields[2] = {
-  {33, UPB_SIZE(1, 1), 1, 0, 8, 1},
-  {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_ServiceOptions_msginit = {
-  &google_protobuf_ServiceOptions_submsgs[0],
-  &google_protobuf_ServiceOptions__fields[0],
-  UPB_SIZE(8, 16), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_MethodOptions_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_MethodOptions__fields[3] = {
-  {33, UPB_SIZE(16, 16), 2, 0, 8, 1},
-  {34, UPB_SIZE(8, 8), 1, 0, 14, 1},
-  {999, UPB_SIZE(20, 24), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_MethodOptions_msginit = {
-  &google_protobuf_MethodOptions_submsgs[0],
-  &google_protobuf_MethodOptions__fields[0],
-  UPB_SIZE(24, 32), 3, false,
-};
-
-static const upb_msglayout *const google_protobuf_UninterpretedOption_submsgs[1] = {
-  &google_protobuf_UninterpretedOption_NamePart_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_UninterpretedOption__fields[7] = {
-  {2, UPB_SIZE(56, 80), 0, 0, 11, 3},
-  {3, UPB_SIZE(32, 32), 4, 0, 9, 1},
-  {4, UPB_SIZE(8, 8), 1, 0, 4, 1},
-  {5, UPB_SIZE(16, 16), 2, 0, 3, 1},
-  {6, UPB_SIZE(24, 24), 3, 0, 1, 1},
-  {7, UPB_SIZE(40, 48), 5, 0, 12, 1},
-  {8, UPB_SIZE(48, 64), 6, 0, 9, 1},
-};
-
-const upb_msglayout google_protobuf_UninterpretedOption_msginit = {
-  &google_protobuf_UninterpretedOption_submsgs[0],
-  &google_protobuf_UninterpretedOption__fields[0],
-  UPB_SIZE(64, 96), 7, false,
-};
-
-static const upb_msglayout_field google_protobuf_UninterpretedOption_NamePart__fields[2] = {
-  {1, UPB_SIZE(4, 8), 2, 0, 9, 2},
-  {2, UPB_SIZE(1, 1), 1, 0, 8, 2},
-};
-
-const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit = {
-  NULL,
-  &google_protobuf_UninterpretedOption_NamePart__fields[0],
-  UPB_SIZE(16, 32), 2, false,
-};
-
-static const upb_msglayout *const google_protobuf_SourceCodeInfo_submsgs[1] = {
-  &google_protobuf_SourceCodeInfo_Location_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_SourceCodeInfo__fields[1] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_SourceCodeInfo_msginit = {
-  &google_protobuf_SourceCodeInfo_submsgs[0],
-  &google_protobuf_SourceCodeInfo__fields[0],
-  UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout_field google_protobuf_SourceCodeInfo_Location__fields[5] = {
-  {1, UPB_SIZE(20, 40), 0, 0, 5, _UPB_LABEL_PACKED},
-  {2, UPB_SIZE(24, 48), 0, 0, 5, _UPB_LABEL_PACKED},
-  {3, UPB_SIZE(4, 8), 1, 0, 9, 1},
-  {4, UPB_SIZE(12, 24), 2, 0, 9, 1},
-  {6, UPB_SIZE(28, 56), 0, 0, 9, 3},
-};
-
-const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit = {
-  NULL,
-  &google_protobuf_SourceCodeInfo_Location__fields[0],
-  UPB_SIZE(32, 64), 5, false,
-};
-
-static const upb_msglayout *const google_protobuf_GeneratedCodeInfo_submsgs[1] = {
-  &google_protobuf_GeneratedCodeInfo_Annotation_msginit,
-};
-
-static const upb_msglayout_field google_protobuf_GeneratedCodeInfo__fields[1] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
-};
-
-const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit = {
-  &google_protobuf_GeneratedCodeInfo_submsgs[0],
-  &google_protobuf_GeneratedCodeInfo__fields[0],
-  UPB_SIZE(4, 8), 1, false,
-};
-
-static const upb_msglayout_field google_protobuf_GeneratedCodeInfo_Annotation__fields[4] = {
-  {1, UPB_SIZE(20, 32), 0, 0, 5, _UPB_LABEL_PACKED},
-  {2, UPB_SIZE(12, 16), 3, 0, 9, 1},
-  {3, UPB_SIZE(4, 4), 1, 0, 5, 1},
-  {4, UPB_SIZE(8, 8), 2, 0, 5, 1},
-};
-
-const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit = {
-  NULL,
-  &google_protobuf_GeneratedCodeInfo_Annotation__fields[0],
-  UPB_SIZE(24, 48), 4, false,
-};
-
-
-
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-typedef struct {
-  size_t len;
-  char str[1];  /* Null-terminated string data follows. */
-} str_t;
-
-static str_t *newstr(upb_alloc *alloc, const char *data, size_t len) {
-  str_t *ret = upb_malloc(alloc, sizeof(*ret) + len);
-  if (!ret) return NULL;
-  ret->len = len;
-  memcpy(ret->str, data, len);
-  ret->str[len] = '\0';
-  return ret;
-}
-
-struct upb_fielddef {
-  const upb_filedef *file;
-  const upb_msgdef *msgdef;
-  const char *full_name;
-  const char *json_name;
-  union {
-    int64_t sint;
-    uint64_t uint;
-    double dbl;
-    float flt;
-    bool boolean;
-    str_t *str;
-  } defaultval;
-  const upb_oneofdef *oneof;
-  union {
-    const upb_msgdef *msgdef;
-    const upb_enumdef *enumdef;
-    const google_protobuf_FieldDescriptorProto *unresolved;
-  } sub;
-  uint32_t number_;
-  uint16_t index_;
-  uint16_t layout_index;
-  uint32_t selector_base;  /* Used to index into a upb::Handlers table. */
-  bool is_extension_;
-  bool lazy_;
-  bool packed_;
-  bool proto3_optional_;
-  upb_descriptortype_t type_;
-  upb_label_t label_;
-};
-
-struct upb_msgdef {
-  const upb_msglayout *layout;
-  const upb_filedef *file;
-  const char *full_name;
-  uint32_t selector_count;
-  uint32_t submsg_field_count;
-
-  /* Tables for looking up fields by number and name. */
-  upb_inttable itof;
-  upb_strtable ntof;
-
-  const upb_fielddef *fields;
-  const upb_oneofdef *oneofs;
-  int field_count;
-  int oneof_count;
-  int real_oneof_count;
-
-  /* Is this a map-entry message? */
-  bool map_entry;
-  upb_wellknowntype_t well_known_type;
-
-  /* TODO(haberman): proper extension ranges (there can be multiple). */
-};
-
-struct upb_enumdef {
-  const upb_filedef *file;
-  const char *full_name;
-  upb_strtable ntoi;
-  upb_inttable iton;
-  int32_t defaultval;
-};
-
-struct upb_oneofdef {
-  const upb_msgdef *parent;
-  const char *full_name;
-  uint32_t index;
-  upb_strtable ntof;
-  upb_inttable itof;
-};
-
-struct upb_filedef {
-  const char *name;
-  const char *package;
-  const char *phpprefix;
-  const char *phpnamespace;
-  upb_syntax_t syntax;
-
-  const upb_filedef **deps;
-  const upb_msgdef *msgs;
-  const upb_enumdef *enums;
-  const upb_fielddef *exts;
-
-  int dep_count;
-  int msg_count;
-  int enum_count;
-  int ext_count;
-};
-
-struct upb_symtab {
-  upb_arena *arena;
-  upb_strtable syms;  /* full_name -> packed def ptr */
-  upb_strtable files;  /* file_name -> upb_filedef* */
-};
-
-/* Inside a symtab we store tagged pointers to specific def types. */
-typedef enum {
-  UPB_DEFTYPE_FIELD = 0,
-
-  /* Only inside symtab table. */
-  UPB_DEFTYPE_MSG = 1,
-  UPB_DEFTYPE_ENUM = 2,
-
-  /* Only inside message table. */
-  UPB_DEFTYPE_ONEOF = 1,
-  UPB_DEFTYPE_FIELD_JSONNAME = 2
-} upb_deftype_t;
-
-static const void *unpack_def(upb_value v, upb_deftype_t type) {
-  uintptr_t num = (uintptr_t)upb_value_getconstptr(v);
-  return (num & 3) == type ? (const void*)(num & ~3) : NULL;
-}
-
-static upb_value pack_def(const void *ptr, upb_deftype_t type) {
-  uintptr_t num = (uintptr_t)ptr | type;
-  return upb_value_constptr((const void*)num);
-}
-
-/* isalpha() etc. from <ctype.h> are locale-dependent, which we don't want. */
-static bool upb_isbetween(char c, char low, char high) {
-  return c >= low && c <= high;
-}
-
-static bool upb_isletter(char c) {
-  return upb_isbetween(c, 'A', 'Z') || upb_isbetween(c, 'a', 'z') || c == '_';
-}
-
-static bool upb_isalphanum(char c) {
-  return upb_isletter(c) || upb_isbetween(c, '0', '9');
-}
-
-static bool upb_isident(upb_strview name, bool full, upb_status *s) {
-  const char *str = name.data;
-  size_t len = name.size;
-  bool start = true;
-  size_t i;
-  for (i = 0; i < len; i++) {
-    char c = str[i];
-    if (c == '.') {
-      if (start || !full) {
-        upb_status_seterrf(s, "invalid name: unexpected '.' (%s)", str);
-        return false;
-      }
-      start = true;
-    } else if (start) {
-      if (!upb_isletter(c)) {
-        upb_status_seterrf(
-            s, "invalid name: path components must start with a letter (%s)",
-            str);
-        return false;
-      }
-      start = false;
-    } else {
-      if (!upb_isalphanum(c)) {
-        upb_status_seterrf(s, "invalid name: non-alphanumeric character (%s)",
-                           str);
-        return false;
-      }
-    }
-  }
-  return !start;
-}
-
-static const char *shortdefname(const char *fullname) {
-  const char *p;
-
-  if (fullname == NULL) {
-    return NULL;
-  } else if ((p = strrchr(fullname, '.')) == NULL) {
-    /* No '.' in the name, return the full string. */
-    return fullname;
-  } else {
-    /* Return one past the last '.'. */
-    return p + 1;
-  }
-}
-
-/* All submessage fields are lower than all other fields.
- * Secondly, fields are increasing in order. */
-uint32_t field_rank(const upb_fielddef *f) {
-  uint32_t ret = upb_fielddef_number(f);
-  const uint32_t high_bit = 1 << 30;
-  UPB_ASSERT(ret < high_bit);
-  if (!upb_fielddef_issubmsg(f))
-    ret |= high_bit;
-  return ret;
-}
-
-int cmp_fields(const void *p1, const void *p2) {
-  const upb_fielddef *f1 = *(upb_fielddef*const*)p1;
-  const upb_fielddef *f2 = *(upb_fielddef*const*)p2;
-  return field_rank(f1) - field_rank(f2);
-}
-
-/* A few implementation details of handlers.  We put these here to avoid
- * a def -> handlers dependency. */
-
-#define UPB_STATIC_SELECTOR_COUNT 3  /* Warning: also in upb/handlers.h. */
-
-static uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) {
-  return upb_fielddef_isseq(f) ? 2 : 0;
-}
-
-static uint32_t upb_handlers_selectorcount(const upb_fielddef *f) {
-  uint32_t ret = 1;
-  if (upb_fielddef_isseq(f)) ret += 2;    /* STARTSEQ/ENDSEQ */
-  if (upb_fielddef_isstring(f)) ret += 2; /* [STRING]/STARTSTR/ENDSTR */
-  if (upb_fielddef_issubmsg(f)) {
-    /* ENDSUBMSG (STARTSUBMSG is at table beginning) */
-    ret += 0;
-    if (upb_fielddef_lazy(f)) {
-      /* STARTSTR/ENDSTR/STRING (for lazy) */
-      ret += 3;
-    }
-  }
-  return ret;
-}
-
-static void upb_status_setoom(upb_status *status) {
-  upb_status_seterrmsg(status, "out of memory");
-}
-
-static bool assign_msg_indices(upb_msgdef *m, upb_status *s) {
-  /* Sort fields.  upb internally relies on UPB_TYPE_MESSAGE fields having the
-   * lowest indexes, but we do not publicly guarantee this. */
-  upb_msg_field_iter j;
-  int i;
-  uint32_t selector;
-  int n = upb_msgdef_numfields(m);
-  upb_fielddef **fields;
-
-  if (n == 0) {
-    m->selector_count = UPB_STATIC_SELECTOR_COUNT;
-    m->submsg_field_count = 0;
-    return true;
-  }
-
-  fields = upb_gmalloc(n * sizeof(*fields));
-  if (!fields) {
-    upb_status_setoom(s);
-    return false;
-  }
-
-  m->submsg_field_count = 0;
-  for(i = 0, upb_msg_field_begin(&j, m);
-      !upb_msg_field_done(&j);
-      upb_msg_field_next(&j), i++) {
-    upb_fielddef *f = upb_msg_iter_field(&j);
-    UPB_ASSERT(f->msgdef == m);
-    if (upb_fielddef_issubmsg(f)) {
-      m->submsg_field_count++;
-    }
-    fields[i] = f;
-  }
-
-  qsort(fields, n, sizeof(*fields), cmp_fields);
-
-  selector = UPB_STATIC_SELECTOR_COUNT + m->submsg_field_count;
-  for (i = 0; i < n; i++) {
-    upb_fielddef *f = fields[i];
-    f->index_ = i;
-    f->selector_base = selector + upb_handlers_selectorbaseoffset(f);
-    selector += upb_handlers_selectorcount(f);
-  }
-  m->selector_count = selector;
-
-  upb_gfree(fields);
-  return true;
-}
-
-static bool check_oneofs(upb_msgdef *m, upb_status *s) {
-  int i;
-  int first_synthetic = -1;
-  upb_oneofdef *mutable_oneofs = (upb_oneofdef*)m->oneofs;
-
-  for (i = 0; i < m->oneof_count; i++) {
-    mutable_oneofs[i].index = i;
-
-    if (upb_oneofdef_issynthetic(&mutable_oneofs[i])) {
-      if (first_synthetic == -1) {
-        first_synthetic = i;
-      }
-    } else {
-      if (first_synthetic != -1) {
-        upb_status_seterrf(
-            s, "Synthetic oneofs must be after all other oneofs: %s",
-            upb_oneofdef_name(&mutable_oneofs[i]));
-        return false;
-      }
-    }
-  }
-
-  if (first_synthetic == -1) {
-    m->real_oneof_count = m->oneof_count;
-  } else {
-    m->real_oneof_count = first_synthetic;
-  }
-
-  return true;
-}
-
-static void assign_msg_wellknowntype(upb_msgdef *m) {
-  const char *name = upb_msgdef_fullname(m);
-  if (name == NULL) {
-    m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED;
-    return;
-  }
-  if (!strcmp(name, "google.protobuf.Any")) {
-    m->well_known_type = UPB_WELLKNOWN_ANY;
-  } else if (!strcmp(name, "google.protobuf.FieldMask")) {
-    m->well_known_type = UPB_WELLKNOWN_FIELDMASK;
-  } else if (!strcmp(name, "google.protobuf.Duration")) {
-    m->well_known_type = UPB_WELLKNOWN_DURATION;
-  } else if (!strcmp(name, "google.protobuf.Timestamp")) {
-    m->well_known_type = UPB_WELLKNOWN_TIMESTAMP;
-  } else if (!strcmp(name, "google.protobuf.DoubleValue")) {
-    m->well_known_type = UPB_WELLKNOWN_DOUBLEVALUE;
-  } else if (!strcmp(name, "google.protobuf.FloatValue")) {
-    m->well_known_type = UPB_WELLKNOWN_FLOATVALUE;
-  } else if (!strcmp(name, "google.protobuf.Int64Value")) {
-    m->well_known_type = UPB_WELLKNOWN_INT64VALUE;
-  } else if (!strcmp(name, "google.protobuf.UInt64Value")) {
-    m->well_known_type = UPB_WELLKNOWN_UINT64VALUE;
-  } else if (!strcmp(name, "google.protobuf.Int32Value")) {
-    m->well_known_type = UPB_WELLKNOWN_INT32VALUE;
-  } else if (!strcmp(name, "google.protobuf.UInt32Value")) {
-    m->well_known_type = UPB_WELLKNOWN_UINT32VALUE;
-  } else if (!strcmp(name, "google.protobuf.BoolValue")) {
-    m->well_known_type = UPB_WELLKNOWN_BOOLVALUE;
-  } else if (!strcmp(name, "google.protobuf.StringValue")) {
-    m->well_known_type = UPB_WELLKNOWN_STRINGVALUE;
-  } else if (!strcmp(name, "google.protobuf.BytesValue")) {
-    m->well_known_type = UPB_WELLKNOWN_BYTESVALUE;
-  } else if (!strcmp(name, "google.protobuf.Value")) {
-    m->well_known_type = UPB_WELLKNOWN_VALUE;
-  } else if (!strcmp(name, "google.protobuf.ListValue")) {
-    m->well_known_type = UPB_WELLKNOWN_LISTVALUE;
-  } else if (!strcmp(name, "google.protobuf.Struct")) {
-    m->well_known_type = UPB_WELLKNOWN_STRUCT;
-  } else {
-    m->well_known_type = UPB_WELLKNOWN_UNSPECIFIED;
-  }
-}
-
-
-/* upb_enumdef ****************************************************************/
-
-const char *upb_enumdef_fullname(const upb_enumdef *e) {
-  return e->full_name;
-}
-
-const char *upb_enumdef_name(const upb_enumdef *e) {
-  return shortdefname(e->full_name);
-}
-
-const upb_filedef *upb_enumdef_file(const upb_enumdef *e) {
-  return e->file;
-}
-
-int32_t upb_enumdef_default(const upb_enumdef *e) {
-  UPB_ASSERT(upb_enumdef_iton(e, e->defaultval));
-  return e->defaultval;
-}
-
-int upb_enumdef_numvals(const upb_enumdef *e) {
-  return (int)upb_strtable_count(&e->ntoi);
-}
-
-void upb_enum_begin(upb_enum_iter *i, const upb_enumdef *e) {
-  /* We iterate over the ntoi table, to account for duplicate numbers. */
-  upb_strtable_begin(i, &e->ntoi);
-}
-
-void upb_enum_next(upb_enum_iter *iter) { upb_strtable_next(iter); }
-bool upb_enum_done(upb_enum_iter *iter) { return upb_strtable_done(iter); }
-
-bool upb_enumdef_ntoi(const upb_enumdef *def, const char *name,
-                      size_t len, int32_t *num) {
-  upb_value v;
-  if (!upb_strtable_lookup2(&def->ntoi, name, len, &v)) {
-    return false;
-  }
-  if (num) *num = upb_value_getint32(v);
-  return true;
-}
-
-const char *upb_enumdef_iton(const upb_enumdef *def, int32_t num) {
-  upb_value v;
-  return upb_inttable_lookup32(&def->iton, num, &v) ?
-      upb_value_getcstr(v) : NULL;
-}
-
-const char *upb_enum_iter_name(upb_enum_iter *iter) {
-  return upb_strtable_iter_key(iter).data;
-}
-
-int32_t upb_enum_iter_number(upb_enum_iter *iter) {
-  return upb_value_getint32(upb_strtable_iter_value(iter));
-}
-
-
-/* upb_fielddef ***************************************************************/
-
-const char *upb_fielddef_fullname(const upb_fielddef *f) {
-  return f->full_name;
-}
-
-upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f) {
-  switch (f->type_) {
-    case UPB_DESCRIPTOR_TYPE_DOUBLE:
-      return UPB_TYPE_DOUBLE;
-    case UPB_DESCRIPTOR_TYPE_FLOAT:
-      return UPB_TYPE_FLOAT;
-    case UPB_DESCRIPTOR_TYPE_INT64:
-    case UPB_DESCRIPTOR_TYPE_SINT64:
-    case UPB_DESCRIPTOR_TYPE_SFIXED64:
-      return UPB_TYPE_INT64;
-    case UPB_DESCRIPTOR_TYPE_INT32:
-    case UPB_DESCRIPTOR_TYPE_SFIXED32:
-    case UPB_DESCRIPTOR_TYPE_SINT32:
-      return UPB_TYPE_INT32;
-    case UPB_DESCRIPTOR_TYPE_UINT64:
-    case UPB_DESCRIPTOR_TYPE_FIXED64:
-      return UPB_TYPE_UINT64;
-    case UPB_DESCRIPTOR_TYPE_UINT32:
-    case UPB_DESCRIPTOR_TYPE_FIXED32:
-      return UPB_TYPE_UINT32;
-    case UPB_DESCRIPTOR_TYPE_ENUM:
-      return UPB_TYPE_ENUM;
-    case UPB_DESCRIPTOR_TYPE_BOOL:
-      return UPB_TYPE_BOOL;
-    case UPB_DESCRIPTOR_TYPE_STRING:
-      return UPB_TYPE_STRING;
-    case UPB_DESCRIPTOR_TYPE_BYTES:
-      return UPB_TYPE_BYTES;
-    case UPB_DESCRIPTOR_TYPE_GROUP:
-    case UPB_DESCRIPTOR_TYPE_MESSAGE:
-      return UPB_TYPE_MESSAGE;
-  }
-  UPB_UNREACHABLE();
-}
-
-upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f) {
-  return f->type_;
-}
-
-uint32_t upb_fielddef_index(const upb_fielddef *f) {
-  return f->index_;
-}
-
-upb_label_t upb_fielddef_label(const upb_fielddef *f) {
-  return f->label_;
-}
-
-uint32_t upb_fielddef_number(const upb_fielddef *f) {
-  return f->number_;
-}
-
-bool upb_fielddef_isextension(const upb_fielddef *f) {
-  return f->is_extension_;
-}
-
-bool upb_fielddef_lazy(const upb_fielddef *f) {
-  return f->lazy_;
-}
-
-bool upb_fielddef_packed(const upb_fielddef *f) {
-  return f->packed_;
-}
-
-const char *upb_fielddef_name(const upb_fielddef *f) {
-  return shortdefname(f->full_name);
-}
-
-const char *upb_fielddef_jsonname(const upb_fielddef *f) {
-  return f->json_name;
-}
-
-uint32_t upb_fielddef_selectorbase(const upb_fielddef *f) {
-  return f->selector_base;
-}
-
-const upb_filedef *upb_fielddef_file(const upb_fielddef *f) {
-  return f->file;
-}
-
-const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) {
-  return f->msgdef;
-}
-
-const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f) {
-  return f->oneof;
-}
-
-const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f) {
-  if (!f->oneof || upb_oneofdef_issynthetic(f->oneof)) return NULL;
-  return f->oneof;
-}
-
-static void chkdefaulttype(const upb_fielddef *f, int ctype) {
-  UPB_UNUSED(f);
-  UPB_UNUSED(ctype);
-}
-
-int64_t upb_fielddef_defaultint64(const upb_fielddef *f) {
-  chkdefaulttype(f, UPB_TYPE_INT64);
-  return f->defaultval.sint;
-}
-
-int32_t upb_fielddef_defaultint32(const upb_fielddef *f) {
-  chkdefaulttype(f, UPB_TYPE_INT32);
-  return (int32_t)f->defaultval.sint;
-}
-
-uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f) {
-  chkdefaulttype(f, UPB_TYPE_UINT64);
-  return f->defaultval.uint;
-}
-
-uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f) {
-  chkdefaulttype(f, UPB_TYPE_UINT32);
-  return (uint32_t)f->defaultval.uint;
-}
-
-bool upb_fielddef_defaultbool(const upb_fielddef *f) {
-  chkdefaulttype(f, UPB_TYPE_BOOL);
-  return f->defaultval.boolean;
-}
-
-float upb_fielddef_defaultfloat(const upb_fielddef *f) {
-  chkdefaulttype(f, UPB_TYPE_FLOAT);
-  return f->defaultval.flt;
-}
-
-double upb_fielddef_defaultdouble(const upb_fielddef *f) {
-  chkdefaulttype(f, UPB_TYPE_DOUBLE);
-  return f->defaultval.dbl;
-}
-
-const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) {
-  str_t *str = f->defaultval.str;
-  UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_STRING ||
-         upb_fielddef_type(f) == UPB_TYPE_BYTES ||
-         upb_fielddef_type(f) == UPB_TYPE_ENUM);
-  if (str) {
-    if (len) *len = str->len;
-    return str->str;
-  } else {
-    if (len) *len = 0;
-    return NULL;
-  }
-}
-
-const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f) {
-  UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_MESSAGE);
-  return f->sub.msgdef;
-}
-
-const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f) {
-  UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_ENUM);
-  return f->sub.enumdef;
-}
-
-const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f) {
-  return &f->msgdef->layout->fields[f->layout_index];
-}
-
-bool upb_fielddef_issubmsg(const upb_fielddef *f) {
-  return upb_fielddef_type(f) == UPB_TYPE_MESSAGE;
-}
-
-bool upb_fielddef_isstring(const upb_fielddef *f) {
-  return upb_fielddef_type(f) == UPB_TYPE_STRING ||
-         upb_fielddef_type(f) == UPB_TYPE_BYTES;
-}
-
-bool upb_fielddef_isseq(const upb_fielddef *f) {
-  return upb_fielddef_label(f) == UPB_LABEL_REPEATED;
-}
-
-bool upb_fielddef_isprimitive(const upb_fielddef *f) {
-  return !upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f);
-}
-
-bool upb_fielddef_ismap(const upb_fielddef *f) {
-  return upb_fielddef_isseq(f) && upb_fielddef_issubmsg(f) &&
-         upb_msgdef_mapentry(upb_fielddef_msgsubdef(f));
-}
-
-bool upb_fielddef_hassubdef(const upb_fielddef *f) {
-  return upb_fielddef_issubmsg(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM;
-}
-
-bool upb_fielddef_haspresence(const upb_fielddef *f) {
-  if (upb_fielddef_isseq(f)) return false;
-  return upb_fielddef_issubmsg(f) || upb_fielddef_containingoneof(f) ||
-         f->file->syntax == UPB_SYNTAX_PROTO2;
-}
-
-static bool between(int32_t x, int32_t low, int32_t high) {
-  return x >= low && x <= high;
-}
-
-bool upb_fielddef_checklabel(int32_t label) { return between(label, 1, 3); }
-bool upb_fielddef_checktype(int32_t type) { return between(type, 1, 11); }
-bool upb_fielddef_checkintfmt(int32_t fmt) { return between(fmt, 1, 3); }
-
-bool upb_fielddef_checkdescriptortype(int32_t type) {
-  return between(type, 1, 18);
-}
-
-/* upb_msgdef *****************************************************************/
-
-const char *upb_msgdef_fullname(const upb_msgdef *m) {
-  return m->full_name;
-}
-
-const upb_filedef *upb_msgdef_file(const upb_msgdef *m) {
-  return m->file;
-}
-
-const char *upb_msgdef_name(const upb_msgdef *m) {
-  return shortdefname(m->full_name);
-}
-
-upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m) {
-  return m->file->syntax;
-}
-
-size_t upb_msgdef_selectorcount(const upb_msgdef *m) {
-  return m->selector_count;
-}
-
-uint32_t upb_msgdef_submsgfieldcount(const upb_msgdef *m) {
-  return m->submsg_field_count;
-}
-
-const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) {
-  upb_value val;
-  return upb_inttable_lookup32(&m->itof, i, &val) ?
-      upb_value_getconstptr(val) : NULL;
-}
-
-const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
-                                    size_t len) {
-  upb_value val;
-
-  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
-    return NULL;
-  }
-
-  return unpack_def(val, UPB_DEFTYPE_FIELD);
-}
-
-const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
-                                    size_t len) {
-  upb_value val;
-
-  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
-    return NULL;
-  }
-
-  return unpack_def(val, UPB_DEFTYPE_ONEOF);
-}
-
-bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
-                           const upb_fielddef **f, const upb_oneofdef **o) {
-  upb_value val;
-
-  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
-    return false;
-  }
-
-  *o = unpack_def(val, UPB_DEFTYPE_ONEOF);
-  *f = unpack_def(val, UPB_DEFTYPE_FIELD);
-  return *o || *f;  /* False if this was a JSON name. */
-}
-
-const upb_fielddef *upb_msgdef_lookupjsonname(const upb_msgdef *m,
-                                              const char *name, size_t len) {
-  upb_value val;
-  const upb_fielddef* f;
-
-  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
-    return NULL;
-  }
-
-  f = unpack_def(val, UPB_DEFTYPE_FIELD);
-  if (!f) f = unpack_def(val, UPB_DEFTYPE_FIELD_JSONNAME);
-
-  return f;
-}
-
-int upb_msgdef_numfields(const upb_msgdef *m) {
-  return m->field_count;
-}
-
-int upb_msgdef_numoneofs(const upb_msgdef *m) {
-  return m->oneof_count;
-}
-
-int upb_msgdef_numrealoneofs(const upb_msgdef *m) {
-  return m->real_oneof_count;
-}
-
-const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m) {
-  return m->layout;
-}
-
-const upb_fielddef *_upb_msgdef_field(const upb_msgdef *m, int i) {
-  if (i >= m->field_count) return NULL;
-  return &m->fields[i];
-}
-
-bool upb_msgdef_mapentry(const upb_msgdef *m) {
-  return m->map_entry;
-}
-
-upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m) {
-  return m->well_known_type;
-}
-
-bool upb_msgdef_isnumberwrapper(const upb_msgdef *m) {
-  upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
-  return type >= UPB_WELLKNOWN_DOUBLEVALUE &&
-         type <= UPB_WELLKNOWN_UINT32VALUE;
-}
-
-void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m) {
-  upb_inttable_begin(iter, &m->itof);
-}
-
-void upb_msg_field_next(upb_msg_field_iter *iter) { upb_inttable_next(iter); }
-
-bool upb_msg_field_done(const upb_msg_field_iter *iter) {
-  return upb_inttable_done(iter);
-}
-
-upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter) {
-  return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter));
-}
-
-void upb_msg_field_iter_setdone(upb_msg_field_iter *iter) {
-  upb_inttable_iter_setdone(iter);
-}
-
-bool upb_msg_field_iter_isequal(const upb_msg_field_iter * iter1,
-                                const upb_msg_field_iter * iter2) {
-  return upb_inttable_iter_isequal(iter1, iter2);
-}
-
-void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) {
-  upb_strtable_begin(iter, &m->ntof);
-  /* We need to skip past any initial fields. */
-  while (!upb_strtable_done(iter) &&
-         !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF)) {
-    upb_strtable_next(iter);
-  }
-}
-
-void upb_msg_oneof_next(upb_msg_oneof_iter *iter) {
-  /* We need to skip past fields to return only oneofs. */
-  do {
-    upb_strtable_next(iter);
-  } while (!upb_strtable_done(iter) &&
-           !unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF));
-}
-
-bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) {
-  return upb_strtable_done(iter);
-}
-
-const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter) {
-  return unpack_def(upb_strtable_iter_value(iter), UPB_DEFTYPE_ONEOF);
-}
-
-void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter) {
-  upb_strtable_iter_setdone(iter);
-}
-
-bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1,
-                                const upb_msg_oneof_iter *iter2) {
-  return upb_strtable_iter_isequal(iter1, iter2);
-}
-
-/* upb_oneofdef ***************************************************************/
-
-const char *upb_oneofdef_name(const upb_oneofdef *o) {
-  return shortdefname(o->full_name);
-}
-
-const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) {
-  return o->parent;
-}
-
-int upb_oneofdef_numfields(const upb_oneofdef *o) {
-  return (int)upb_strtable_count(&o->ntof);
-}
-
-uint32_t upb_oneofdef_index(const upb_oneofdef *o) {
-  return o->index;
-}
-
-bool upb_oneofdef_issynthetic(const upb_oneofdef *o) {
-  upb_inttable_iter iter;
-  const upb_fielddef *f;
-  upb_inttable_begin(&iter, &o->itof);
-  if (upb_oneofdef_numfields(o) != 1) return false;
-  f = upb_value_getptr(upb_inttable_iter_value(&iter));
-  UPB_ASSERT(f);
-  return f->proto3_optional_;
-}
-
-const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
-                                      const char *name, size_t length) {
-  upb_value val;
-  return upb_strtable_lookup2(&o->ntof, name, length, &val) ?
-      upb_value_getptr(val) : NULL;
-}
-
-const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num) {
-  upb_value val;
-  return upb_inttable_lookup32(&o->itof, num, &val) ?
-      upb_value_getptr(val) : NULL;
-}
-
-void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o) {
-  upb_inttable_begin(iter, &o->itof);
-}
-
-void upb_oneof_next(upb_oneof_iter *iter) {
-  upb_inttable_next(iter);
-}
-
-bool upb_oneof_done(upb_oneof_iter *iter) {
-  return upb_inttable_done(iter);
-}
-
-upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) {
-  return (upb_fielddef *)upb_value_getconstptr(upb_inttable_iter_value(iter));
-}
-
-void upb_oneof_iter_setdone(upb_oneof_iter *iter) {
-  upb_inttable_iter_setdone(iter);
-}
-
-/* Dynamic Layout Generation. *************************************************/
-
-static bool is_power_of_two(size_t val) {
-  return (val & (val - 1)) == 0;
-}
-
-/* Align up to the given power of 2. */
-static size_t align_up(size_t val, size_t align) {
-  UPB_ASSERT(is_power_of_two(align));
-  return (val + align - 1) & ~(align - 1);
-}
-
-static size_t div_round_up(size_t n, size_t d) {
-  return (n + d - 1) / d;
-}
-
-static size_t upb_msgval_sizeof(upb_fieldtype_t type) {
-  switch (type) {
-    case UPB_TYPE_DOUBLE:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT64:
-      return 8;
-    case UPB_TYPE_ENUM:
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_FLOAT:
-      return 4;
-    case UPB_TYPE_BOOL:
-      return 1;
-    case UPB_TYPE_MESSAGE:
-      return sizeof(void*);
-    case UPB_TYPE_BYTES:
-    case UPB_TYPE_STRING:
-      return sizeof(upb_strview);
-  }
-  UPB_UNREACHABLE();
-}
-
-static uint8_t upb_msg_fielddefsize(const upb_fielddef *f) {
-  if (upb_msgdef_mapentry(upb_fielddef_containingtype(f))) {
-    upb_map_entry ent;
-    UPB_ASSERT(sizeof(ent.k) == sizeof(ent.v));
-    return sizeof(ent.k);
-  } else if (upb_fielddef_isseq(f)) {
-    return sizeof(void*);
-  } else {
-    return upb_msgval_sizeof(upb_fielddef_type(f));
-  }
-}
-
-static uint32_t upb_msglayout_place(upb_msglayout *l, size_t size) {
-  uint32_t ret;
-
-  l->size = align_up(l->size, size);
-  ret = l->size;
-  l->size += size;
-  return ret;
-}
-
-/* This function is the dynamic equivalent of message_layout.{cc,h} in upbc.
- * It computes a dynamic layout for all of the fields in |m|. */
-static bool make_layout(const upb_symtab *symtab, const upb_msgdef *m) {
-  upb_msglayout *l = (upb_msglayout*)m->layout;
-  upb_msg_field_iter it;
-  upb_msg_oneof_iter oit;
-  size_t hasbit;
-  size_t submsg_count = m->submsg_field_count;
-  const upb_msglayout **submsgs;
-  upb_msglayout_field *fields;
-  upb_alloc *alloc = upb_arena_alloc(symtab->arena);
-
-  memset(l, 0, sizeof(*l));
-
-  fields = upb_malloc(alloc, upb_msgdef_numfields(m) * sizeof(*fields));
-  submsgs = upb_malloc(alloc, submsg_count * sizeof(*submsgs));
-
-  if ((!fields && upb_msgdef_numfields(m)) ||
-      (!submsgs && submsg_count)) {
-    /* OOM. */
-    return false;
-  }
-
-  l->field_count = upb_msgdef_numfields(m);
-  l->fields = fields;
-  l->submsgs = submsgs;
-
-  if (upb_msgdef_mapentry(m)) {
-    /* TODO(haberman): refactor this method so this special case is more
-     * elegant. */
-    const upb_fielddef *key = upb_msgdef_itof(m, 1);
-    const upb_fielddef *val = upb_msgdef_itof(m, 2);
-    fields[0].number = 1;
-    fields[1].number = 2;
-    fields[0].label = UPB_LABEL_OPTIONAL;
-    fields[1].label = UPB_LABEL_OPTIONAL;
-    fields[0].presence = 0;
-    fields[1].presence = 0;
-    fields[0].descriptortype = upb_fielddef_descriptortype(key);
-    fields[1].descriptortype = upb_fielddef_descriptortype(val);
-    fields[0].offset = 0;
-    fields[1].offset = sizeof(upb_strview);
-    fields[1].submsg_index = 0;
-
-    if (upb_fielddef_type(val) == UPB_TYPE_MESSAGE) {
-      submsgs[0] = upb_fielddef_msgsubdef(val)->layout;
-    }
-
-    l->field_count = 2;
-    l->size = 2 * sizeof(upb_strview);align_up(l->size, 8);
-    return true;
-  }
-
-  /* Allocate data offsets in three stages:
-   *
-   * 1. hasbits.
-   * 2. regular fields.
-   * 3. oneof fields.
-   *
-   * OPT: There is a lot of room for optimization here to minimize the size.
-   */
-
-  /* Allocate hasbits and set basic field attributes. */
-  submsg_count = 0;
-  for (upb_msg_field_begin(&it, m), hasbit = 0;
-       !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    upb_fielddef* f = upb_msg_iter_field(&it);
-    upb_msglayout_field *field = &fields[upb_fielddef_index(f)];
-
-    field->number = upb_fielddef_number(f);
-    field->descriptortype = upb_fielddef_descriptortype(f);
-    field->label = upb_fielddef_label(f);
-
-    if (upb_fielddef_ismap(f)) {
-      field->label = _UPB_LABEL_MAP;
-    } else if (upb_fielddef_packed(f)) {
-      field->label = _UPB_LABEL_PACKED;
-    }
-
-    /* TODO: we probably should sort the fields by field number to match the
-     * output of upbc, and to improve search speed for the table parser. */
-    f->layout_index = f->index_;
-
-    if (upb_fielddef_issubmsg(f)) {
-      const upb_msgdef *subm = upb_fielddef_msgsubdef(f);
-      field->submsg_index = submsg_count++;
-      submsgs[field->submsg_index] = subm->layout;
-    }
-
-    if (upb_fielddef_haspresence(f) && !upb_fielddef_realcontainingoneof(f)) {
-      /* We don't use hasbit 0, so that 0 can indicate "no presence" in the
-       * table. This wastes one hasbit, but we don't worry about it for now. */
-      field->presence = ++hasbit;
-    } else {
-      field->presence = 0;
-    }
-  }
-
-  /* Account for space used by hasbits. */
-  l->size = div_round_up(hasbit, 8);
-
-  /* Allocate non-oneof fields. */
-  for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it);
-       upb_msg_field_next(&it)) {
-    const upb_fielddef* f = upb_msg_iter_field(&it);
-    size_t field_size = upb_msg_fielddefsize(f);
-    size_t index = upb_fielddef_index(f);
-
-    if (upb_fielddef_realcontainingoneof(f)) {
-      /* Oneofs are handled separately below. */
-      continue;
-    }
-
-    fields[index].offset = upb_msglayout_place(l, field_size);
-  }
-
-  /* Allocate oneof fields.  Each oneof field consists of a uint32 for the case
-   * and space for the actual data. */
-  for (upb_msg_oneof_begin(&oit, m); !upb_msg_oneof_done(&oit);
-       upb_msg_oneof_next(&oit)) {
-    const upb_oneofdef* o = upb_msg_iter_oneof(&oit);
-    upb_oneof_iter fit;
-
-    if (upb_oneofdef_issynthetic(o)) continue;
-
-    size_t case_size = sizeof(uint32_t);  /* Could potentially optimize this. */
-    size_t field_size = 0;
-    uint32_t case_offset;
-    uint32_t data_offset;
-
-    /* Calculate field size: the max of all field sizes. */
-    for (upb_oneof_begin(&fit, o);
-         !upb_oneof_done(&fit);
-         upb_oneof_next(&fit)) {
-      const upb_fielddef* f = upb_oneof_iter_field(&fit);
-      field_size = UPB_MAX(field_size, upb_msg_fielddefsize(f));
-    }
-
-    /* Align and allocate case offset. */
-    case_offset = upb_msglayout_place(l, case_size);
-    data_offset = upb_msglayout_place(l, field_size);
-
-    for (upb_oneof_begin(&fit, o);
-         !upb_oneof_done(&fit);
-         upb_oneof_next(&fit)) {
-      const upb_fielddef* f = upb_oneof_iter_field(&fit);
-      fields[upb_fielddef_index(f)].offset = data_offset;
-      fields[upb_fielddef_index(f)].presence = ~case_offset;
-    }
-  }
-
-  /* Size of the entire structure should be a multiple of its greatest
-   * alignment.  TODO: track overall alignment for real? */
-  l->size = align_up(l->size, 8);
-
-  return true;
-}
-
-/* Code to build defs from descriptor protos. *********************************/
-
-/* There is a question of how much validation to do here.  It will be difficult
- * to perfectly match the amount of validation performed by proto2.  But since
- * this code is used to directly build defs from Ruby (for example) we do need
- * to validate important constraints like uniqueness of names and numbers. */
-
-#define CHK(x) if (!(x)) { return false; }
-#define CHK_OOM(x) if (!(x)) { upb_status_setoom(ctx->status); return false; }
-
-typedef struct {
-  const upb_symtab *symtab;
-  upb_filedef *file;              /* File we are building. */
-  upb_alloc *alloc;               /* Allocate defs here. */
-  upb_alloc *tmp;                 /* Alloc for addtab and any other tmp data. */
-  upb_strtable *addtab;           /* full_name -> packed def ptr for new defs */
-  const upb_msglayout **layouts;  /* NULL if we should build layouts. */
-  upb_status *status;             /* Record errors here. */
-} symtab_addctx;
-
-static char* strviewdup(const symtab_addctx *ctx, upb_strview view) {
-  return upb_strdup2(view.data, view.size, ctx->alloc);
-}
-
-static bool streql2(const char *a, size_t n, const char *b) {
-  return n == strlen(b) && memcmp(a, b, n) == 0;
-}
-
-static bool streql_view(upb_strview view, const char *b) {
-  return streql2(view.data, view.size, b);
-}
-
-static const char *makefullname(const symtab_addctx *ctx, const char *prefix,
-                                upb_strview name) {
-  if (prefix) {
-    /* ret = prefix + '.' + name; */
-    size_t n = strlen(prefix);
-    char *ret = upb_malloc(ctx->alloc, n + name.size + 2);
-    CHK_OOM(ret);
-    strcpy(ret, prefix);
-    ret[n] = '.';
-    memcpy(&ret[n + 1], name.data, name.size);
-    ret[n + 1 + name.size] = '\0';
-    return ret;
-  } else {
-    return strviewdup(ctx, name);
-  }
-}
-
-size_t getjsonname(const char *name, char *buf, size_t len) {
-  size_t src, dst = 0;
-  bool ucase_next = false;
-
-#define WRITE(byte) \
-  ++dst; \
-  if (dst < len) buf[dst - 1] = byte; \
-  else if (dst == len) buf[dst - 1] = '\0'
-
-  if (!name) {
-    WRITE('\0');
-    return 0;
-  }
-
-  /* Implement the transformation as described in the spec:
-   *   1. upper case all letters after an underscore.
-   *   2. remove all underscores.
-   */
-  for (src = 0; name[src]; src++) {
-    if (name[src] == '_') {
-      ucase_next = true;
-      continue;
-    }
-
-    if (ucase_next) {
-      WRITE(toupper(name[src]));
-      ucase_next = false;
-    } else {
-      WRITE(name[src]);
-    }
-  }
-
-  WRITE('\0');
-  return dst;
-
-#undef WRITE
-}
-
-static char* makejsonname(const char* name, upb_alloc *alloc) {
-  size_t size = getjsonname(name, NULL, 0);
-  char* json_name = upb_malloc(alloc, size);
-  getjsonname(name, json_name, size);
-  return json_name;
-}
-
-static bool symtab_add(const symtab_addctx *ctx, const char *name,
-                       upb_value v) {
-  upb_value tmp;
-  if (upb_strtable_lookup(ctx->addtab, name, &tmp) ||
-      upb_strtable_lookup(&ctx->symtab->syms, name, &tmp)) {
-    upb_status_seterrf(ctx->status, "duplicate symbol '%s'", name);
-    return false;
-  }
-
-  CHK_OOM(upb_strtable_insert3(ctx->addtab, name, strlen(name), v, ctx->tmp));
-  return true;
-}
-
-/* Given a symbol and the base symbol inside which it is defined, find the
- * symbol's definition in t. */
-static bool resolvename(const upb_strtable *t, const upb_fielddef *f,
-                        const char *base, upb_strview sym,
-                        upb_deftype_t type, upb_status *status,
-                        const void **def) {
-  if(sym.size == 0) return NULL;
-  if(sym.data[0] == '.') {
-    /* Symbols starting with '.' are absolute, so we do a single lookup.
-     * Slice to omit the leading '.' */
-    upb_value v;
-    if (!upb_strtable_lookup2(t, sym.data + 1, sym.size - 1, &v)) {
-      return false;
-    }
-
-    *def = unpack_def(v, type);
-
-    if (!*def) {
-      upb_status_seterrf(status,
-                         "type mismatch when resolving field %s, name %s",
-                         f->full_name, sym.data);
-      return false;
-    }
-
-    return true;
-  } else {
-    /* Remove components from base until we find an entry or run out.
-     * TODO: This branch is totally broken, but currently not used. */
-    (void)base;
-    UPB_ASSERT(false);
-    return false;
-  }
-}
-
-const void *symtab_resolve(const symtab_addctx *ctx, const upb_fielddef *f,
-                           const char *base, upb_strview sym,
-                           upb_deftype_t type) {
-  const void *ret;
-  if (!resolvename(ctx->addtab, f, base, sym, type, ctx->status, &ret) &&
-      !resolvename(&ctx->symtab->syms, f, base, sym, type, ctx->status, &ret)) {
-    if (upb_ok(ctx->status)) {
-      upb_status_seterrf(ctx->status, "couldn't resolve name '%s'", sym.data);
-    }
-    return false;
-  }
-  return ret;
-}
-
-static bool create_oneofdef(
-    const symtab_addctx *ctx, upb_msgdef *m,
-    const google_protobuf_OneofDescriptorProto *oneof_proto) {
-  upb_oneofdef *o;
-  upb_strview name = google_protobuf_OneofDescriptorProto_name(oneof_proto);
-  upb_value v;
-
-  o = (upb_oneofdef*)&m->oneofs[m->oneof_count++];
-  o->parent = m;
-  o->full_name = makefullname(ctx, m->full_name, name);
-
-  v = pack_def(o, UPB_DEFTYPE_ONEOF);
-  CHK_OOM(symtab_add(ctx, o->full_name, v));
-  CHK_OOM(upb_strtable_insert3(&m->ntof, name.data, name.size, v, ctx->alloc));
-
-  CHK_OOM(upb_inttable_init2(&o->itof, UPB_CTYPE_CONSTPTR, ctx->alloc));
-  CHK_OOM(upb_strtable_init2(&o->ntof, UPB_CTYPE_CONSTPTR, ctx->alloc));
-
-  return true;
-}
-
-static bool parse_default(const symtab_addctx *ctx, const char *str, size_t len,
-                          upb_fielddef *f) {
-  char *end;
-  char nullz[64];
-  errno = 0;
-
-  switch (upb_fielddef_type(f)) {
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_UINT64:
-    case UPB_TYPE_DOUBLE:
-    case UPB_TYPE_FLOAT:
-      /* Standard C number parsing functions expect null-terminated strings. */
-      if (len >= sizeof(nullz) - 1) {
-        return false;
-      }
-      memcpy(nullz, str, len);
-      nullz[len] = '\0';
-      str = nullz;
-      break;
-    default:
-      break;
-  }
-
-  switch (upb_fielddef_type(f)) {
-    case UPB_TYPE_INT32: {
-      long val = strtol(str, &end, 0);
-      CHK(val <= INT32_MAX && val >= INT32_MIN && errno != ERANGE && !*end);
-      f->defaultval.sint = val;
-      break;
-    }
-    case UPB_TYPE_ENUM: {
-      const upb_enumdef *e = f->sub.enumdef;
-      int32_t val;
-      CHK(upb_enumdef_ntoi(e, str, len, &val));
-      f->defaultval.sint = val;
-      break;
-    }
-    case UPB_TYPE_INT64: {
-      /* XXX: Need to write our own strtoll, since it's not available in c89. */
-      int64_t val = strtol(str, &end, 0);
-      CHK(val <= INT64_MAX && val >= INT64_MIN && errno != ERANGE && !*end);
-      f->defaultval.sint = val;
-      break;
-    }
-    case UPB_TYPE_UINT32: {
-      unsigned long val = strtoul(str, &end, 0);
-      CHK(val <= UINT32_MAX && errno != ERANGE && !*end);
-      f->defaultval.uint = val;
-      break;
-    }
-    case UPB_TYPE_UINT64: {
-      /* XXX: Need to write our own strtoull, since it's not available in c89. */
-      uint64_t val = strtoul(str, &end, 0);
-      CHK(val <= UINT64_MAX && errno != ERANGE && !*end);
-      f->defaultval.uint = val;
-      break;
-    }
-    case UPB_TYPE_DOUBLE: {
-      double val = strtod(str, &end);
-      CHK(errno != ERANGE && !*end);
-      f->defaultval.dbl = val;
-      break;
-    }
-    case UPB_TYPE_FLOAT: {
-      /* XXX: Need to write our own strtof, since it's not available in c89. */
-      float val = strtod(str, &end);
-      CHK(errno != ERANGE && !*end);
-      f->defaultval.flt = val;
-      break;
-    }
-    case UPB_TYPE_BOOL: {
-      if (streql2(str, len, "false")) {
-        f->defaultval.boolean = false;
-      } else if (streql2(str, len, "true")) {
-        f->defaultval.boolean = true;
-      } else {
-        return false;
-      }
-      break;
-    }
-    case UPB_TYPE_STRING:
-      f->defaultval.str = newstr(ctx->alloc, str, len);
-      break;
-    case UPB_TYPE_BYTES:
-      /* XXX: need to interpret the C-escaped value. */
-      f->defaultval.str = newstr(ctx->alloc, str, len);
-      break;
-    case UPB_TYPE_MESSAGE:
-      /* Should not have a default value. */
-      return false;
-  }
-  return true;
-}
-
-static void set_default_default(const symtab_addctx *ctx, upb_fielddef *f) {
-  switch (upb_fielddef_type(f)) {
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_ENUM:
-      f->defaultval.sint = 0;
-      break;
-    case UPB_TYPE_UINT64:
-    case UPB_TYPE_UINT32:
-      f->defaultval.uint = 0;
-      break;
-    case UPB_TYPE_DOUBLE:
-    case UPB_TYPE_FLOAT:
-      f->defaultval.dbl = 0;
-      break;
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES:
-      f->defaultval.str = newstr(ctx->alloc, NULL, 0);
-      break;
-    case UPB_TYPE_BOOL:
-      f->defaultval.boolean = false;
-      break;
-    case UPB_TYPE_MESSAGE:
-      break;
-  }
-}
-
-static bool create_fielddef(
-    const symtab_addctx *ctx, const char *prefix, upb_msgdef *m,
-    const google_protobuf_FieldDescriptorProto *field_proto) {
-  upb_alloc *alloc = ctx->alloc;
-  upb_fielddef *f;
-  const google_protobuf_FieldOptions *options;
-  upb_strview name;
-  const char *full_name;
-  const char *json_name;
-  const char *shortname;
-  uint32_t field_number;
-
-  if (!google_protobuf_FieldDescriptorProto_has_name(field_proto)) {
-    upb_status_seterrmsg(ctx->status, "field has no name");
-    return false;
-  }
-
-  name = google_protobuf_FieldDescriptorProto_name(field_proto);
-  CHK(upb_isident(name, false, ctx->status));
-  full_name = makefullname(ctx, prefix, name);
-  shortname = shortdefname(full_name);
-
-  if (google_protobuf_FieldDescriptorProto_has_json_name(field_proto)) {
-    json_name = strviewdup(
-        ctx, google_protobuf_FieldDescriptorProto_json_name(field_proto));
-  } else {
-    json_name = makejsonname(shortname, ctx->alloc);
-  }
-
-  field_number = google_protobuf_FieldDescriptorProto_number(field_proto);
-
-  if (field_number == 0 || field_number > UPB_MAX_FIELDNUMBER) {
-    upb_status_seterrf(ctx->status, "invalid field number (%u)", field_number);
-    return false;
-  }
-
-  if (m) {
-    /* direct message field. */
-    upb_value v, field_v, json_v;
-    size_t json_size;
-
-    f = (upb_fielddef*)&m->fields[m->field_count++];
-    f->msgdef = m;
-    f->is_extension_ = false;
-
-    if (upb_strtable_lookup(&m->ntof, shortname, NULL)) {
-      upb_status_seterrf(ctx->status, "duplicate field name (%s)", shortname);
-      return false;
-    }
-
-    if (upb_strtable_lookup(&m->ntof, json_name, NULL)) {
-      upb_status_seterrf(ctx->status, "duplicate json_name (%s)", json_name);
-      return false;
-    }
-
-    if (upb_inttable_lookup(&m->itof, field_number, NULL)) {
-      upb_status_seterrf(ctx->status, "duplicate field number (%u)",
-                         field_number);
-      return false;
-    }
-
-    field_v = pack_def(f, UPB_DEFTYPE_FIELD);
-    json_v = pack_def(f, UPB_DEFTYPE_FIELD_JSONNAME);
-    v = upb_value_constptr(f);
-    json_size = strlen(json_name);
-
-    CHK_OOM(
-        upb_strtable_insert3(&m->ntof, name.data, name.size, field_v, alloc));
-    CHK_OOM(upb_inttable_insert2(&m->itof, field_number, v, alloc));
-
-    if (strcmp(shortname, json_name) != 0) {
-      upb_strtable_insert3(&m->ntof, json_name, json_size, json_v, alloc);
-    }
-
-    if (ctx->layouts) {
-      const upb_msglayout_field *fields = m->layout->fields;
-      int count = m->layout->field_count;
-      bool found = false;
-      int i;
-      for (i = 0; i < count; i++) {
-        if (fields[i].number == field_number) {
-          f->layout_index = i;
-          found = true;
-          break;
-        }
-      }
-      UPB_ASSERT(found);
-    }
-  } else {
-    /* extension field. */
-    f = (upb_fielddef*)&ctx->file->exts[ctx->file->ext_count++];
-    f->is_extension_ = true;
-    CHK_OOM(symtab_add(ctx, full_name, pack_def(f, UPB_DEFTYPE_FIELD)));
-  }
-
-  f->full_name = full_name;
-  f->json_name = json_name;
-  f->file = ctx->file;
-  f->type_ = (int)google_protobuf_FieldDescriptorProto_type(field_proto);
-  f->label_ = (int)google_protobuf_FieldDescriptorProto_label(field_proto);
-  f->number_ = field_number;
-  f->oneof = NULL;
-  f->proto3_optional_ =
-      google_protobuf_FieldDescriptorProto_proto3_optional(field_proto);
-
-  /* We can't resolve the subdef or (in the case of extensions) the containing
-   * message yet, because it may not have been defined yet.  We stash a pointer
-   * to the field_proto until later when we can properly resolve it. */
-  f->sub.unresolved = field_proto;
-
-  if (f->label_ == UPB_LABEL_REQUIRED && f->file->syntax == UPB_SYNTAX_PROTO3) {
-    upb_status_seterrf(ctx->status, "proto3 fields cannot be required (%s)",
-                       f->full_name);
-    return false;
-  }
-
-  if (google_protobuf_FieldDescriptorProto_has_oneof_index(field_proto)) {
-    int oneof_index =
-        google_protobuf_FieldDescriptorProto_oneof_index(field_proto);
-    upb_oneofdef *oneof;
-    upb_value v = upb_value_constptr(f);
-
-    if (upb_fielddef_label(f) != UPB_LABEL_OPTIONAL) {
-      upb_status_seterrf(ctx->status,
-                         "fields in oneof must have OPTIONAL label (%s)",
-                         f->full_name);
-      return false;
-    }
-
-    if (!m) {
-      upb_status_seterrf(ctx->status,
-                         "oneof_index provided for extension field (%s)",
-                         f->full_name);
-      return false;
-    }
-
-    if (oneof_index >= m->oneof_count) {
-      upb_status_seterrf(ctx->status, "oneof_index out of range (%s)",
-                         f->full_name);
-      return false;
-    }
-
-    oneof = (upb_oneofdef*)&m->oneofs[oneof_index];
-    f->oneof = oneof;
-
-    CHK(upb_inttable_insert2(&oneof->itof, f->number_, v, alloc));
-    CHK(upb_strtable_insert3(&oneof->ntof, name.data, name.size, v, alloc));
-  } else {
-    f->oneof = NULL;
-  }
-
-  if (google_protobuf_FieldDescriptorProto_has_options(field_proto)) {
-    options = google_protobuf_FieldDescriptorProto_options(field_proto);
-    f->lazy_ = google_protobuf_FieldOptions_lazy(options);
-    f->packed_ = google_protobuf_FieldOptions_packed(options);
-  } else {
-    f->lazy_ = false;
-    f->packed_ = false;
-  }
-
-  return true;
-}
-
-static bool create_enumdef(
-    const symtab_addctx *ctx, const char *prefix,
-    const google_protobuf_EnumDescriptorProto *enum_proto) {
-  upb_enumdef *e;
-  const google_protobuf_EnumValueDescriptorProto *const *values;
-  upb_strview name;
-  size_t i, n;
-
-  name = google_protobuf_EnumDescriptorProto_name(enum_proto);
-  CHK(upb_isident(name, false, ctx->status));
-
-  e = (upb_enumdef*)&ctx->file->enums[ctx->file->enum_count++];
-  e->full_name = makefullname(ctx, prefix, name);
-  CHK_OOM(symtab_add(ctx, e->full_name, pack_def(e, UPB_DEFTYPE_ENUM)));
-
-  CHK_OOM(upb_strtable_init2(&e->ntoi, UPB_CTYPE_INT32, ctx->alloc));
-  CHK_OOM(upb_inttable_init2(&e->iton, UPB_CTYPE_CSTR, ctx->alloc));
-
-  e->file = ctx->file;
-  e->defaultval = 0;
-
-  values = google_protobuf_EnumDescriptorProto_value(enum_proto, &n);
-
-  if (n == 0) {
-    upb_status_seterrf(ctx->status,
-                       "enums must contain at least one value (%s)",
-                       e->full_name);
-    return false;
-  }
-
-  for (i = 0; i < n; i++) {
-    const google_protobuf_EnumValueDescriptorProto *value = values[i];
-    upb_strview name = google_protobuf_EnumValueDescriptorProto_name(value);
-    char *name2 = strviewdup(ctx, name);
-    int32_t num = google_protobuf_EnumValueDescriptorProto_number(value);
-    upb_value v = upb_value_int32(num);
-
-    if (i == 0 && e->file->syntax == UPB_SYNTAX_PROTO3 && num != 0) {
-      upb_status_seterrf(ctx->status,
-                         "for proto3, the first enum value must be zero (%s)",
-                         e->full_name);
-      return false;
-    }
-
-    if (upb_strtable_lookup(&e->ntoi, name2, NULL)) {
-      upb_status_seterrf(ctx->status, "duplicate enum label '%s'", name2);
-      return false;
-    }
-
-    CHK_OOM(name2)
-    CHK_OOM(
-        upb_strtable_insert3(&e->ntoi, name2, strlen(name2), v, ctx->alloc));
-
-    if (!upb_inttable_lookup(&e->iton, num, NULL)) {
-      upb_value v = upb_value_cstr(name2);
-      CHK_OOM(upb_inttable_insert2(&e->iton, num, v, ctx->alloc));
-    }
-  }
-
-  upb_inttable_compact2(&e->iton, ctx->alloc);
-
-  return true;
-}
-
-static bool create_msgdef(symtab_addctx *ctx, const char *prefix,
-                          const google_protobuf_DescriptorProto *msg_proto) {
-  upb_msgdef *m;
-  const google_protobuf_MessageOptions *options;
-  const google_protobuf_OneofDescriptorProto *const *oneofs;
-  const google_protobuf_FieldDescriptorProto *const *fields;
-  const google_protobuf_EnumDescriptorProto *const *enums;
-  const google_protobuf_DescriptorProto *const *msgs;
-  size_t i, n;
-  upb_strview name;
-
-  name = google_protobuf_DescriptorProto_name(msg_proto);
-  CHK(upb_isident(name, false, ctx->status));
-
-  m = (upb_msgdef*)&ctx->file->msgs[ctx->file->msg_count++];
-  m->full_name = makefullname(ctx, prefix, name);
-  CHK_OOM(symtab_add(ctx, m->full_name, pack_def(m, UPB_DEFTYPE_MSG)));
-
-  CHK_OOM(upb_inttable_init2(&m->itof, UPB_CTYPE_CONSTPTR, ctx->alloc));
-  CHK_OOM(upb_strtable_init2(&m->ntof, UPB_CTYPE_CONSTPTR, ctx->alloc));
-
-  m->file = ctx->file;
-  m->map_entry = false;
-
-  options = google_protobuf_DescriptorProto_options(msg_proto);
-
-  if (options) {
-    m->map_entry = google_protobuf_MessageOptions_map_entry(options);
-  }
-
-  if (ctx->layouts) {
-    m->layout = *ctx->layouts;
-    ctx->layouts++;
-  } else {
-    /* Allocate now (to allow cross-linking), populate later. */
-    m->layout = upb_malloc(ctx->alloc, sizeof(*m->layout));
-  }
-
-  oneofs = google_protobuf_DescriptorProto_oneof_decl(msg_proto, &n);
-  m->oneof_count = 0;
-  m->oneofs = upb_malloc(ctx->alloc, sizeof(*m->oneofs) * n);
-  for (i = 0; i < n; i++) {
-    CHK(create_oneofdef(ctx, m, oneofs[i]));
-  }
-
-  fields = google_protobuf_DescriptorProto_field(msg_proto, &n);
-  m->field_count = 0;
-  m->fields = upb_malloc(ctx->alloc, sizeof(*m->fields) * n);
-  for (i = 0; i < n; i++) {
-    CHK(create_fielddef(ctx, m->full_name, m, fields[i]));
-  }
-
-  CHK(assign_msg_indices(m, ctx->status));
-  CHK(check_oneofs(m, ctx->status));
-  assign_msg_wellknowntype(m);
-  upb_inttable_compact2(&m->itof, ctx->alloc);
-
-  /* This message is built.  Now build nested messages and enums. */
-
-  enums = google_protobuf_DescriptorProto_enum_type(msg_proto, &n);
-  for (i = 0; i < n; i++) {
-    CHK(create_enumdef(ctx, m->full_name, enums[i]));
-  }
-
-  msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
-  for (i = 0; i < n; i++) {
-    CHK(create_msgdef(ctx, m->full_name, msgs[i]));
-  }
-
-  return true;
-}
-
-typedef struct {
-  int msg_count;
-  int enum_count;
-  int ext_count;
-} decl_counts;
-
-static void count_types_in_msg(const google_protobuf_DescriptorProto *msg_proto,
-                               decl_counts *counts) {
-  const google_protobuf_DescriptorProto *const *msgs;
-  size_t i, n;
-
-  counts->msg_count++;
-
-  msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
-  for (i = 0; i < n; i++) {
-    count_types_in_msg(msgs[i], counts);
-  }
-
-  google_protobuf_DescriptorProto_enum_type(msg_proto, &n);
-  counts->enum_count += n;
-
-  google_protobuf_DescriptorProto_extension(msg_proto, &n);
-  counts->ext_count += n;
-}
-
-static void count_types_in_file(
-    const google_protobuf_FileDescriptorProto *file_proto,
-    decl_counts *counts) {
-  const google_protobuf_DescriptorProto *const *msgs;
-  size_t i, n;
-
-  msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
-  for (i = 0; i < n; i++) {
-    count_types_in_msg(msgs[i], counts);
-  }
-
-  google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
-  counts->enum_count += n;
-
-  google_protobuf_FileDescriptorProto_extension(file_proto, &n);
-  counts->ext_count += n;
-}
-
-static bool resolve_fielddef(const symtab_addctx *ctx, const char *prefix,
-                             upb_fielddef *f) {
-  upb_strview name;
-  const google_protobuf_FieldDescriptorProto *field_proto = f->sub.unresolved;
-
-  if (f->is_extension_) {
-    if (!google_protobuf_FieldDescriptorProto_has_extendee(field_proto)) {
-      upb_status_seterrf(ctx->status,
-                         "extension for field '%s' had no extendee",
-                         f->full_name);
-      return false;
-    }
-
-    name = google_protobuf_FieldDescriptorProto_extendee(field_proto);
-    f->msgdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_MSG);
-    CHK(f->msgdef);
-  }
-
-  if ((upb_fielddef_issubmsg(f) || f->type_ == UPB_DESCRIPTOR_TYPE_ENUM) &&
-      !google_protobuf_FieldDescriptorProto_has_type_name(field_proto)) {
-    upb_status_seterrf(ctx->status, "field '%s' is missing type name",
-                       f->full_name);
-    return false;
-  }
-
-  name = google_protobuf_FieldDescriptorProto_type_name(field_proto);
-
-  if (upb_fielddef_issubmsg(f)) {
-    f->sub.msgdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_MSG);
-    CHK(f->sub.msgdef);
-  } else if (f->type_ == UPB_DESCRIPTOR_TYPE_ENUM) {
-    f->sub.enumdef = symtab_resolve(ctx, f, prefix, name, UPB_DEFTYPE_ENUM);
-    CHK(f->sub.enumdef);
-  }
-
-  /* Have to delay resolving of the default value until now because of the enum
-   * case, since enum defaults are specified with a label. */
-  if (google_protobuf_FieldDescriptorProto_has_default_value(field_proto)) {
-    upb_strview defaultval =
-        google_protobuf_FieldDescriptorProto_default_value(field_proto);
-
-    if (f->file->syntax == UPB_SYNTAX_PROTO3) {
-      upb_status_seterrf(ctx->status,
-                         "proto3 fields cannot have explicit defaults (%s)",
-                         f->full_name);
-      return false;
-    }
-
-    if (upb_fielddef_issubmsg(f)) {
-      upb_status_seterrf(ctx->status,
-                         "message fields cannot have explicit defaults (%s)",
-                         f->full_name);
-      return false;
-    }
-
-    if (!parse_default(ctx, defaultval.data, defaultval.size, f)) {
-      upb_status_seterrf(ctx->status,
-                         "couldn't parse default '" UPB_STRVIEW_FORMAT
-                         "' for field (%s)",
-                         UPB_STRVIEW_ARGS(defaultval), f->full_name);
-      return false;
-    }
-  } else {
-    set_default_default(ctx, f);
-  }
-
-  return true;
-}
-
-static bool build_filedef(
-    symtab_addctx *ctx, upb_filedef *file,
-    const google_protobuf_FileDescriptorProto *file_proto) {
-  upb_alloc *alloc = ctx->alloc;
-  const google_protobuf_FileOptions *file_options_proto;
-  const google_protobuf_DescriptorProto *const *msgs;
-  const google_protobuf_EnumDescriptorProto *const *enums;
-  const google_protobuf_FieldDescriptorProto *const *exts;
-  const upb_strview* strs;
-  size_t i, n;
-  decl_counts counts = {0};
-
-  count_types_in_file(file_proto, &counts);
-
-  file->msgs = upb_malloc(alloc, sizeof(*file->msgs) * counts.msg_count);
-  file->enums = upb_malloc(alloc, sizeof(*file->enums) * counts.enum_count);
-  file->exts = upb_malloc(alloc, sizeof(*file->exts) * counts.ext_count);
-
-  CHK_OOM(counts.msg_count == 0 || file->msgs);
-  CHK_OOM(counts.enum_count == 0 || file->enums);
-  CHK_OOM(counts.ext_count == 0 || file->exts);
-
-  /* We increment these as defs are added. */
-  file->msg_count = 0;
-  file->enum_count = 0;
-  file->ext_count = 0;
-
-  if (!google_protobuf_FileDescriptorProto_has_name(file_proto)) {
-    upb_status_seterrmsg(ctx->status, "File has no name");
-    return false;
-  }
-
-  file->name =
-      strviewdup(ctx, google_protobuf_FileDescriptorProto_name(file_proto));
-  file->phpprefix = NULL;
-  file->phpnamespace = NULL;
-
-  if (google_protobuf_FileDescriptorProto_has_package(file_proto)) {
-    upb_strview package =
-        google_protobuf_FileDescriptorProto_package(file_proto);
-    CHK(upb_isident(package, true, ctx->status));
-    file->package = strviewdup(ctx, package);
-  } else {
-    file->package = NULL;
-  }
-
-  if (google_protobuf_FileDescriptorProto_has_syntax(file_proto)) {
-    upb_strview syntax =
-        google_protobuf_FileDescriptorProto_syntax(file_proto);
-
-    if (streql_view(syntax, "proto2")) {
-      file->syntax = UPB_SYNTAX_PROTO2;
-    } else if (streql_view(syntax, "proto3")) {
-      file->syntax = UPB_SYNTAX_PROTO3;
-    } else {
-      upb_status_seterrf(ctx->status, "Invalid syntax '" UPB_STRVIEW_FORMAT "'",
-                         UPB_STRVIEW_ARGS(syntax));
-      return false;
-    }
-  } else {
-    file->syntax = UPB_SYNTAX_PROTO2;
-  }
-
-  /* Read options. */
-  file_options_proto = google_protobuf_FileDescriptorProto_options(file_proto);
-  if (file_options_proto) {
-    if (google_protobuf_FileOptions_has_php_class_prefix(file_options_proto)) {
-      file->phpprefix = strviewdup(
-          ctx,
-          google_protobuf_FileOptions_php_class_prefix(file_options_proto));
-    }
-    if (google_protobuf_FileOptions_has_php_namespace(file_options_proto)) {
-      file->phpnamespace = strviewdup(
-          ctx, google_protobuf_FileOptions_php_namespace(file_options_proto));
-    }
-  }
-
-  /* Verify dependencies. */
-  strs = google_protobuf_FileDescriptorProto_dependency(file_proto, &n);
-  file->deps = upb_malloc(alloc, sizeof(*file->deps) * n) ;
-  CHK_OOM(n == 0 || file->deps);
-
-  for (i = 0; i < n; i++) {
-    upb_strview dep_name = strs[i];
-    upb_value v;
-    if (!upb_strtable_lookup2(&ctx->symtab->files, dep_name.data,
-                              dep_name.size, &v)) {
-      upb_status_seterrf(ctx->status,
-                         "Depends on file '" UPB_STRVIEW_FORMAT
-                         "', but it has not been loaded",
-                         UPB_STRVIEW_ARGS(dep_name));
-      return false;
-    }
-    file->deps[i] = upb_value_getconstptr(v);
-  }
-
-  /* Create messages. */
-  msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
-  for (i = 0; i < n; i++) {
-    CHK(create_msgdef(ctx, file->package, msgs[i]));
-  }
-
-  /* Create enums. */
-  enums = google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
-  for (i = 0; i < n; i++) {
-    CHK(create_enumdef(ctx, file->package, enums[i]));
-  }
-
-  /* Create extensions. */
-  exts = google_protobuf_FileDescriptorProto_extension(file_proto, &n);
-  file->exts = upb_malloc(alloc, sizeof(*file->exts) * n);
-  CHK_OOM(n == 0 || file->exts);
-  for (i = 0; i < n; i++) {
-    CHK(create_fielddef(ctx, file->package, NULL, exts[i]));
-  }
-
-  /* Now that all names are in the table, build layouts and resolve refs. */
-  for (i = 0; i < file->ext_count; i++) {
-    CHK(resolve_fielddef(ctx, file->package, (upb_fielddef*)&file->exts[i]));
-  }
-
-  for (i = 0; i < file->msg_count; i++) {
-    const upb_msgdef *m = &file->msgs[i];
-    int j;
-    for (j = 0; j < m->field_count; j++) {
-      CHK(resolve_fielddef(ctx, m->full_name, (upb_fielddef*)&m->fields[j]));
-    }
-  }
-
-  if (!ctx->layouts) {
-    for (i = 0; i < file->msg_count; i++) {
-      const upb_msgdef *m = &file->msgs[i];
-      make_layout(ctx->symtab, m);
-    }
-  }
-
-  return true;
- }
-
-static bool upb_symtab_addtotabs(upb_symtab *s, symtab_addctx *ctx,
-                                 upb_status *status) {
-  const upb_filedef *file = ctx->file;
-  upb_alloc *alloc = upb_arena_alloc(s->arena);
-  upb_strtable_iter iter;
-
-  CHK_OOM(upb_strtable_insert3(&s->files, file->name, strlen(file->name),
-                               upb_value_constptr(file), alloc));
-
-  upb_strtable_begin(&iter, ctx->addtab);
-  for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
-    upb_strview key = upb_strtable_iter_key(&iter);
-    upb_value value = upb_strtable_iter_value(&iter);
-    CHK_OOM(upb_strtable_insert3(&s->syms, key.data, key.size, value, alloc));
-  }
-
-  return true;
-}
-
-/* upb_filedef ****************************************************************/
-
-const char *upb_filedef_name(const upb_filedef *f) {
-  return f->name;
-}
-
-const char *upb_filedef_package(const upb_filedef *f) {
-  return f->package;
-}
-
-const char *upb_filedef_phpprefix(const upb_filedef *f) {
-  return f->phpprefix;
-}
-
-const char *upb_filedef_phpnamespace(const upb_filedef *f) {
-  return f->phpnamespace;
-}
-
-upb_syntax_t upb_filedef_syntax(const upb_filedef *f) {
-  return f->syntax;
-}
-
-int upb_filedef_msgcount(const upb_filedef *f) {
-  return f->msg_count;
-}
-
-int upb_filedef_depcount(const upb_filedef *f) {
-  return f->dep_count;
-}
-
-int upb_filedef_enumcount(const upb_filedef *f) {
-  return f->enum_count;
-}
-
-const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i) {
-  return i < 0 || i >= f->dep_count ? NULL : f->deps[i];
-}
-
-const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i) {
-  return i < 0 || i >= f->msg_count ? NULL : &f->msgs[i];
-}
-
-const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i) {
-  return i < 0 || i >= f->enum_count ? NULL : &f->enums[i];
-}
-
-void upb_symtab_free(upb_symtab *s) {
-  upb_arena_free(s->arena);
-  upb_gfree(s);
-}
-
-upb_symtab *upb_symtab_new(void) {
-  upb_symtab *s = upb_gmalloc(sizeof(*s));
-  upb_alloc *alloc;
-
-  if (!s) {
-    return NULL;
-  }
-
-  s->arena = upb_arena_new();
-  alloc = upb_arena_alloc(s->arena);
-
-  if (!upb_strtable_init2(&s->syms, UPB_CTYPE_CONSTPTR, alloc) ||
-      !upb_strtable_init2(&s->files, UPB_CTYPE_CONSTPTR, alloc)) {
-    upb_arena_free(s->arena);
-    upb_gfree(s);
-    s = NULL;
-  }
-  return s;
-}
-
-const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym) {
-  upb_value v;
-  return upb_strtable_lookup(&s->syms, sym, &v) ?
-      unpack_def(v, UPB_DEFTYPE_MSG) : NULL;
-}
-
-const upb_msgdef *upb_symtab_lookupmsg2(const upb_symtab *s, const char *sym,
-                                        size_t len) {
-  upb_value v;
-  return upb_strtable_lookup2(&s->syms, sym, len, &v) ?
-      unpack_def(v, UPB_DEFTYPE_MSG) : NULL;
-}
-
-const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym) {
-  upb_value v;
-  return upb_strtable_lookup(&s->syms, sym, &v) ?
-      unpack_def(v, UPB_DEFTYPE_ENUM) : NULL;
-}
-
-const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name) {
-  upb_value v;
-  return upb_strtable_lookup(&s->files, name, &v) ? upb_value_getconstptr(v)
-                                                  : NULL;
-}
-
-int upb_symtab_filecount(const upb_symtab *s) {
-  return (int)upb_strtable_count(&s->files);
-}
-
-static const upb_filedef *_upb_symtab_addfile(
-    upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto,
-    const upb_msglayout **layouts, upb_status *status) {
-  upb_arena *tmparena = upb_arena_new();
-  upb_strtable addtab;
-  upb_alloc *alloc = upb_arena_alloc(s->arena);
-  upb_filedef *file = upb_malloc(alloc, sizeof(*file));
-  bool ok;
-  symtab_addctx ctx;
-
-  ctx.file = file;
-  ctx.symtab = s;
-  ctx.alloc = alloc;
-  ctx.tmp = upb_arena_alloc(tmparena);
-  ctx.addtab = &addtab;
-  ctx.layouts = layouts;
-  ctx.status = status;
-
-  ok = file &&
-      upb_strtable_init2(&addtab, UPB_CTYPE_CONSTPTR, ctx.tmp) &&
-      build_filedef(&ctx, file, file_proto) &&
-      upb_symtab_addtotabs(s, &ctx, status);
-
-  upb_arena_free(tmparena);
-  return ok ? file : NULL;
-}
-
-const upb_filedef *upb_symtab_addfile(
-    upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto,
-    upb_status *status) {
-  return _upb_symtab_addfile(s, file_proto, NULL, status);
-}
-
-/* Include here since we want most of this file to be stdio-free. */
-#include <stdio.h>
-
-bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init) {
-  /* Since this function should never fail (it would indicate a bug in upb) we
-   * print errors to stderr instead of returning error status to the user. */
-  upb_def_init **deps = init->deps;
-  google_protobuf_FileDescriptorProto *file;
-  upb_arena *arena;
-  upb_status status;
-
-  upb_status_clear(&status);
-
-  if (upb_strtable_lookup(&s->files, init->filename, NULL)) {
-    return true;
-  }
-
-  arena = upb_arena_new();
-
-  for (; *deps; deps++) {
-    if (!_upb_symtab_loaddefinit(s, *deps)) goto err;
-  }
-
-  file = google_protobuf_FileDescriptorProto_parse(
-      init->descriptor.data, init->descriptor.size, arena);
-
-  if (!file) {
-    upb_status_seterrf(
-        &status,
-        "Failed to parse compiled-in descriptor for file '%s'. This should "
-        "never happen.",
-        init->filename);
-    goto err;
-  }
-
-  if (!_upb_symtab_addfile(s, file, init->layouts, &status)) goto err;
-
-  upb_arena_free(arena);
-  return true;
-
-err:
-  fprintf(stderr, "Error loading compiled-in descriptor: %s\n",
-          upb_status_errmsg(&status));
-  upb_arena_free(arena);
-  return false;
-}
-
-#undef CHK
-#undef CHK_OOM
-
-
-#include <string.h>
-
-
-static char field_size[] = {
-  0,/* 0 */
-  8, /* UPB_DESCRIPTOR_TYPE_DOUBLE */
-  4, /* UPB_DESCRIPTOR_TYPE_FLOAT */
-  8, /* UPB_DESCRIPTOR_TYPE_INT64 */
-  8, /* UPB_DESCRIPTOR_TYPE_UINT64 */
-  4, /* UPB_DESCRIPTOR_TYPE_INT32 */
-  8, /* UPB_DESCRIPTOR_TYPE_FIXED64 */
-  4, /* UPB_DESCRIPTOR_TYPE_FIXED32 */
-  1, /* UPB_DESCRIPTOR_TYPE_BOOL */
-  sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_STRING */
-  sizeof(void*), /* UPB_DESCRIPTOR_TYPE_GROUP */
-  sizeof(void*), /* UPB_DESCRIPTOR_TYPE_MESSAGE */
-  sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_BYTES */
-  4, /* UPB_DESCRIPTOR_TYPE_UINT32 */
-  4, /* UPB_DESCRIPTOR_TYPE_ENUM */
-  4, /* UPB_DESCRIPTOR_TYPE_SFIXED32 */
-  8, /* UPB_DESCRIPTOR_TYPE_SFIXED64 */
-  4, /* UPB_DESCRIPTOR_TYPE_SINT32 */
-  8, /* UPB_DESCRIPTOR_TYPE_SINT64 */
-};
-
-/* Strings/bytes are special-cased in maps. */
-static char _upb_fieldtype_to_mapsize[12] = {
-  0,
-  1,  /* UPB_TYPE_BOOL */
-  4,  /* UPB_TYPE_FLOAT */
-  4,  /* UPB_TYPE_INT32 */
-  4,  /* UPB_TYPE_UINT32 */
-  4,  /* UPB_TYPE_ENUM */
-  sizeof(void*),  /* UPB_TYPE_MESSAGE */
-  8,  /* UPB_TYPE_DOUBLE */
-  8,  /* UPB_TYPE_INT64 */
-  8,  /* UPB_TYPE_UINT64 */
-  0,  /* UPB_TYPE_STRING */
-  0,  /* UPB_TYPE_BYTES */
-};
-
-/** upb_msg *******************************************************************/
-
-upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a) {
-  return _upb_msg_new(upb_msgdef_layout(m), a);
-}
-
-static bool in_oneof(const upb_msglayout_field *field) {
-  return field->presence < 0;
-}
-
-static uint32_t *oneofcase(const upb_msg *msg,
-                           const upb_msglayout_field *field) {
-  UPB_ASSERT(in_oneof(field));
-  return UPB_PTR_AT(msg, -field->presence, uint32_t);
-}
-
-static upb_msgval _upb_msg_getraw(const upb_msg *msg, const upb_fielddef *f) {
-  const upb_msglayout_field *field = upb_fielddef_layout(f);
-  const char *mem = UPB_PTR_AT(msg, field->offset, char);
-  upb_msgval val = {0};
-  int size = upb_fielddef_isseq(f) ? sizeof(void *)
-                                   : field_size[field->descriptortype];
-  memcpy(&val, mem, size);
-  return val;
-}
-
-bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f) {
-  const upb_msglayout_field *field = upb_fielddef_layout(f);
-  if (in_oneof(field)) {
-    return *oneofcase(msg, field) == field->number;
-  } else if (field->presence > 0) {
-    uint32_t hasbit = field->presence;
-    return *UPB_PTR_AT(msg, hasbit / 8, uint8_t) & (1 << (hasbit % 8));
-  } else {
-    UPB_ASSERT(field->descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE ||
-               field->descriptortype == UPB_DESCRIPTOR_TYPE_GROUP);
-    return _upb_msg_getraw(msg, f).msg_val != NULL;
-  }
-}
-
-bool upb_msg_hasoneof(const upb_msg *msg, const upb_oneofdef *o) {
-  upb_oneof_iter i;
-  const upb_fielddef *f;
-  const upb_msglayout_field *field;
-
-  upb_oneof_begin(&i, o);
-  if (upb_oneof_done(&i)) return false;
-  f = upb_oneof_iter_field(&i);
-  field = upb_fielddef_layout(f);
-  return *oneofcase(msg, field) != 0;
-}
-
-upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f) {
-  if (!upb_fielddef_haspresence(f) || upb_msg_has(msg, f)) {
-    return _upb_msg_getraw(msg, f);
-  } else {
-    /* TODO(haberman): change upb_fielddef to not require this switch(). */
-    upb_msgval val = {0};
-    switch (upb_fielddef_type(f)) {
-      case UPB_TYPE_INT32:
-      case UPB_TYPE_ENUM:
-        val.int32_val = upb_fielddef_defaultint32(f);
-        break;
-      case UPB_TYPE_INT64:
-        val.int64_val = upb_fielddef_defaultint64(f);
-        break;
-      case UPB_TYPE_UINT32:
-        val.uint32_val = upb_fielddef_defaultuint32(f);
-        break;
-      case UPB_TYPE_UINT64:
-        val.uint64_val = upb_fielddef_defaultuint64(f);
-        break;
-      case UPB_TYPE_FLOAT:
-        val.float_val = upb_fielddef_defaultfloat(f);
-        break;
-      case UPB_TYPE_DOUBLE:
-        val.double_val = upb_fielddef_defaultdouble(f);
-        break;
-      case UPB_TYPE_BOOL:
-        val.double_val = upb_fielddef_defaultbool(f);
-        break;
-      case UPB_TYPE_STRING:
-      case UPB_TYPE_BYTES:
-        val.str_val.data = upb_fielddef_defaultstr(f, &val.str_val.size);
-        break;
-      case UPB_TYPE_MESSAGE:
-        val.msg_val = NULL;
-        break;
-    }
-    return val;
-  }
-}
-
-upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f,
-                              upb_arena *a) {
-  const upb_msglayout_field *field = upb_fielddef_layout(f);
-  upb_mutmsgval ret;
-  char *mem = UPB_PTR_AT(msg, field->offset, char);
-  bool wrong_oneof = in_oneof(field) && *oneofcase(msg, field) != field->number;
-
-  memcpy(&ret, mem, sizeof(void*));
-
-  if (a && (!ret.msg || wrong_oneof)) {
-    if (upb_fielddef_ismap(f)) {
-      const upb_msgdef *entry = upb_fielddef_msgsubdef(f);
-      const upb_fielddef *key = upb_msgdef_itof(entry, UPB_MAPENTRY_KEY);
-      const upb_fielddef *value = upb_msgdef_itof(entry, UPB_MAPENTRY_VALUE);
-      ret.map = upb_map_new(a, upb_fielddef_type(key), upb_fielddef_type(value));
-    } else if (upb_fielddef_isseq(f)) {
-      ret.array = upb_array_new(a, upb_fielddef_type(f));
-    } else {
-      UPB_ASSERT(upb_fielddef_issubmsg(f));
-      ret.msg = upb_msg_new(upb_fielddef_msgsubdef(f), a);
-    }
-
-    memcpy(mem, &ret, sizeof(void*));
-
-    if (wrong_oneof) {
-      *oneofcase(msg, field) = field->number;
-    }
-  }
-  return ret;
-}
-
-void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val,
-                 upb_arena *a) {
-  const upb_msglayout_field *field = upb_fielddef_layout(f);
-  char *mem = UPB_PTR_AT(msg, field->offset, char);
-  int size = upb_fielddef_isseq(f) ? sizeof(void *)
-                                   : field_size[field->descriptortype];
-  memcpy(mem, &val, size);
-  if (in_oneof(field)) {
-    *oneofcase(msg, field) = field->number;
-  }
-}
-
-bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m,
-                  const upb_symtab *ext_pool, const upb_fielddef **out_f,
-                  upb_msgval *out_val, size_t *iter) {
-  size_t i = *iter;
-  const upb_msgval zero = {0};
-  const upb_fielddef *f;
-  while ((f = _upb_msgdef_field(m, (int)++i)) != NULL) {
-    upb_msgval val = _upb_msg_getraw(msg, f);
-
-    /* Skip field if unset or empty. */
-    if (upb_fielddef_haspresence(f)) {
-      if (!upb_msg_has(msg, f)) continue;
-    } else {
-      upb_msgval test = val;
-      if (upb_fielddef_isstring(f) && !upb_fielddef_isseq(f)) {
-        /* Clear string pointer, only size matters (ptr could be non-NULL). */
-        test.str_val.data = NULL;
-      }
-      /* Continue if NULL or 0. */
-      if (memcmp(&test, &zero, sizeof(test)) == 0) continue;
-
-      /* Continue on empty array or map. */
-      if (upb_fielddef_ismap(f)) {
-        if (upb_map_size(test.map_val) == 0) continue;
-      } else if (upb_fielddef_isseq(f)) {
-        if (upb_array_size(test.array_val) == 0) continue;
-      }
-    }
-
-    *out_val = val;
-    *out_f = f;
-    *iter = i;
-    return true;
-  }
-  *iter = i;
-  return false;
-}
-
-/** upb_array *****************************************************************/
-
-upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type) {
-  return _upb_array_new(a, type);
-}
-
-size_t upb_array_size(const upb_array *arr) {
-  return arr->len;
-}
-
-upb_msgval upb_array_get(const upb_array *arr, size_t i) {
-  upb_msgval ret;
-  const char* data = _upb_array_constptr(arr);
-  int lg2 = arr->data & 7;
-  UPB_ASSERT(i < arr->len);
-  memcpy(&ret, data + (i << lg2), 1 << lg2);
-  return ret;
-}
-
-void upb_array_set(upb_array *arr, size_t i, upb_msgval val) {
-  char* data = _upb_array_ptr(arr);
-  int lg2 = arr->data & 7;
-  UPB_ASSERT(i < arr->len);
-  memcpy(data + (i << lg2), &val, 1 << lg2);
-}
-
-bool upb_array_append(upb_array *arr, upb_msgval val, upb_arena *arena) {
-  if (!_upb_array_realloc(arr, arr->len + 1, arena)) {
-    return false;
-  }
-  arr->len++;
-  upb_array_set(arr, arr->len - 1, val);
-  return true;
-}
-
-/* Resizes the array to the given size, reallocating if necessary, and returns a
- * pointer to the new array elements. */
-bool upb_array_resize(upb_array *arr, size_t size, upb_arena *arena) {
-  return _upb_array_realloc(arr, size, arena);
-}
-
-/** upb_map *******************************************************************/
-
-upb_map *upb_map_new(upb_arena *a, upb_fieldtype_t key_type,
-                     upb_fieldtype_t value_type) {
-  return _upb_map_new(a, _upb_fieldtype_to_mapsize[key_type],
-                      _upb_fieldtype_to_mapsize[value_type]);
-}
-
-size_t upb_map_size(const upb_map *map) {
-  return _upb_map_size(map);
-}
-
-bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val) {
-  return _upb_map_get(map, &key, map->key_size, val, map->val_size);
-}
-
-bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val,
-                 upb_arena *arena) {
-  return _upb_map_set(map, &key, map->key_size, &val, map->val_size, arena);
-}
-
-bool upb_map_delete(upb_map *map, upb_msgval key) {
-  return _upb_map_delete(map, &key, map->key_size);
-}
-
-bool upb_mapiter_next(const upb_map *map, size_t *iter) {
-  return _upb_map_next(map, iter);
-}
-
-/* Returns the key and value for this entry of the map. */
-upb_msgval upb_mapiter_key(const upb_map *map, size_t iter) {
-  upb_strtable_iter i;
-  upb_msgval ret;
-  i.t = &map->table;
-  i.index = iter;
-  _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size);
-  return ret;
-}
-
-upb_msgval upb_mapiter_value(const upb_map *map, size_t iter) {
-  upb_strtable_iter i;
-  upb_msgval ret;
-  i.t = &map->table;
-  i.index = iter;
-  _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size);
-  return ret;
-}
-
-/* void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value); */
-/*
-** TODO(haberman): it's unclear whether a lot of the consistency checks should
-** UPB_ASSERT() or return false.
-*/
-
-
-#include <string.h>
-
-
-
-struct upb_handlers {
-  upb_handlercache *cache;
-  const upb_msgdef *msg;
-  const upb_handlers **sub;
-  const void *top_closure_type;
-  upb_handlers_tabent table[1];  /* Dynamically-sized field handler array. */
-};
-
-static void *upb_calloc(upb_arena *arena, size_t size) {
-  void *mem = upb_malloc(upb_arena_alloc(arena), size);
-  if (mem) {
-    memset(mem, 0, size);
-  }
-  return mem;
-}
-
-/* Defined for the sole purpose of having a unique pointer value for
- * UPB_NO_CLOSURE. */
-char _upb_noclosure;
-
-/* Given a selector for a STARTSUBMSG handler, resolves to a pointer to the
- * subhandlers for this submessage field. */
-#define SUBH(h, selector) (h->sub[selector])
-
-/* The selector for a submessage field is the field index. */
-#define SUBH_F(h, f) SUBH(h, upb_fielddef_index(f))
-
-static int32_t trygetsel(upb_handlers *h, const upb_fielddef *f,
-                         upb_handlertype_t type) {
-  upb_selector_t sel;
-  bool ok;
-
-  ok = upb_handlers_getselector(f, type, &sel);
-
-  UPB_ASSERT(upb_handlers_msgdef(h) == upb_fielddef_containingtype(f));
-  UPB_ASSERT(ok);
-
-  return sel;
-}
-
-static upb_selector_t handlers_getsel(upb_handlers *h, const upb_fielddef *f,
-                             upb_handlertype_t type) {
-  int32_t sel = trygetsel(h, f, type);
-  UPB_ASSERT(sel >= 0);
-  return sel;
-}
-
-static const void **returntype(upb_handlers *h, const upb_fielddef *f,
-                               upb_handlertype_t type) {
-  return &h->table[handlers_getsel(h, f, type)].attr.return_closure_type;
-}
-
-static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f,
-                  upb_handlertype_t type, upb_func *func,
-                  const upb_handlerattr *attr) {
-  upb_handlerattr set_attr = UPB_HANDLERATTR_INIT;
-  const void *closure_type;
-  const void **context_closure_type;
-
-  UPB_ASSERT(!h->table[sel].func);
-
-  if (attr) {
-    set_attr = *attr;
-  }
-
-  /* Check that the given closure type matches the closure type that has been
-   * established for this context (if any). */
-  closure_type = set_attr.closure_type;
-
-  if (type == UPB_HANDLER_STRING) {
-    context_closure_type = returntype(h, f, UPB_HANDLER_STARTSTR);
-  } else if (f && upb_fielddef_isseq(f) &&
-             type != UPB_HANDLER_STARTSEQ &&
-             type != UPB_HANDLER_ENDSEQ) {
-    context_closure_type = returntype(h, f, UPB_HANDLER_STARTSEQ);
-  } else {
-    context_closure_type = &h->top_closure_type;
-  }
-
-  if (closure_type && *context_closure_type &&
-      closure_type != *context_closure_type) {
-    return false;
-  }
-
-  if (closure_type)
-    *context_closure_type = closure_type;
-
-  /* If this is a STARTSEQ or STARTSTR handler, check that the returned pointer
-   * matches any pre-existing expectations about what type is expected. */
-  if (type == UPB_HANDLER_STARTSEQ || type == UPB_HANDLER_STARTSTR) {
-    const void *return_type = set_attr.return_closure_type;
-    const void *table_return_type = h->table[sel].attr.return_closure_type;
-    if (return_type && table_return_type && return_type != table_return_type) {
-      return false;
-    }
-
-    if (table_return_type && !return_type) {
-      set_attr.return_closure_type = table_return_type;
-    }
-  }
-
-  h->table[sel].func = (upb_func*)func;
-  h->table[sel].attr = set_attr;
-  return true;
-}
-
-/* Returns the effective closure type for this handler (which will propagate
- * from outer frames if this frame has no START* handler).  Not implemented for
- * UPB_HANDLER_STRING at the moment since this is not needed.  Returns NULL is
- * the effective closure type is unspecified (either no handler was registered
- * to specify it or the handler that was registered did not specify the closure
- * type). */
-const void *effective_closure_type(upb_handlers *h, const upb_fielddef *f,
-                                   upb_handlertype_t type) {
-  const void *ret;
-  upb_selector_t sel;
-
-  UPB_ASSERT(type != UPB_HANDLER_STRING);
-  ret = h->top_closure_type;
-
-  if (upb_fielddef_isseq(f) &&
-      type != UPB_HANDLER_STARTSEQ &&
-      type != UPB_HANDLER_ENDSEQ &&
-      h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSEQ)].func) {
-    ret = h->table[sel].attr.return_closure_type;
-  }
-
-  if (type == UPB_HANDLER_STRING &&
-      h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSTR)].func) {
-    ret = h->table[sel].attr.return_closure_type;
-  }
-
-  /* The effective type of the submessage; not used yet.
-   * if (type == SUBMESSAGE &&
-   *     h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)].func) {
-   *   ret = h->table[sel].attr.return_closure_type;
-   * } */
-
-  return ret;
-}
-
-/* Checks whether the START* handler specified by f & type is missing even
- * though it is required to convert the established type of an outer frame
- * ("closure_type") into the established type of an inner frame (represented in
- * the return closure type of this handler's attr. */
-bool checkstart(upb_handlers *h, const upb_fielddef *f, upb_handlertype_t type,
-                upb_status *status) {
-  const void *closure_type;
-  const upb_handlerattr *attr;
-  const void *return_closure_type;
-
-  upb_selector_t sel = handlers_getsel(h, f, type);
-  if (h->table[sel].func) return true;
-  closure_type = effective_closure_type(h, f, type);
-  attr = &h->table[sel].attr;
-  return_closure_type = attr->return_closure_type;
-  if (closure_type && return_closure_type &&
-      closure_type != return_closure_type) {
-    return false;
-  }
-  return true;
-}
-
-static upb_handlers *upb_handlers_new(const upb_msgdef *md,
-                                      upb_handlercache *cache,
-                                      upb_arena *arena) {
-  int extra;
-  upb_handlers *h;
-
-  extra =
-      (int)(sizeof(upb_handlers_tabent) * (upb_msgdef_selectorcount(md) - 1));
-  h = upb_calloc(arena, sizeof(*h) + extra);
-  if (!h) return NULL;
-
-  h->cache = cache;
-  h->msg = md;
-
-  if (upb_msgdef_submsgfieldcount(md) > 0) {
-    size_t bytes = upb_msgdef_submsgfieldcount(md) * sizeof(*h->sub);
-    h->sub = upb_calloc(arena, bytes);
-    if (!h->sub) return NULL;
-  } else {
-    h->sub = 0;
-  }
-
-  /* calloc() above initialized all handlers to NULL. */
-  return h;
-}
-
-/* Public interface ***********************************************************/
-
-#define SETTER(name, handlerctype, handlertype)                       \
-  bool upb_handlers_set##name(upb_handlers *h, const upb_fielddef *f, \
-                              handlerctype func,                      \
-                              const upb_handlerattr *attr) {          \
-    int32_t sel = trygetsel(h, f, handlertype);                       \
-    return doset(h, sel, f, handlertype, (upb_func *)func, attr);     \
-  }
-
-SETTER(int32,       upb_int32_handlerfunc*,       UPB_HANDLER_INT32)
-SETTER(int64,       upb_int64_handlerfunc*,       UPB_HANDLER_INT64)
-SETTER(uint32,      upb_uint32_handlerfunc*,      UPB_HANDLER_UINT32)
-SETTER(uint64,      upb_uint64_handlerfunc*,      UPB_HANDLER_UINT64)
-SETTER(float,       upb_float_handlerfunc*,       UPB_HANDLER_FLOAT)
-SETTER(double,      upb_double_handlerfunc*,      UPB_HANDLER_DOUBLE)
-SETTER(bool,        upb_bool_handlerfunc*,        UPB_HANDLER_BOOL)
-SETTER(startstr,    upb_startstr_handlerfunc*,    UPB_HANDLER_STARTSTR)
-SETTER(string,      upb_string_handlerfunc*,      UPB_HANDLER_STRING)
-SETTER(endstr,      upb_endfield_handlerfunc*,    UPB_HANDLER_ENDSTR)
-SETTER(startseq,    upb_startfield_handlerfunc*,  UPB_HANDLER_STARTSEQ)
-SETTER(startsubmsg, upb_startfield_handlerfunc*,  UPB_HANDLER_STARTSUBMSG)
-SETTER(endsubmsg,   upb_endfield_handlerfunc*,    UPB_HANDLER_ENDSUBMSG)
-SETTER(endseq,      upb_endfield_handlerfunc*,    UPB_HANDLER_ENDSEQ)
-
-#undef SETTER
-
-bool upb_handlers_setunknown(upb_handlers *h, upb_unknown_handlerfunc *func,
-                             const upb_handlerattr *attr) {
-  return doset(h, UPB_UNKNOWN_SELECTOR, NULL, UPB_HANDLER_INT32,
-               (upb_func *)func, attr);
-}
-
-bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func,
-                              const upb_handlerattr *attr) {
-  return doset(h, UPB_STARTMSG_SELECTOR, NULL, UPB_HANDLER_INT32,
-               (upb_func *)func, attr);
-}
-
-bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func,
-                            const upb_handlerattr *attr) {
-  return doset(h, UPB_ENDMSG_SELECTOR, NULL, UPB_HANDLER_INT32,
-               (upb_func *)func, attr);
-}
-
-bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f,
-                                 const upb_handlers *sub) {
-  UPB_ASSERT(sub);
-  UPB_ASSERT(upb_fielddef_issubmsg(f));
-  if (SUBH_F(h, f)) return false;  /* Can't reset. */
-  if (upb_handlers_msgdef(sub) != upb_fielddef_msgsubdef(f)) {
-    return false;
-  }
-  SUBH_F(h, f) = sub;
-  return true;
-}
-
-const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h,
-                                                const upb_fielddef *f) {
-  UPB_ASSERT(upb_fielddef_issubmsg(f));
-  return SUBH_F(h, f);
-}
-
-upb_func *upb_handlers_gethandler(const upb_handlers *h, upb_selector_t s,
-                                  const void **handler_data) {
-  upb_func *ret = (upb_func *)h->table[s].func;
-  if (ret && handler_data) {
-    *handler_data = h->table[s].attr.handler_data;
-  }
-  return ret;
-}
-
-bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t sel,
-                          upb_handlerattr *attr) {
-  if (!upb_handlers_gethandler(h, sel, NULL))
-    return false;
-  *attr = h->table[sel].attr;
-  return true;
-}
-
-const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h,
-                                                    upb_selector_t sel) {
-  /* STARTSUBMSG selector in sel is the field's selector base. */
-  return SUBH(h, sel - UPB_STATIC_SELECTOR_COUNT);
-}
-
-const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h) { return h->msg; }
-
-bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *func) {
-  return upb_handlercache_addcleanup(h->cache, p, func);
-}
-
-upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f) {
-  switch (upb_fielddef_type(f)) {
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_ENUM: return UPB_HANDLER_INT32;
-    case UPB_TYPE_INT64: return UPB_HANDLER_INT64;
-    case UPB_TYPE_UINT32: return UPB_HANDLER_UINT32;
-    case UPB_TYPE_UINT64: return UPB_HANDLER_UINT64;
-    case UPB_TYPE_FLOAT: return UPB_HANDLER_FLOAT;
-    case UPB_TYPE_DOUBLE: return UPB_HANDLER_DOUBLE;
-    case UPB_TYPE_BOOL: return UPB_HANDLER_BOOL;
-    default: UPB_ASSERT(false); return -1;  /* Invalid input. */
-  }
-}
-
-bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
-                              upb_selector_t *s) {
-  uint32_t selector_base = upb_fielddef_selectorbase(f);
-  switch (type) {
-    case UPB_HANDLER_INT32:
-    case UPB_HANDLER_INT64:
-    case UPB_HANDLER_UINT32:
-    case UPB_HANDLER_UINT64:
-    case UPB_HANDLER_FLOAT:
-    case UPB_HANDLER_DOUBLE:
-    case UPB_HANDLER_BOOL:
-      if (!upb_fielddef_isprimitive(f) ||
-          upb_handlers_getprimitivehandlertype(f) != type)
-        return false;
-      *s = selector_base;
-      break;
-    case UPB_HANDLER_STRING:
-      if (upb_fielddef_isstring(f)) {
-        *s = selector_base;
-      } else if (upb_fielddef_lazy(f)) {
-        *s = selector_base + 3;
-      } else {
-        return false;
-      }
-      break;
-    case UPB_HANDLER_STARTSTR:
-      if (upb_fielddef_isstring(f) || upb_fielddef_lazy(f)) {
-        *s = selector_base + 1;
-      } else {
-        return false;
-      }
-      break;
-    case UPB_HANDLER_ENDSTR:
-      if (upb_fielddef_isstring(f) || upb_fielddef_lazy(f)) {
-        *s = selector_base + 2;
-      } else {
-        return false;
-      }
-      break;
-    case UPB_HANDLER_STARTSEQ:
-      if (!upb_fielddef_isseq(f)) return false;
-      *s = selector_base - 2;
-      break;
-    case UPB_HANDLER_ENDSEQ:
-      if (!upb_fielddef_isseq(f)) return false;
-      *s = selector_base - 1;
-      break;
-    case UPB_HANDLER_STARTSUBMSG:
-      if (!upb_fielddef_issubmsg(f)) return false;
-      /* Selectors for STARTSUBMSG are at the beginning of the table so that the
-       * selector can also be used as an index into the "sub" array of
-       * subhandlers.  The indexes for the two into these two tables are the
-       * same, except that in the handler table the static selectors come first. */
-      *s = upb_fielddef_index(f) + UPB_STATIC_SELECTOR_COUNT;
-      break;
-    case UPB_HANDLER_ENDSUBMSG:
-      if (!upb_fielddef_issubmsg(f)) return false;
-      *s = selector_base;
-      break;
-  }
-  UPB_ASSERT((size_t)*s < upb_msgdef_selectorcount(upb_fielddef_containingtype(f)));
-  return true;
-}
-
-/* upb_handlercache ***********************************************************/
-
-struct upb_handlercache {
-  upb_arena *arena;
-  upb_inttable tab;  /* maps upb_msgdef* -> upb_handlers*. */
-  upb_handlers_callback *callback;
-  const void *closure;
-};
-
-const upb_handlers *upb_handlercache_get(upb_handlercache *c,
-                                         const upb_msgdef *md) {
-  upb_msg_field_iter i;
-  upb_value v;
-  upb_handlers *h;
-
-  if (upb_inttable_lookupptr(&c->tab, md, &v)) {
-    return upb_value_getptr(v);
-  }
-
-  h = upb_handlers_new(md, c, c->arena);
-  v = upb_value_ptr(h);
-
-  if (!h) return NULL;
-  if (!upb_inttable_insertptr(&c->tab, md, v)) return NULL;
-
-  c->callback(c->closure, h);
-
-  /* For each submessage field, get or create a handlers object and set it as
-   * the subhandlers. */
-  for(upb_msg_field_begin(&i, md);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    upb_fielddef *f = upb_msg_iter_field(&i);
-
-    if (upb_fielddef_issubmsg(f)) {
-      const upb_msgdef *subdef = upb_fielddef_msgsubdef(f);
-      const upb_handlers *sub_mh = upb_handlercache_get(c, subdef);
-
-      if (!sub_mh) return NULL;
-
-      upb_handlers_setsubhandlers(h, f, sub_mh);
-    }
-  }
-
-  return h;
-}
-
-
-upb_handlercache *upb_handlercache_new(upb_handlers_callback *callback,
-                                       const void *closure) {
-  upb_handlercache *cache = upb_gmalloc(sizeof(*cache));
-
-  if (!cache) return NULL;
-
-  cache->arena = upb_arena_new();
-
-  cache->callback = callback;
-  cache->closure = closure;
-
-  if (!upb_inttable_init(&cache->tab, UPB_CTYPE_PTR)) goto oom;
-
-  return cache;
-
-oom:
-  upb_gfree(cache);
-  return NULL;
-}
-
-void upb_handlercache_free(upb_handlercache *cache) {
-  upb_inttable_uninit(&cache->tab);
-  upb_arena_free(cache->arena);
-  upb_gfree(cache);
-}
-
-bool upb_handlercache_addcleanup(upb_handlercache *c, void *p,
-                                 upb_handlerfree *func) {
-  return upb_arena_addcleanup(c->arena, p, func);
-}
-
-/* upb_byteshandler ***********************************************************/
-
-bool upb_byteshandler_setstartstr(upb_byteshandler *h,
-                                  upb_startstr_handlerfunc *func, void *d) {
-  h->table[UPB_STARTSTR_SELECTOR].func = (upb_func*)func;
-  h->table[UPB_STARTSTR_SELECTOR].attr.handler_data = d;
-  return true;
-}
-
-bool upb_byteshandler_setstring(upb_byteshandler *h,
-                                upb_string_handlerfunc *func, void *d) {
-  h->table[UPB_STRING_SELECTOR].func = (upb_func*)func;
-  h->table[UPB_STRING_SELECTOR].attr.handler_data = d;
-  return true;
-}
-
-bool upb_byteshandler_setendstr(upb_byteshandler *h,
-                                upb_endfield_handlerfunc *func, void *d) {
-  h->table[UPB_ENDSTR_SELECTOR].func = (upb_func*)func;
-  h->table[UPB_ENDSTR_SELECTOR].attr.handler_data = d;
-  return true;
-}
-
-/** Handlers for upb_msg ******************************************************/
-
-typedef struct {
-  size_t offset;
-  int32_t hasbit;
-} upb_msg_handlerdata;
-
-/* Fallback implementation if the handler is not specialized by the producer. */
-#define MSG_WRITER(type, ctype)                                               \
-  bool upb_msg_set ## type (void *c, const void *hd, ctype val) {             \
-    uint8_t *m = c;                                                           \
-    const upb_msg_handlerdata *d = hd;                                        \
-    if (d->hasbit > 0)                                                        \
-      *(uint8_t*)&m[d->hasbit / 8] |= 1 << (d->hasbit % 8);                   \
-    *(ctype*)&m[d->offset] = val;                                             \
-    return true;                                                              \
-  }                                                                           \
-
-MSG_WRITER(double, double)
-MSG_WRITER(float,  float)
-MSG_WRITER(int32,  int32_t)
-MSG_WRITER(int64,  int64_t)
-MSG_WRITER(uint32, uint32_t)
-MSG_WRITER(uint64, uint64_t)
-MSG_WRITER(bool,   bool)
-
-bool upb_msg_setscalarhandler(upb_handlers *h, const upb_fielddef *f,
-                              size_t offset, int32_t hasbit) {
-  upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-  bool ok;
-
-  upb_msg_handlerdata *d = upb_gmalloc(sizeof(*d));
-  if (!d) return false;
-  d->offset = offset;
-  d->hasbit = hasbit;
-
-  attr.handler_data = d;
-  attr.alwaysok = true;
-  upb_handlers_addcleanup(h, d, upb_gfree);
-
-#define TYPE(u, l) \
-  case UPB_TYPE_##u: \
-    ok = upb_handlers_set##l(h, f, upb_msg_set##l, &attr); break;
-
-  ok = false;
-
-  switch (upb_fielddef_type(f)) {
-    TYPE(INT64,  int64);
-    TYPE(INT32,  int32);
-    TYPE(ENUM,   int32);
-    TYPE(UINT64, uint64);
-    TYPE(UINT32, uint32);
-    TYPE(DOUBLE, double);
-    TYPE(FLOAT,  float);
-    TYPE(BOOL,   bool);
-    default: UPB_ASSERT(false); break;
-  }
-#undef TYPE
-
-  return ok;
-}
-
-bool upb_msg_getscalarhandlerdata(const upb_handlers *h,
-                                  upb_selector_t s,
-                                  upb_fieldtype_t *type,
-                                  size_t *offset,
-                                  int32_t *hasbit) {
-  const upb_msg_handlerdata *d;
-  const void *p;
-  upb_func *f = upb_handlers_gethandler(h, s, &p);
-
-  if ((upb_int64_handlerfunc*)f == upb_msg_setint64) {
-    *type = UPB_TYPE_INT64;
-  } else if ((upb_int32_handlerfunc*)f == upb_msg_setint32) {
-    *type = UPB_TYPE_INT32;
-  } else if ((upb_uint64_handlerfunc*)f == upb_msg_setuint64) {
-    *type = UPB_TYPE_UINT64;
-  } else if ((upb_uint32_handlerfunc*)f == upb_msg_setuint32) {
-    *type = UPB_TYPE_UINT32;
-  } else if ((upb_double_handlerfunc*)f == upb_msg_setdouble) {
-    *type = UPB_TYPE_DOUBLE;
-  } else if ((upb_float_handlerfunc*)f == upb_msg_setfloat) {
-    *type = UPB_TYPE_FLOAT;
-  } else if ((upb_bool_handlerfunc*)f == upb_msg_setbool) {
-    *type = UPB_TYPE_BOOL;
-  } else {
-    return false;
-  }
-
-  d = p;
-  *offset = d->offset;
-  *hasbit = d->hasbit;
-  return true;
-}
-
-
-bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink sink) {
-  void *subc;
-  bool ret;
-  upb_bufhandle handle = UPB_BUFHANDLE_INIT;
-  handle.buf = buf;
-  ret = upb_bytessink_start(sink, len, &subc);
-  if (ret && len != 0) {
-    ret = (upb_bytessink_putbuf(sink, subc, buf, len, &handle) >= len);
-  }
-  if (ret) {
-    ret = upb_bytessink_end(sink);
-  }
-  return ret;
-}
-
-
-#ifdef UPB_MSVC_VSNPRINTF
-/* Visual C++ earlier than 2015 doesn't have standard C99 snprintf and
- * vsnprintf. To support them, missing functions are manually implemented
- * using the existing secure functions. */
-int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg) {
-  if (!s) {
-    return _vscprintf(format, arg);
-  }
-  int ret = _vsnprintf_s(s, n, _TRUNCATE, format, arg);
-  if (ret < 0) {
-	ret = _vscprintf(format, arg);
-  }
-  return ret;
-}
-
-int msvc_snprintf(char* s, size_t n, const char* format, ...) {
-  va_list arg;
-  va_start(arg, format);
-  int ret = msvc_vsnprintf(s, n, format, arg);
-  va_end(arg);
-  return ret;
-}
-#endif
-/*
-** protobuf decoder bytecode compiler
-**
-** Code to compile a upb::Handlers into bytecode for decoding a protobuf
-** according to that specific schema and destination handlers.
-**
-** Bytecode definition is in decoder.int.h.
-*/
-
-#include <stdarg.h>
-
-#ifdef UPB_DUMP_BYTECODE
-#include <stdio.h>
-#endif
-
-
-#define MAXLABEL 5
-#define EMPTYLABEL -1
-
-/* upb_pbdecodermethod ********************************************************/
-
-static void freemethod(upb_pbdecodermethod *method) {
-  upb_inttable_uninit(&method->dispatch);
-  upb_gfree(method);
-}
-
-static upb_pbdecodermethod *newmethod(const upb_handlers *dest_handlers,
-                                      mgroup *group) {
-  upb_pbdecodermethod *ret = upb_gmalloc(sizeof(*ret));
-  upb_byteshandler_init(&ret->input_handler_);
-
-  ret->group = group;
-  ret->dest_handlers_ = dest_handlers;
-  upb_inttable_init(&ret->dispatch, UPB_CTYPE_UINT64);
-
-  return ret;
-}
-
-const upb_handlers *upb_pbdecodermethod_desthandlers(
-    const upb_pbdecodermethod *m) {
-  return m->dest_handlers_;
-}
-
-const upb_byteshandler *upb_pbdecodermethod_inputhandler(
-    const upb_pbdecodermethod *m) {
-  return &m->input_handler_;
-}
-
-bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m) {
-  return m->is_native_;
-}
-
-
-/* mgroup *********************************************************************/
-
-static void freegroup(mgroup *g) {
-  upb_inttable_iter i;
-
-  upb_inttable_begin(&i, &g->methods);
-  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
-    freemethod(upb_value_getptr(upb_inttable_iter_value(&i)));
-  }
-
-  upb_inttable_uninit(&g->methods);
-  upb_gfree(g->bytecode);
-  upb_gfree(g);
-}
-
-mgroup *newgroup(void) {
-  mgroup *g = upb_gmalloc(sizeof(*g));
-  upb_inttable_init(&g->methods, UPB_CTYPE_PTR);
-  g->bytecode = NULL;
-  g->bytecode_end = NULL;
-  return g;
-}
-
-
-/* bytecode compiler **********************************************************/
-
-/* Data used only at compilation time. */
-typedef struct {
-  mgroup *group;
-
-  uint32_t *pc;
-  int fwd_labels[MAXLABEL];
-  int back_labels[MAXLABEL];
-
-  /* For fields marked "lazy", parse them lazily or eagerly? */
-  bool lazy;
-} compiler;
-
-static compiler *newcompiler(mgroup *group, bool lazy) {
-  compiler *ret = upb_gmalloc(sizeof(*ret));
-  int i;
-
-  ret->group = group;
-  ret->lazy = lazy;
-  for (i = 0; i < MAXLABEL; i++) {
-    ret->fwd_labels[i] = EMPTYLABEL;
-    ret->back_labels[i] = EMPTYLABEL;
-  }
-  return ret;
-}
-
-static void freecompiler(compiler *c) {
-  upb_gfree(c);
-}
-
-const size_t ptr_words = sizeof(void*) / sizeof(uint32_t);
-
-/* How many words an instruction is. */
-static int instruction_len(uint32_t instr) {
-  switch (getop(instr)) {
-    case OP_SETDISPATCH: return 1 + ptr_words;
-    case OP_TAGN: return 3;
-    case OP_SETBIGGROUPNUM: return 2;
-    default: return 1;
-  }
-}
-
-bool op_has_longofs(int32_t instruction) {
-  switch (getop(instruction)) {
-    case OP_CALL:
-    case OP_BRANCH:
-    case OP_CHECKDELIM:
-      return true;
-    /* The "tag" instructions only have 8 bytes available for the jump target,
-     * but that is ok because these opcodes only require short jumps. */
-    case OP_TAG1:
-    case OP_TAG2:
-    case OP_TAGN:
-      return false;
-    default:
-      UPB_ASSERT(false);
-      return false;
-  }
-}
-
-static int32_t getofs(uint32_t instruction) {
-  if (op_has_longofs(instruction)) {
-    return (int32_t)instruction >> 8;
-  } else {
-    return (int8_t)(instruction >> 8);
-  }
-}
-
-static void setofs(uint32_t *instruction, int32_t ofs) {
-  if (op_has_longofs(*instruction)) {
-    *instruction = getop(*instruction) | (uint32_t)ofs << 8;
-  } else {
-    *instruction = (*instruction & ~0xff00) | ((ofs & 0xff) << 8);
-  }
-  UPB_ASSERT(getofs(*instruction) == ofs);  /* Would fail in cases of overflow. */
-}
-
-static uint32_t pcofs(compiler *c) {
-  return (uint32_t)(c->pc - c->group->bytecode);
-}
-
-/* Defines a local label at the current PC location.  All previous forward
- * references are updated to point to this location.  The location is noted
- * for any future backward references. */
-static void label(compiler *c, unsigned int label) {
-  int val;
-  uint32_t *codep;
-
-  UPB_ASSERT(label < MAXLABEL);
-  val = c->fwd_labels[label];
-  codep = (val == EMPTYLABEL) ? NULL : c->group->bytecode + val;
-  while (codep) {
-    int ofs = getofs(*codep);
-    setofs(codep, (int32_t)(c->pc - codep - instruction_len(*codep)));
-    codep = ofs ? codep + ofs : NULL;
-  }
-  c->fwd_labels[label] = EMPTYLABEL;
-  c->back_labels[label] = pcofs(c);
-}
-
-/* Creates a reference to a numbered label; either a forward reference
- * (positive arg) or backward reference (negative arg).  For forward references
- * the value returned now is actually a "next" pointer into a linked list of all
- * instructions that use this label and will be patched later when the label is
- * defined with label().
- *
- * The returned value is the offset that should be written into the instruction.
- */
-static int32_t labelref(compiler *c, int label) {
-  UPB_ASSERT(label < MAXLABEL);
-  if (label == LABEL_DISPATCH) {
-    /* No resolving required. */
-    return 0;
-  } else if (label < 0) {
-    /* Backward local label.  Relative to the next instruction. */
-    uint32_t from = (uint32_t)((c->pc + 1) - c->group->bytecode);
-    return c->back_labels[-label] - from;
-  } else {
-    /* Forward local label: prepend to (possibly-empty) linked list. */
-    int *lptr = &c->fwd_labels[label];
-    int32_t ret = (*lptr == EMPTYLABEL) ? 0 : *lptr - pcofs(c);
-    *lptr = pcofs(c);
-    return ret;
-  }
-}
-
-static void put32(compiler *c, uint32_t v) {
-  mgroup *g = c->group;
-  if (c->pc == g->bytecode_end) {
-    int ofs = pcofs(c);
-    size_t oldsize = g->bytecode_end - g->bytecode;
-    size_t newsize = UPB_MAX(oldsize * 2, 64);
-    /* TODO(haberman): handle OOM. */
-    g->bytecode = upb_grealloc(g->bytecode, oldsize * sizeof(uint32_t),
-                                            newsize * sizeof(uint32_t));
-    g->bytecode_end = g->bytecode + newsize;
-    c->pc = g->bytecode + ofs;
-  }
-  *c->pc++ = v;
-}
-
-static void putop(compiler *c, int op, ...) {
-  va_list ap;
-  va_start(ap, op);
-
-  switch (op) {
-    case OP_SETDISPATCH: {
-      uintptr_t ptr = (uintptr_t)va_arg(ap, void*);
-      put32(c, OP_SETDISPATCH);
-      put32(c, (uint32_t)ptr);
-      if (sizeof(uintptr_t) > sizeof(uint32_t))
-        put32(c, (uint64_t)ptr >> 32);
-      break;
-    }
-    case OP_STARTMSG:
-    case OP_ENDMSG:
-    case OP_PUSHLENDELIM:
-    case OP_POP:
-    case OP_SETDELIM:
-    case OP_HALT:
-    case OP_RET:
-    case OP_DISPATCH:
-      put32(c, op);
-      break;
-    case OP_PARSE_DOUBLE:
-    case OP_PARSE_FLOAT:
-    case OP_PARSE_INT64:
-    case OP_PARSE_UINT64:
-    case OP_PARSE_INT32:
-    case OP_PARSE_FIXED64:
-    case OP_PARSE_FIXED32:
-    case OP_PARSE_BOOL:
-    case OP_PARSE_UINT32:
-    case OP_PARSE_SFIXED32:
-    case OP_PARSE_SFIXED64:
-    case OP_PARSE_SINT32:
-    case OP_PARSE_SINT64:
-    case OP_STARTSEQ:
-    case OP_ENDSEQ:
-    case OP_STARTSUBMSG:
-    case OP_ENDSUBMSG:
-    case OP_STARTSTR:
-    case OP_STRING:
-    case OP_ENDSTR:
-    case OP_PUSHTAGDELIM:
-      put32(c, op | va_arg(ap, upb_selector_t) << 8);
-      break;
-    case OP_SETBIGGROUPNUM:
-      put32(c, op);
-      put32(c, va_arg(ap, int));
-      break;
-    case OP_CALL: {
-      const upb_pbdecodermethod *method = va_arg(ap, upb_pbdecodermethod *);
-      put32(c, op | (method->code_base.ofs - (pcofs(c) + 1)) << 8);
-      break;
-    }
-    case OP_CHECKDELIM:
-    case OP_BRANCH: {
-      uint32_t instruction = op;
-      int label = va_arg(ap, int);
-      setofs(&instruction, labelref(c, label));
-      put32(c, instruction);
-      break;
-    }
-    case OP_TAG1:
-    case OP_TAG2: {
-      int label = va_arg(ap, int);
-      uint64_t tag = va_arg(ap, uint64_t);
-      uint32_t instruction = (uint32_t)(op | (tag << 16));
-      UPB_ASSERT(tag <= 0xffff);
-      setofs(&instruction, labelref(c, label));
-      put32(c, instruction);
-      break;
-    }
-    case OP_TAGN: {
-      int label = va_arg(ap, int);
-      uint64_t tag = va_arg(ap, uint64_t);
-      uint32_t instruction = op | (upb_value_size(tag) << 16);
-      setofs(&instruction, labelref(c, label));
-      put32(c, instruction);
-      put32(c, (uint32_t)tag);
-      put32(c, tag >> 32);
-      break;
-    }
-  }
-
-  va_end(ap);
-}
-
-#if defined(UPB_DUMP_BYTECODE)
-
-const char *upb_pbdecoder_getopname(unsigned int op) {
-#define QUOTE(x) #x
-#define EXPAND_AND_QUOTE(x) QUOTE(x)
-#define OPNAME(x) OP_##x
-#define OP(x) case OPNAME(x): return EXPAND_AND_QUOTE(OPNAME(x));
-#define T(x) OP(PARSE_##x)
-  /* Keep in sync with list in decoder.int.h. */
-  switch ((opcode)op) {
-    T(DOUBLE) T(FLOAT) T(INT64) T(UINT64) T(INT32) T(FIXED64) T(FIXED32)
-    T(BOOL) T(UINT32) T(SFIXED32) T(SFIXED64) T(SINT32) T(SINT64)
-    OP(STARTMSG) OP(ENDMSG) OP(STARTSEQ) OP(ENDSEQ) OP(STARTSUBMSG)
-    OP(ENDSUBMSG) OP(STARTSTR) OP(STRING) OP(ENDSTR) OP(CALL) OP(RET)
-    OP(PUSHLENDELIM) OP(PUSHTAGDELIM) OP(SETDELIM) OP(CHECKDELIM)
-    OP(BRANCH) OP(TAG1) OP(TAG2) OP(TAGN) OP(SETDISPATCH) OP(POP)
-    OP(SETBIGGROUPNUM) OP(DISPATCH) OP(HALT)
-  }
-  return "<unknown op>";
-#undef OP
-#undef T
-}
-
-#endif
-
-#ifdef UPB_DUMP_BYTECODE
-
-static void dumpbc(uint32_t *p, uint32_t *end, FILE *f) {
-
-  uint32_t *begin = p;
-
-  while (p < end) {
-    fprintf(f, "%p  %8tx", p, p - begin);
-    uint32_t instr = *p++;
-    uint8_t op = getop(instr);
-    fprintf(f, " %s", upb_pbdecoder_getopname(op));
-    switch ((opcode)op) {
-      case OP_SETDISPATCH: {
-        const upb_inttable *dispatch;
-        memcpy(&dispatch, p, sizeof(void*));
-        p += ptr_words;
-        const upb_pbdecodermethod *method =
-            (void *)((char *)dispatch -
-                     offsetof(upb_pbdecodermethod, dispatch));
-        fprintf(f, " %s", upb_msgdef_fullname(
-                              upb_handlers_msgdef(method->dest_handlers_)));
-        break;
-      }
-      case OP_DISPATCH:
-      case OP_STARTMSG:
-      case OP_ENDMSG:
-      case OP_PUSHLENDELIM:
-      case OP_POP:
-      case OP_SETDELIM:
-      case OP_HALT:
-      case OP_RET:
-        break;
-      case OP_PARSE_DOUBLE:
-      case OP_PARSE_FLOAT:
-      case OP_PARSE_INT64:
-      case OP_PARSE_UINT64:
-      case OP_PARSE_INT32:
-      case OP_PARSE_FIXED64:
-      case OP_PARSE_FIXED32:
-      case OP_PARSE_BOOL:
-      case OP_PARSE_UINT32:
-      case OP_PARSE_SFIXED32:
-      case OP_PARSE_SFIXED64:
-      case OP_PARSE_SINT32:
-      case OP_PARSE_SINT64:
-      case OP_STARTSEQ:
-      case OP_ENDSEQ:
-      case OP_STARTSUBMSG:
-      case OP_ENDSUBMSG:
-      case OP_STARTSTR:
-      case OP_STRING:
-      case OP_ENDSTR:
-      case OP_PUSHTAGDELIM:
-        fprintf(f, " %d", instr >> 8);
-        break;
-      case OP_SETBIGGROUPNUM:
-        fprintf(f, " %d", *p++);
-        break;
-      case OP_CHECKDELIM:
-      case OP_CALL:
-      case OP_BRANCH:
-        fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
-        break;
-      case OP_TAG1:
-      case OP_TAG2: {
-        fprintf(f, " tag:0x%x", instr >> 16);
-        if (getofs(instr)) {
-          fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
-        }
-        break;
-      }
-      case OP_TAGN: {
-        uint64_t tag = *p++;
-        tag |= (uint64_t)*p++ << 32;
-        fprintf(f, " tag:0x%llx", (long long)tag);
-        fprintf(f, " n:%d", instr >> 16);
-        if (getofs(instr)) {
-          fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
-        }
-        break;
-      }
-    }
-    fputs("\n", f);
-  }
-}
-
-#endif
-
-static uint64_t get_encoded_tag(const upb_fielddef *f, int wire_type) {
-  uint32_t tag = (upb_fielddef_number(f) << 3) | wire_type;
-  uint64_t encoded_tag = upb_vencode32(tag);
-  /* No tag should be greater than 5 bytes. */
-  UPB_ASSERT(encoded_tag <= 0xffffffffff);
-  return encoded_tag;
-}
-
-static void putchecktag(compiler *c, const upb_fielddef *f,
-                        int wire_type, int dest) {
-  uint64_t tag = get_encoded_tag(f, wire_type);
-  switch (upb_value_size(tag)) {
-    case 1:
-      putop(c, OP_TAG1, dest, tag);
-      break;
-    case 2:
-      putop(c, OP_TAG2, dest, tag);
-      break;
-    default:
-      putop(c, OP_TAGN, dest, tag);
-      break;
-  }
-}
-
-static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
-  upb_selector_t selector;
-  bool ok = upb_handlers_getselector(f, type, &selector);
-  UPB_ASSERT(ok);
-  return selector;
-}
-
-/* Takes an existing, primary dispatch table entry and repacks it with a
- * different alternate wire type.  Called when we are inserting a secondary
- * dispatch table entry for an alternate wire type. */
-static uint64_t repack(uint64_t dispatch, int new_wt2) {
-  uint64_t ofs;
-  uint8_t wt1;
-  uint8_t old_wt2;
-  upb_pbdecoder_unpackdispatch(dispatch, &ofs, &wt1, &old_wt2);
-  UPB_ASSERT(old_wt2 == NO_WIRE_TYPE);  /* wt2 should not be set yet. */
-  return upb_pbdecoder_packdispatch(ofs, wt1, new_wt2);
-}
-
-/* Marks the current bytecode position as the dispatch target for this message,
- * field, and wire type. */
-static void dispatchtarget(compiler *c, upb_pbdecodermethod *method,
-                           const upb_fielddef *f, int wire_type) {
-  /* Offset is relative to msg base. */
-  uint64_t ofs = pcofs(c) - method->code_base.ofs;
-  uint32_t fn = upb_fielddef_number(f);
-  upb_inttable *d = &method->dispatch;
-  upb_value v;
-  if (upb_inttable_remove(d, fn, &v)) {
-    /* TODO: prioritize based on packed setting in .proto file. */
-    uint64_t repacked = repack(upb_value_getuint64(v), wire_type);
-    upb_inttable_insert(d, fn, upb_value_uint64(repacked));
-    upb_inttable_insert(d, fn + UPB_MAX_FIELDNUMBER, upb_value_uint64(ofs));
-  } else {
-    uint64_t val = upb_pbdecoder_packdispatch(ofs, wire_type, NO_WIRE_TYPE);
-    upb_inttable_insert(d, fn, upb_value_uint64(val));
-  }
-}
-
-static void putpush(compiler *c, const upb_fielddef *f) {
-  if (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE) {
-    putop(c, OP_PUSHLENDELIM);
-  } else {
-    uint32_t fn = upb_fielddef_number(f);
-    if (fn >= 1 << 24) {
-      putop(c, OP_PUSHTAGDELIM, 0);
-      putop(c, OP_SETBIGGROUPNUM, fn);
-    } else {
-      putop(c, OP_PUSHTAGDELIM, fn);
-    }
-  }
-}
-
-static upb_pbdecodermethod *find_submethod(const compiler *c,
-                                           const upb_pbdecodermethod *method,
-                                           const upb_fielddef *f) {
-  const upb_handlers *sub =
-      upb_handlers_getsubhandlers(method->dest_handlers_, f);
-  upb_value v;
-  return upb_inttable_lookupptr(&c->group->methods, sub, &v)
-             ? upb_value_getptr(v)
-             : NULL;
-}
-
-static void putsel(compiler *c, opcode op, upb_selector_t sel,
-                   const upb_handlers *h) {
-  if (upb_handlers_gethandler(h, sel, NULL)) {
-    putop(c, op, sel);
-  }
-}
-
-/* Puts an opcode to call a callback, but only if a callback actually exists for
- * this field and handler type. */
-static void maybeput(compiler *c, opcode op, const upb_handlers *h,
-                     const upb_fielddef *f, upb_handlertype_t type) {
-  putsel(c, op, getsel(f, type), h);
-}
-
-static bool haslazyhandlers(const upb_handlers *h, const upb_fielddef *f) {
-  if (!upb_fielddef_lazy(f))
-    return false;
-
-  return upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STARTSTR), NULL) ||
-         upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STRING), NULL) ||
-         upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_ENDSTR), NULL);
-}
-
-
-/* bytecode compiler code generation ******************************************/
-
-/* Symbolic names for our local labels. */
-#define LABEL_LOOPSTART 1  /* Top of a repeated field loop. */
-#define LABEL_LOOPBREAK 2  /* To jump out of a repeated loop */
-#define LABEL_FIELD     3  /* Jump backward to find the most recent field. */
-#define LABEL_ENDMSG    4  /* To reach the OP_ENDMSG instr for this msg. */
-
-/* Generates bytecode to parse a single non-lazy message field. */
-static void generate_msgfield(compiler *c, const upb_fielddef *f,
-                              upb_pbdecodermethod *method) {
-  const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
-  const upb_pbdecodermethod *sub_m = find_submethod(c, method, f);
-  int wire_type;
-
-  if (!sub_m) {
-    /* Don't emit any code for this field at all; it will be parsed as an
-     * unknown field.
-     *
-     * TODO(haberman): we should change this to parse it as a string field
-     * instead.  It will probably be faster, but more importantly, once we
-     * start vending unknown fields, a field shouldn't be treated as unknown
-     * just because it doesn't have subhandlers registered. */
-    return;
-  }
-
-  label(c, LABEL_FIELD);
-
-  wire_type =
-      (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE)
-          ? UPB_WIRE_TYPE_DELIMITED
-          : UPB_WIRE_TYPE_START_GROUP;
-
-  if (upb_fielddef_isseq(f)) {
-    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
-    putchecktag(c, f, wire_type, LABEL_DISPATCH);
-   dispatchtarget(c, method, f, wire_type);
-    putop(c, OP_PUSHTAGDELIM, 0);
-    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));
-   label(c, LABEL_LOOPSTART);
-    putpush(c, f);
-    putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG));
-    putop(c, OP_CALL, sub_m);
-    putop(c, OP_POP);
-    maybeput(c, OP_ENDSUBMSG, h, f, UPB_HANDLER_ENDSUBMSG);
-    if (wire_type == UPB_WIRE_TYPE_DELIMITED) {
-      putop(c, OP_SETDELIM);
-    }
-    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
-    putchecktag(c, f, wire_type, LABEL_LOOPBREAK);
-    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
-   label(c, LABEL_LOOPBREAK);
-    putop(c, OP_POP);
-    maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
-  } else {
-    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
-    putchecktag(c, f, wire_type, LABEL_DISPATCH);
-   dispatchtarget(c, method, f, wire_type);
-    putpush(c, f);
-    putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG));
-    putop(c, OP_CALL, sub_m);
-    putop(c, OP_POP);
-    maybeput(c, OP_ENDSUBMSG, h, f, UPB_HANDLER_ENDSUBMSG);
-    if (wire_type == UPB_WIRE_TYPE_DELIMITED) {
-      putop(c, OP_SETDELIM);
-    }
-  }
-}
-
-/* Generates bytecode to parse a single string or lazy submessage field. */
-static void generate_delimfield(compiler *c, const upb_fielddef *f,
-                                upb_pbdecodermethod *method) {
-  const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
-
-  label(c, LABEL_FIELD);
-  if (upb_fielddef_isseq(f)) {
-    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
-    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
-   dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
-    putop(c, OP_PUSHTAGDELIM, 0);
-    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));
-   label(c, LABEL_LOOPSTART);
-    putop(c, OP_PUSHLENDELIM);
-    putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR));
-    /* Need to emit even if no handler to skip past the string. */
-    putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING));
-    maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR);
-    putop(c, OP_POP);
-    putop(c, OP_SETDELIM);
-    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
-    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_LOOPBREAK);
-    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
-   label(c, LABEL_LOOPBREAK);
-    putop(c, OP_POP);
-    maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
-  } else {
-    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
-    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
-   dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
-    putop(c, OP_PUSHLENDELIM);
-    putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR));
-    putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING));
-    maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR);
-    putop(c, OP_POP);
-    putop(c, OP_SETDELIM);
-  }
-}
-
-/* Generates bytecode to parse a single primitive field. */
-static void generate_primitivefield(compiler *c, const upb_fielddef *f,
-                                    upb_pbdecodermethod *method) {
-  const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
-  upb_descriptortype_t descriptor_type = upb_fielddef_descriptortype(f);
-  opcode parse_type;
-  upb_selector_t sel;
-  int wire_type;
-
-  label(c, LABEL_FIELD);
-
-  /* From a decoding perspective, ENUM is the same as INT32. */
-  if (descriptor_type == UPB_DESCRIPTOR_TYPE_ENUM)
-    descriptor_type = UPB_DESCRIPTOR_TYPE_INT32;
-
-  parse_type = (opcode)descriptor_type;
-
-  /* TODO(haberman): generate packed or non-packed first depending on "packed"
-   * setting in the fielddef.  This will favor (in speed) whichever was
-   * specified. */
-
-  UPB_ASSERT((int)parse_type >= 0 && parse_type <= OP_MAX);
-  sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
-  wire_type = upb_pb_native_wire_types[upb_fielddef_descriptortype(f)];
-  if (upb_fielddef_isseq(f)) {
-    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
-    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
-   dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
-    putop(c, OP_PUSHLENDELIM);
-    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));  /* Packed */
-   label(c, LABEL_LOOPSTART);
-    putop(c, parse_type, sel);
-    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
-    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
-   dispatchtarget(c, method, f, wire_type);
-    putop(c, OP_PUSHTAGDELIM, 0);
-    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));  /* Non-packed */
-   label(c, LABEL_LOOPSTART);
-    putop(c, parse_type, sel);
-    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
-    putchecktag(c, f, wire_type, LABEL_LOOPBREAK);
-    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
-   label(c, LABEL_LOOPBREAK);
-    putop(c, OP_POP);  /* Packed and non-packed join. */
-    maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
-    putop(c, OP_SETDELIM);  /* Could remove for non-packed by dup ENDSEQ. */
-  } else {
-    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
-    putchecktag(c, f, wire_type, LABEL_DISPATCH);
-   dispatchtarget(c, method, f, wire_type);
-    putop(c, parse_type, sel);
-  }
-}
-
-/* Adds bytecode for parsing the given message to the given decoderplan,
- * while adding all dispatch targets to this message's dispatch table. */
-static void compile_method(compiler *c, upb_pbdecodermethod *method) {
-  const upb_handlers *h;
-  const upb_msgdef *md;
-  uint32_t* start_pc;
-  upb_msg_field_iter i;
-  upb_value val;
-
-  UPB_ASSERT(method);
-
-  /* Clear all entries in the dispatch table. */
-  upb_inttable_uninit(&method->dispatch);
-  upb_inttable_init(&method->dispatch, UPB_CTYPE_UINT64);
-
-  h = upb_pbdecodermethod_desthandlers(method);
-  md = upb_handlers_msgdef(h);
-
- method->code_base.ofs = pcofs(c);
-  putop(c, OP_SETDISPATCH, &method->dispatch);
-  putsel(c, OP_STARTMSG, UPB_STARTMSG_SELECTOR, h);
- label(c, LABEL_FIELD);
-  start_pc = c->pc;
-  for(upb_msg_field_begin(&i, md);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    const upb_fielddef *f = upb_msg_iter_field(&i);
-    upb_fieldtype_t type = upb_fielddef_type(f);
-
-    if (type == UPB_TYPE_MESSAGE && !(haslazyhandlers(h, f) && c->lazy)) {
-      generate_msgfield(c, f, method);
-    } else if (type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES ||
-               type == UPB_TYPE_MESSAGE) {
-      generate_delimfield(c, f, method);
-    } else {
-      generate_primitivefield(c, f, method);
-    }
-  }
-
-  /* If there were no fields, or if no handlers were defined, we need to
-   * generate a non-empty loop body so that we can at least dispatch for unknown
-   * fields and check for the end of the message. */
-  if (c->pc == start_pc) {
-    /* Check for end-of-message. */
-    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
-    /* Unconditionally dispatch. */
-    putop(c, OP_DISPATCH, 0);
-  }
-
-  /* For now we just loop back to the last field of the message (or if none,
-   * the DISPATCH opcode for the message). */
-  putop(c, OP_BRANCH, -LABEL_FIELD);
-
-  /* Insert both a label and a dispatch table entry for this end-of-msg. */
- label(c, LABEL_ENDMSG);
-  val = upb_value_uint64(pcofs(c) - method->code_base.ofs);
-  upb_inttable_insert(&method->dispatch, DISPATCH_ENDMSG, val);
-
-  putsel(c, OP_ENDMSG, UPB_ENDMSG_SELECTOR, h);
-  putop(c, OP_RET);
-
-  upb_inttable_compact(&method->dispatch);
-}
-
-/* Populate "methods" with new upb_pbdecodermethod objects reachable from "h".
- * Returns the method for these handlers.
- *
- * Generates a new method for every destination handlers reachable from "h". */
-static void find_methods(compiler *c, const upb_handlers *h) {
-  upb_value v;
-  upb_msg_field_iter i;
-  const upb_msgdef *md;
-  upb_pbdecodermethod *method;
-
-  if (upb_inttable_lookupptr(&c->group->methods, h, &v))
-    return;
-
-  method = newmethod(h, c->group);
-  upb_inttable_insertptr(&c->group->methods, h, upb_value_ptr(method));
-
-  /* Find submethods. */
-  md = upb_handlers_msgdef(h);
-  for(upb_msg_field_begin(&i, md);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    const upb_fielddef *f = upb_msg_iter_field(&i);
-    const upb_handlers *sub_h;
-    if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE &&
-        (sub_h = upb_handlers_getsubhandlers(h, f)) != NULL) {
-      /* We only generate a decoder method for submessages with handlers.
-       * Others will be parsed as unknown fields. */
-      find_methods(c, sub_h);
-    }
-  }
-}
-
-/* (Re-)compile bytecode for all messages in "msgs."
- * Overwrites any existing bytecode in "c". */
-static void compile_methods(compiler *c) {
-  upb_inttable_iter i;
-
-  /* Start over at the beginning of the bytecode. */
-  c->pc = c->group->bytecode;
-
-  upb_inttable_begin(&i, &c->group->methods);
-  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
-    upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i));
-    compile_method(c, method);
-  }
-}
-
-static void set_bytecode_handlers(mgroup *g) {
-  upb_inttable_iter i;
-  upb_inttable_begin(&i, &g->methods);
-  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
-    upb_pbdecodermethod *m = upb_value_getptr(upb_inttable_iter_value(&i));
-    upb_byteshandler *h = &m->input_handler_;
-
-    m->code_base.ptr = g->bytecode + m->code_base.ofs;
-
-    upb_byteshandler_setstartstr(h, upb_pbdecoder_startbc, m->code_base.ptr);
-    upb_byteshandler_setstring(h, upb_pbdecoder_decode, g);
-    upb_byteshandler_setendstr(h, upb_pbdecoder_end, m);
-  }
-}
-
-
-/* TODO(haberman): allow this to be constructed for an arbitrary set of dest
- * handlers and other mgroups (but verify we have a transitive closure). */
-const mgroup *mgroup_new(const upb_handlers *dest, bool lazy) {
-  mgroup *g;
-  compiler *c;
-
-  g = newgroup();
-  c = newcompiler(g, lazy);
-  find_methods(c, dest);
-
-  /* We compile in two passes:
-   * 1. all messages are assigned relative offsets from the beginning of the
-   *    bytecode (saved in method->code_base).
-   * 2. forwards OP_CALL instructions can be correctly linked since message
-   *    offsets have been previously assigned.
-   *
-   * Could avoid the second pass by linking OP_CALL instructions somehow. */
-  compile_methods(c);
-  compile_methods(c);
-  g->bytecode_end = c->pc;
-  freecompiler(c);
-
-#ifdef UPB_DUMP_BYTECODE
-  {
-    FILE *f = fopen("/tmp/upb-bytecode", "w");
-    UPB_ASSERT(f);
-    dumpbc(g->bytecode, g->bytecode_end, stderr);
-    dumpbc(g->bytecode, g->bytecode_end, f);
-    fclose(f);
-
-    f = fopen("/tmp/upb-bytecode.bin", "wb");
-    UPB_ASSERT(f);
-    fwrite(g->bytecode, 1, g->bytecode_end - g->bytecode, f);
-    fclose(f);
-  }
-#endif
-
-  set_bytecode_handlers(g);
-  return g;
-}
-
-
-/* upb_pbcodecache ************************************************************/
-
-upb_pbcodecache *upb_pbcodecache_new(upb_handlercache *dest) {
-  upb_pbcodecache *c = upb_gmalloc(sizeof(*c));
-
-  if (!c) return NULL;
-
-  c->dest = dest;
-  c->lazy = false;
-
-  c->arena = upb_arena_new();
-  if (!upb_inttable_init(&c->groups, UPB_CTYPE_CONSTPTR)) return NULL;
-
-  return c;
-}
-
-void upb_pbcodecache_free(upb_pbcodecache *c) {
-  upb_inttable_iter i;
-
-  upb_inttable_begin(&i, &c->groups);
-  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
-    upb_value val = upb_inttable_iter_value(&i);
-    freegroup((void*)upb_value_getconstptr(val));
-  }
-
-  upb_inttable_uninit(&c->groups);
-  upb_arena_free(c->arena);
-  upb_gfree(c);
-}
-
-void upb_pbdecodermethodopts_setlazy(upb_pbcodecache *c, bool lazy) {
-  UPB_ASSERT(upb_inttable_count(&c->groups) == 0);
-  c->lazy = lazy;
-}
-
-const upb_pbdecodermethod *upb_pbcodecache_get(upb_pbcodecache *c,
-                                               const upb_msgdef *md) {
-  upb_value v;
-  bool ok;
-  const upb_handlers *h;
-  const mgroup *g;
-
-  h = upb_handlercache_get(c->dest, md);
-  if (upb_inttable_lookupptr(&c->groups, md, &v)) {
-    g = upb_value_getconstptr(v);
-  } else {
-    g = mgroup_new(h, c->lazy);
-    ok = upb_inttable_insertptr(&c->groups, md, upb_value_constptr(g));
-    UPB_ASSUME(ok);
-  }
-
-  ok = upb_inttable_lookupptr(&g->methods, h, &v);
-  UPB_ASSUME(ok);
-  return upb_value_getptr(v);
-}
-/*
-** upb::Decoder (Bytecode Decoder VM)
-**
-** Bytecode must previously have been generated using the bytecode compiler in
-** compile_decoder.c.  This decoder then walks through the bytecode op-by-op to
-** parse the input.
-**
-** Decoding is fully resumable; we just keep a pointer to the current bytecode
-** instruction and resume from there.  A fair amount of the logic here is to
-** handle the fact that values can span buffer seams and we have to be able to
-** be capable of suspending/resuming from any byte in the stream.  This
-** sometimes requires keeping a few trailing bytes from the last buffer around
-** in the "residual" buffer.
-*/
-
-#include <inttypes.h>
-#include <stddef.h>
-
-#ifdef UPB_DUMP_BYTECODE
-#include <stdio.h>
-#endif
-
-
-#define CHECK_SUSPEND(x) if (!(x)) return upb_pbdecoder_suspend(d);
-
-/* Error messages that are shared between the bytecode and JIT decoders. */
-const char *kPbDecoderStackOverflow = "Nesting too deep.";
-const char *kPbDecoderSubmessageTooLong =
-    "Submessage end extends past enclosing submessage.";
-
-/* Error messages shared within this file. */
-static const char *kUnterminatedVarint = "Unterminated varint.";
-
-/* upb_pbdecoder **************************************************************/
-
-static opcode halt = OP_HALT;
-
-/* A dummy character we can point to when the user passes us a NULL buffer.
- * We need this because in C (NULL + 0) and (NULL - NULL) are undefined
- * behavior, which would invalidate functions like curbufleft(). */
-static const char dummy_char;
-
-/* Whether an op consumes any of the input buffer. */
-static bool consumes_input(opcode op) {
-  switch (op) {
-    case OP_SETDISPATCH:
-    case OP_STARTMSG:
-    case OP_ENDMSG:
-    case OP_STARTSEQ:
-    case OP_ENDSEQ:
-    case OP_STARTSUBMSG:
-    case OP_ENDSUBMSG:
-    case OP_STARTSTR:
-    case OP_ENDSTR:
-    case OP_PUSHTAGDELIM:
-    case OP_POP:
-    case OP_SETDELIM:
-    case OP_SETBIGGROUPNUM:
-    case OP_CHECKDELIM:
-    case OP_CALL:
-    case OP_RET:
-    case OP_BRANCH:
-      return false;
-    default:
-      return true;
-  }
-}
-
-static size_t stacksize(upb_pbdecoder *d, size_t entries) {
-  UPB_UNUSED(d);
-  return entries * sizeof(upb_pbdecoder_frame);
-}
-
-static size_t callstacksize(upb_pbdecoder *d, size_t entries) {
-  UPB_UNUSED(d);
-
-  return entries * sizeof(uint32_t*);
-}
-
-
-static bool in_residual_buf(const upb_pbdecoder *d, const char *p);
-
-/* It's unfortunate that we have to micro-manage the compiler with
- * UPB_FORCEINLINE and UPB_NOINLINE, especially since this tuning is necessarily
- * specific to one hardware configuration.  But empirically on a Core i7,
- * performance increases 30-50% with these annotations.  Every instance where
- * these appear, gcc 4.2.1 made the wrong decision and degraded performance in
- * benchmarks. */
-
-static void seterr(upb_pbdecoder *d, const char *msg) {
-  upb_status_seterrmsg(d->status, msg);
-}
-
-void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg) {
-  seterr(d, msg);
-}
-
-
-/* Buffering ******************************************************************/
-
-/* We operate on one buffer at a time, which is either the user's buffer passed
- * to our "decode" callback or some residual bytes from the previous buffer. */
-
-/* How many bytes can be safely read from d->ptr without reading past end-of-buf
- * or past the current delimited end. */
-static size_t curbufleft(const upb_pbdecoder *d) {
-  UPB_ASSERT(d->data_end >= d->ptr);
-  return d->data_end - d->ptr;
-}
-
-/* How many bytes are available before end-of-buffer. */
-static size_t bufleft(const upb_pbdecoder *d) {
-  return d->end - d->ptr;
-}
-
-/* Overall stream offset of d->ptr. */
-uint64_t offset(const upb_pbdecoder *d) {
-  return d->bufstart_ofs + (d->ptr - d->buf);
-}
-
-/* How many bytes are available before the end of this delimited region. */
-size_t delim_remaining(const upb_pbdecoder *d) {
-  return d->top->end_ofs - offset(d);
-}
-
-/* Advances d->ptr. */
-static void advance(upb_pbdecoder *d, size_t len) {
-  UPB_ASSERT(curbufleft(d) >= len);
-  d->ptr += len;
-}
-
-static bool in_buf(const char *p, const char *buf, const char *end) {
-  return p >= buf && p <= end;
-}
-
-static bool in_residual_buf(const upb_pbdecoder *d, const char *p) {
-  return in_buf(p, d->residual, d->residual_end);
-}
-
-/* Calculates the delim_end value, which is affected by both the current buffer
- * and the parsing stack, so must be called whenever either is updated. */
-static void set_delim_end(upb_pbdecoder *d) {
-  size_t delim_ofs = d->top->end_ofs - d->bufstart_ofs;
-  if (delim_ofs <= (size_t)(d->end - d->buf)) {
-    d->delim_end = d->buf + delim_ofs;
-    d->data_end = d->delim_end;
-  } else {
-    d->data_end = d->end;
-    d->delim_end = NULL;
-  }
-}
-
-static void switchtobuf(upb_pbdecoder *d, const char *buf, const char *end) {
-  d->ptr = buf;
-  d->buf = buf;
-  d->end = end;
-  set_delim_end(d);
-}
-
-static void advancetobuf(upb_pbdecoder *d, const char *buf, size_t len) {
-  UPB_ASSERT(curbufleft(d) == 0);
-  d->bufstart_ofs += (d->end - d->buf);
-  switchtobuf(d, buf, buf + len);
-}
-
-static void checkpoint(upb_pbdecoder *d) {
-  /* The assertion here is in the interests of efficiency, not correctness.
-   * We are trying to ensure that we don't checkpoint() more often than
-   * necessary. */
-  UPB_ASSERT(d->checkpoint != d->ptr);
-  d->checkpoint = d->ptr;
-}
-
-/* Skips "bytes" bytes in the stream, which may be more than available.  If we
- * skip more bytes than are available, we return a long read count to the caller
- * indicating how many bytes can be skipped over before passing actual data
- * again.  Skipped bytes can pass a NULL buffer and the decoder guarantees they
- * won't actually be read.
- */
-static int32_t skip(upb_pbdecoder *d, size_t bytes) {
-  UPB_ASSERT(!in_residual_buf(d, d->ptr) || d->size_param == 0);
-  UPB_ASSERT(d->skip == 0);
-  if (bytes > delim_remaining(d)) {
-    seterr(d, "Skipped value extended beyond enclosing submessage.");
-    return (int32_t)upb_pbdecoder_suspend(d);
-  } else if (bufleft(d) >= bytes) {
-    /* Skipped data is all in current buffer, and more is still available. */
-    advance(d, bytes);
-    d->skip = 0;
-    return DECODE_OK;
-  } else {
-    /* Skipped data extends beyond currently available buffers. */
-    d->pc = d->last;
-    d->skip = bytes - curbufleft(d);
-    d->bufstart_ofs += (d->end - d->buf);
-    d->residual_end = d->residual;
-    switchtobuf(d, d->residual, d->residual_end);
-    return (int32_t)(d->size_param + d->skip);
-  }
-}
-
-
-/* Resumes the decoder from an initial state or from a previous suspend. */
-int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf,
-                             size_t size, const upb_bufhandle *handle) {
-  UPB_UNUSED(p);  /* Useless; just for the benefit of the JIT. */
-
-  /* d->skip and d->residual_end could probably elegantly be represented
-   * as a single variable, to more easily represent this invariant. */
-  UPB_ASSERT(!(d->skip && d->residual_end > d->residual));
-
-  /* We need to remember the original size_param, so that the value we return
-   * is relative to it, even if we do some skipping first. */
-  d->size_param = size;
-  d->handle = handle;
-
-  /* Have to handle this case specially (ie. not with skip()) because the user
-   * is allowed to pass a NULL buffer here, which won't allow us to safely
-   * calculate a d->end or use our normal functions like curbufleft(). */
-  if (d->skip && d->skip >= size) {
-    d->skip -= size;
-    d->bufstart_ofs += size;
-    buf = &dummy_char;
-    size = 0;
-
-    /* We can't just return now, because we might need to execute some ops
-     * like CHECKDELIM, which could call some callbacks and pop the stack. */
-  }
-
-  /* We need to pretend that this was the actual buffer param, since some of the
-   * calculations assume that d->ptr/d->buf is relative to this. */
-  d->buf_param = buf;
-
-  if (!buf) {
-    /* NULL buf is ok if its entire span is covered by the "skip" above, but
-     * by this point we know that "skip" doesn't cover the buffer. */
-    seterr(d, "Passed NULL buffer over non-skippable region.");
-    return (int32_t)upb_pbdecoder_suspend(d);
-  }
-
-  if (d->residual_end > d->residual) {
-    /* We have residual bytes from the last buffer. */
-    UPB_ASSERT(d->ptr == d->residual);
-  } else {
-    switchtobuf(d, buf, buf + size);
-  }
-
-  d->checkpoint = d->ptr;
-
-  /* Handle skips that don't cover the whole buffer (as above). */
-  if (d->skip) {
-    size_t skip_bytes = d->skip;
-    d->skip = 0;
-    CHECK_RETURN(skip(d, skip_bytes));
-    checkpoint(d);
-  }
-
-  /* If we're inside an unknown group, continue to parse unknown values. */
-  if (d->top->groupnum < 0) {
-    CHECK_RETURN(upb_pbdecoder_skipunknown(d, -1, 0));
-    checkpoint(d);
-  }
-
-  return DECODE_OK;
-}
-
-/* Suspends the decoder at the last checkpoint, without saving any residual
- * bytes.  If there are any unconsumed bytes, returns a short byte count. */
-size_t upb_pbdecoder_suspend(upb_pbdecoder *d) {
-  d->pc = d->last;
-  if (d->checkpoint == d->residual) {
-    /* Checkpoint was in residual buf; no user bytes were consumed. */
-    d->ptr = d->residual;
-    return 0;
-  } else {
-    size_t ret = d->size_param - (d->end - d->checkpoint);
-    UPB_ASSERT(!in_residual_buf(d, d->checkpoint));
-    UPB_ASSERT(d->buf == d->buf_param || d->buf == &dummy_char);
-
-    d->bufstart_ofs += (d->checkpoint - d->buf);
-    d->residual_end = d->residual;
-    switchtobuf(d, d->residual, d->residual_end);
-    return ret;
-  }
-}
-
-/* Suspends the decoder at the last checkpoint, and saves any unconsumed
- * bytes in our residual buffer.  This is necessary if we need more user
- * bytes to form a complete value, which might not be contiguous in the
- * user's buffers.  Always consumes all user bytes. */
-static size_t suspend_save(upb_pbdecoder *d) {
-  /* We hit end-of-buffer before we could parse a full value.
-   * Save any unconsumed bytes (if any) to the residual buffer. */
-  d->pc = d->last;
-
-  if (d->checkpoint == d->residual) {
-    /* Checkpoint was in residual buf; append user byte(s) to residual buf. */
-    UPB_ASSERT((d->residual_end - d->residual) + d->size_param <=
-           sizeof(d->residual));
-    if (!in_residual_buf(d, d->ptr)) {
-      d->bufstart_ofs -= (d->residual_end - d->residual);
-    }
-    memcpy(d->residual_end, d->buf_param, d->size_param);
-    d->residual_end += d->size_param;
-  } else {
-    /* Checkpoint was in user buf; old residual bytes not needed. */
-    size_t save;
-    UPB_ASSERT(!in_residual_buf(d, d->checkpoint));
-
-    d->ptr = d->checkpoint;
-    save = curbufleft(d);
-    UPB_ASSERT(save <= sizeof(d->residual));
-    memcpy(d->residual, d->ptr, save);
-    d->residual_end = d->residual + save;
-    d->bufstart_ofs = offset(d);
-  }
-
-  switchtobuf(d, d->residual, d->residual_end);
-  return d->size_param;
-}
-
-/* Copies the next "bytes" bytes into "buf" and advances the stream.
- * Requires that this many bytes are available in the current buffer. */
-UPB_FORCEINLINE static void consumebytes(upb_pbdecoder *d, void *buf,
-                                         size_t bytes) {
-  UPB_ASSERT(bytes <= curbufleft(d));
-  memcpy(buf, d->ptr, bytes);
-  advance(d, bytes);
-}
-
-/* Slow path for getting the next "bytes" bytes, regardless of whether they are
- * available in the current buffer or not.  Returns a status code as described
- * in decoder.int.h. */
-UPB_NOINLINE static int32_t getbytes_slow(upb_pbdecoder *d, void *buf,
-                                          size_t bytes) {
-  const size_t avail = curbufleft(d);
-  consumebytes(d, buf, avail);
-  bytes -= avail;
-  UPB_ASSERT(bytes > 0);
-  if (in_residual_buf(d, d->ptr)) {
-    advancetobuf(d, d->buf_param, d->size_param);
-  }
-  if (curbufleft(d) >= bytes) {
-    consumebytes(d, (char *)buf + avail, bytes);
-    return DECODE_OK;
-  } else if (d->data_end == d->delim_end) {
-    seterr(d, "Submessage ended in the middle of a value or group");
-    return (int32_t)upb_pbdecoder_suspend(d);
-  } else {
-    return (int32_t)suspend_save(d);
-  }
-}
-
-/* Gets the next "bytes" bytes, regardless of whether they are available in the
- * current buffer or not.  Returns a status code as described in decoder.int.h.
- */
-UPB_FORCEINLINE static int32_t getbytes(upb_pbdecoder *d, void *buf,
-                                        size_t bytes) {
-  if (curbufleft(d) >= bytes) {
-    /* Buffer has enough data to satisfy. */
-    consumebytes(d, buf, bytes);
-    return DECODE_OK;
-  } else {
-    return getbytes_slow(d, buf, bytes);
-  }
-}
-
-UPB_NOINLINE static size_t peekbytes_slow(upb_pbdecoder *d, void *buf,
-                                          size_t bytes) {
-  size_t ret = curbufleft(d);
-  memcpy(buf, d->ptr, ret);
-  if (in_residual_buf(d, d->ptr)) {
-    size_t copy = UPB_MIN(bytes - ret, d->size_param);
-    memcpy((char *)buf + ret, d->buf_param, copy);
-    ret += copy;
-  }
-  return ret;
-}
-
-UPB_FORCEINLINE static size_t peekbytes(upb_pbdecoder *d, void *buf,
-                                        size_t bytes) {
-  if (curbufleft(d) >= bytes) {
-    memcpy(buf, d->ptr, bytes);
-    return bytes;
-  } else {
-    return peekbytes_slow(d, buf, bytes);
-  }
-}
-
-
-/* Decoding of wire types *****************************************************/
-
-/* Slow path for decoding a varint from the current buffer position.
- * Returns a status code as described in decoder.int.h. */
-UPB_NOINLINE int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d,
-                                                      uint64_t *u64) {
-  uint8_t byte = 0x80;
-  int bitpos;
-  *u64 = 0;
-  for(bitpos = 0; bitpos < 70 && (byte & 0x80); bitpos += 7) {
-    CHECK_RETURN(getbytes(d, &byte, 1));
-    *u64 |= (uint64_t)(byte & 0x7F) << bitpos;
-  }
-  if(bitpos == 70 && (byte & 0x80)) {
-    seterr(d, kUnterminatedVarint);
-    return (int32_t)upb_pbdecoder_suspend(d);
-  }
-  return DECODE_OK;
-}
-
-/* Decodes a varint from the current buffer position.
- * Returns a status code as described in decoder.int.h. */
-UPB_FORCEINLINE static int32_t decode_varint(upb_pbdecoder *d, uint64_t *u64) {
-  if (curbufleft(d) > 0 && !(*d->ptr & 0x80)) {
-    *u64 = *d->ptr;
-    advance(d, 1);
-    return DECODE_OK;
-  } else if (curbufleft(d) >= 10) {
-    /* Fast case. */
-    upb_decoderet r = upb_vdecode_fast(d->ptr);
-    if (r.p == NULL) {
-      seterr(d, kUnterminatedVarint);
-      return (int32_t)upb_pbdecoder_suspend(d);
-    }
-    advance(d, r.p - d->ptr);
-    *u64 = r.val;
-    return DECODE_OK;
-  } else {
-    /* Slow case -- varint spans buffer seam. */
-    return upb_pbdecoder_decode_varint_slow(d, u64);
-  }
-}
-
-/* Decodes a 32-bit varint from the current buffer position.
- * Returns a status code as described in decoder.int.h. */
-UPB_FORCEINLINE static int32_t decode_v32(upb_pbdecoder *d, uint32_t *u32) {
-  uint64_t u64;
-  int32_t ret = decode_varint(d, &u64);
-  if (ret >= 0) return ret;
-  if (u64 > UINT32_MAX) {
-    seterr(d, "Unterminated 32-bit varint");
-    /* TODO(haberman) guarantee that this function return is >= 0 somehow,
-     * so we know this path will always be treated as error by our caller.
-     * Right now the size_t -> int32_t can overflow and produce negative values.
-     */
-    *u32 = 0;
-    return (int32_t)upb_pbdecoder_suspend(d);
-  }
-  *u32 = (uint32_t)u64;
-  return DECODE_OK;
-}
-
-/* Decodes a fixed32 from the current buffer position.
- * Returns a status code as described in decoder.int.h.
- * TODO: proper byte swapping for big-endian machines. */
-UPB_FORCEINLINE static int32_t decode_fixed32(upb_pbdecoder *d, uint32_t *u32) {
-  return getbytes(d, u32, 4);
-}
-
-/* Decodes a fixed64 from the current buffer position.
- * Returns a status code as described in decoder.int.h.
- * TODO: proper byte swapping for big-endian machines. */
-UPB_FORCEINLINE static int32_t decode_fixed64(upb_pbdecoder *d, uint64_t *u64) {
-  return getbytes(d, u64, 8);
-}
-
-/* Non-static versions of the above functions.
- * These are called by the JIT for fallback paths. */
-int32_t upb_pbdecoder_decode_f32(upb_pbdecoder *d, uint32_t *u32) {
-  return decode_fixed32(d, u32);
-}
-
-int32_t upb_pbdecoder_decode_f64(upb_pbdecoder *d, uint64_t *u64) {
-  return decode_fixed64(d, u64);
-}
-
-static double as_double(uint64_t n) { double d; memcpy(&d, &n, 8); return d; }
-static float  as_float(uint32_t n)  { float  f; memcpy(&f, &n, 4); return f; }
-
-/* Pushes a frame onto the decoder stack. */
-static bool decoder_push(upb_pbdecoder *d, uint64_t end) {
-  upb_pbdecoder_frame *fr = d->top;
-
-  if (end > fr->end_ofs) {
-    seterr(d, kPbDecoderSubmessageTooLong);
-    return false;
-  } else if (fr == d->limit) {
-    seterr(d, kPbDecoderStackOverflow);
-    return false;
-  }
-
-  fr++;
-  fr->end_ofs = end;
-  fr->dispatch = NULL;
-  fr->groupnum = 0;
-  d->top = fr;
-  return true;
-}
-
-static bool pushtagdelim(upb_pbdecoder *d, uint32_t arg) {
-  /* While we expect to see an "end" tag (either ENDGROUP or a non-sequence
-   * field number) prior to hitting any enclosing submessage end, pushing our
-   * existing delim end prevents us from continuing to parse values from a
-   * corrupt proto that doesn't give us an END tag in time. */
-  if (!decoder_push(d, d->top->end_ofs))
-    return false;
-  d->top->groupnum = arg;
-  return true;
-}
-
-/* Pops a frame from the decoder stack. */
-static void decoder_pop(upb_pbdecoder *d) { d->top--; }
-
-UPB_NOINLINE int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d,
-                                                 uint64_t expected) {
-  uint64_t data = 0;
-  size_t bytes = upb_value_size(expected);
-  size_t read = peekbytes(d, &data, bytes);
-  if (read == bytes && data == expected) {
-    /* Advance past matched bytes. */
-    int32_t ok = getbytes(d, &data, read);
-    UPB_ASSERT(ok < 0);
-    return DECODE_OK;
-  } else if (read < bytes && memcmp(&data, &expected, read) == 0) {
-    return (int32_t)suspend_save(d);
-  } else {
-    return DECODE_MISMATCH;
-  }
-}
-
-int32_t upb_pbdecoder_skipunknown(upb_pbdecoder *d, int32_t fieldnum,
-                                  uint8_t wire_type) {
-  if (fieldnum >= 0)
-    goto have_tag;
-
-  while (true) {
-    uint32_t tag;
-    CHECK_RETURN(decode_v32(d, &tag));
-    wire_type = tag & 0x7;
-    fieldnum = tag >> 3;
-
-have_tag:
-    if (fieldnum == 0) {
-      seterr(d, "Saw invalid field number (0)");
-      return (int32_t)upb_pbdecoder_suspend(d);
-    }
-
-    switch (wire_type) {
-      case UPB_WIRE_TYPE_32BIT:
-        CHECK_RETURN(skip(d, 4));
-        break;
-      case UPB_WIRE_TYPE_64BIT:
-        CHECK_RETURN(skip(d, 8));
-        break;
-      case UPB_WIRE_TYPE_VARINT: {
-        uint64_t u64;
-        CHECK_RETURN(decode_varint(d, &u64));
-        break;
-      }
-      case UPB_WIRE_TYPE_DELIMITED: {
-        uint32_t len;
-        CHECK_RETURN(decode_v32(d, &len));
-        CHECK_RETURN(skip(d, len));
-        break;
-      }
-      case UPB_WIRE_TYPE_START_GROUP:
-        if (!pushtagdelim(d, -fieldnum)) {
-          return (int32_t)upb_pbdecoder_suspend(d);
-        }
-        break;
-      case UPB_WIRE_TYPE_END_GROUP:
-        if (fieldnum == -d->top->groupnum) {
-          decoder_pop(d);
-        } else if (fieldnum == d->top->groupnum) {
-          return DECODE_ENDGROUP;
-        } else {
-          seterr(d, "Unmatched ENDGROUP tag.");
-          return (int32_t)upb_pbdecoder_suspend(d);
-        }
-        break;
-      default:
-        seterr(d, "Invalid wire type");
-        return (int32_t)upb_pbdecoder_suspend(d);
-    }
-
-    if (d->top->groupnum >= 0) {
-      /* TODO: More code needed for handling unknown groups. */
-      upb_sink_putunknown(d->top->sink, d->checkpoint, d->ptr - d->checkpoint);
-      return DECODE_OK;
-    }
-
-    /* Unknown group -- continue looping over unknown fields. */
-    checkpoint(d);
-  }
-}
-
-static void goto_endmsg(upb_pbdecoder *d) {
-  upb_value v;
-  bool found = upb_inttable_lookup32(d->top->dispatch, DISPATCH_ENDMSG, &v);
-  UPB_ASSERT(found);
-  d->pc = d->top->base + upb_value_getuint64(v);
-}
-
-/* Parses a tag and jumps to the corresponding bytecode instruction for this
- * field.
- *
- * If the tag is unknown (or the wire type doesn't match), parses the field as
- * unknown.  If the tag is a valid ENDGROUP tag, jumps to the bytecode
- * instruction for the end of message. */
-static int32_t dispatch(upb_pbdecoder *d) {
-  upb_inttable *dispatch = d->top->dispatch;
-  uint32_t tag;
-  uint8_t wire_type;
-  uint32_t fieldnum;
-  upb_value val;
-  int32_t retval;
-
-  /* Decode tag. */
-  CHECK_RETURN(decode_v32(d, &tag));
-  wire_type = tag & 0x7;
-  fieldnum = tag >> 3;
-
-  /* Lookup tag.  Because of packed/non-packed compatibility, we have to
-   * check the wire type against two possibilities. */
-  if (fieldnum != DISPATCH_ENDMSG &&
-      upb_inttable_lookup32(dispatch, fieldnum, &val)) {
-    uint64_t v = upb_value_getuint64(val);
-    if (wire_type == (v & 0xff)) {
-      d->pc = d->top->base + (v >> 16);
-      return DECODE_OK;
-    } else if (wire_type == ((v >> 8) & 0xff)) {
-      bool found =
-          upb_inttable_lookup(dispatch, fieldnum + UPB_MAX_FIELDNUMBER, &val);
-      UPB_ASSERT(found);
-      d->pc = d->top->base + upb_value_getuint64(val);
-      return DECODE_OK;
-    }
-  }
-
-  /* We have some unknown fields (or ENDGROUP) to parse.  The DISPATCH or TAG
-   * bytecode that triggered this is preceded by a CHECKDELIM bytecode which
-   * we need to back up to, so that when we're done skipping unknown data we
-   * can re-check the delimited end. */
-  d->last--;  /* Necessary if we get suspended */
-  d->pc = d->last;
-  UPB_ASSERT(getop(*d->last) == OP_CHECKDELIM);
-
-  /* Unknown field or ENDGROUP. */
-  retval = upb_pbdecoder_skipunknown(d, fieldnum, wire_type);
-
-  CHECK_RETURN(retval);
-
-  if (retval == DECODE_ENDGROUP) {
-    goto_endmsg(d);
-    return DECODE_OK;
-  }
-
-  return DECODE_OK;
-}
-
-/* Callers know that the stack is more than one deep because the opcodes that
- * call this only occur after PUSH operations. */
-upb_pbdecoder_frame *outer_frame(upb_pbdecoder *d) {
-  UPB_ASSERT(d->top != d->stack);
-  return d->top - 1;
-}
-
-
-/* The main decoding loop *****************************************************/
-
-/* The main decoder VM function.  Uses traditional bytecode dispatch loop with a
- * switch() statement. */
-size_t run_decoder_vm(upb_pbdecoder *d, const mgroup *group,
-                      const upb_bufhandle* handle) {
-
-#define VMCASE(op, code) \
-  case op: { code; if (consumes_input(op)) checkpoint(d); break; }
-#define PRIMITIVE_OP(type, wt, name, convfunc, ctype) \
-  VMCASE(OP_PARSE_ ## type, { \
-    ctype val; \
-    CHECK_RETURN(decode_ ## wt(d, &val)); \
-    upb_sink_put ## name(d->top->sink, arg, (convfunc)(val)); \
-  })
-
-  while(1) {
-    int32_t instruction;
-    opcode op;
-    uint32_t arg;
-    int32_t longofs;
-
-    d->last = d->pc;
-    instruction = *d->pc++;
-    op = getop(instruction);
-    arg = instruction >> 8;
-    longofs = arg;
-    UPB_ASSERT(d->ptr != d->residual_end);
-    UPB_UNUSED(group);
-#ifdef UPB_DUMP_BYTECODE
-    fprintf(stderr, "s_ofs=%d buf_ofs=%d data_rem=%d buf_rem=%d delim_rem=%d "
-                    "%x %s (%d)\n",
-            (int)offset(d),
-            (int)(d->ptr - d->buf),
-            (int)(d->data_end - d->ptr),
-            (int)(d->end - d->ptr),
-            (int)((d->top->end_ofs - d->bufstart_ofs) - (d->ptr - d->buf)),
-            (int)(d->pc - 1 - group->bytecode),
-            upb_pbdecoder_getopname(op),
-            arg);
-#endif
-    switch (op) {
-      /* Technically, we are losing data if we see a 32-bit varint that is not
-       * properly sign-extended.  We could detect this and error about the data
-       * loss, but proto2 does not do this, so we pass. */
-      PRIMITIVE_OP(INT32,    varint,  int32,  int32_t,      uint64_t)
-      PRIMITIVE_OP(INT64,    varint,  int64,  int64_t,      uint64_t)
-      PRIMITIVE_OP(UINT32,   varint,  uint32, uint32_t,     uint64_t)
-      PRIMITIVE_OP(UINT64,   varint,  uint64, uint64_t,     uint64_t)
-      PRIMITIVE_OP(FIXED32,  fixed32, uint32, uint32_t,     uint32_t)
-      PRIMITIVE_OP(FIXED64,  fixed64, uint64, uint64_t,     uint64_t)
-      PRIMITIVE_OP(SFIXED32, fixed32, int32,  int32_t,      uint32_t)
-      PRIMITIVE_OP(SFIXED64, fixed64, int64,  int64_t,      uint64_t)
-      PRIMITIVE_OP(BOOL,     varint,  bool,   bool,         uint64_t)
-      PRIMITIVE_OP(DOUBLE,   fixed64, double, as_double,    uint64_t)
-      PRIMITIVE_OP(FLOAT,    fixed32, float,  as_float,     uint32_t)
-      PRIMITIVE_OP(SINT32,   varint,  int32,  upb_zzdec_32, uint64_t)
-      PRIMITIVE_OP(SINT64,   varint,  int64,  upb_zzdec_64, uint64_t)
-
-      VMCASE(OP_SETDISPATCH,
-        d->top->base = d->pc - 1;
-        memcpy(&d->top->dispatch, d->pc, sizeof(void*));
-        d->pc += sizeof(void*) / sizeof(uint32_t);
-      )
-      VMCASE(OP_STARTMSG,
-        CHECK_SUSPEND(upb_sink_startmsg(d->top->sink));
-      )
-      VMCASE(OP_ENDMSG,
-        CHECK_SUSPEND(upb_sink_endmsg(d->top->sink, d->status));
-      )
-      VMCASE(OP_STARTSEQ,
-        upb_pbdecoder_frame *outer = outer_frame(d);
-        CHECK_SUSPEND(upb_sink_startseq(outer->sink, arg, &d->top->sink));
-      )
-      VMCASE(OP_ENDSEQ,
-        CHECK_SUSPEND(upb_sink_endseq(d->top->sink, arg));
-      )
-      VMCASE(OP_STARTSUBMSG,
-        upb_pbdecoder_frame *outer = outer_frame(d);
-        CHECK_SUSPEND(upb_sink_startsubmsg(outer->sink, arg, &d->top->sink));
-      )
-      VMCASE(OP_ENDSUBMSG,
-        upb_sink subsink = (d->top + 1)->sink;
-        CHECK_SUSPEND(upb_sink_endsubmsg(d->top->sink, subsink, arg));
-      )
-      VMCASE(OP_STARTSTR,
-        uint32_t len = (uint32_t)delim_remaining(d);
-        upb_pbdecoder_frame *outer = outer_frame(d);
-        CHECK_SUSPEND(upb_sink_startstr(outer->sink, arg, len, &d->top->sink));
-        if (len == 0) {
-          d->pc++;  /* Skip OP_STRING. */
-        }
-      )
-      VMCASE(OP_STRING,
-        uint32_t len = (uint32_t)curbufleft(d);
-        size_t n = upb_sink_putstring(d->top->sink, arg, d->ptr, len, handle);
-        if (n > len) {
-          if (n > delim_remaining(d)) {
-            seterr(d, "Tried to skip past end of string.");
-            return upb_pbdecoder_suspend(d);
-          } else {
-            int32_t ret = skip(d, n);
-            /* This shouldn't return DECODE_OK, because n > len. */
-            UPB_ASSERT(ret >= 0);
-            return ret;
-          }
-        }
-        advance(d, n);
-        if (n < len || d->delim_end == NULL) {
-          /* We aren't finished with this string yet. */
-          d->pc--;  /* Repeat OP_STRING. */
-          if (n > 0) checkpoint(d);
-          return upb_pbdecoder_suspend(d);
-        }
-      )
-      VMCASE(OP_ENDSTR,
-        CHECK_SUSPEND(upb_sink_endstr(d->top->sink, arg));
-      )
-      VMCASE(OP_PUSHTAGDELIM,
-        CHECK_SUSPEND(pushtagdelim(d, arg));
-      )
-      VMCASE(OP_SETBIGGROUPNUM,
-        d->top->groupnum = *d->pc++;
-      )
-      VMCASE(OP_POP,
-        UPB_ASSERT(d->top > d->stack);
-        decoder_pop(d);
-      )
-      VMCASE(OP_PUSHLENDELIM,
-        uint32_t len;
-        CHECK_RETURN(decode_v32(d, &len));
-        CHECK_SUSPEND(decoder_push(d, offset(d) + len));
-        set_delim_end(d);
-      )
-      VMCASE(OP_SETDELIM,
-        set_delim_end(d);
-      )
-      VMCASE(OP_CHECKDELIM,
-        /* We are guaranteed of this assert because we never allow ourselves to
-         * consume bytes beyond data_end, which covers delim_end when non-NULL.
-         */
-        UPB_ASSERT(!(d->delim_end && d->ptr > d->delim_end));
-        if (d->ptr == d->delim_end)
-          d->pc += longofs;
-      )
-      VMCASE(OP_CALL,
-        d->callstack[d->call_len++] = d->pc;
-        d->pc += longofs;
-      )
-      VMCASE(OP_RET,
-        UPB_ASSERT(d->call_len > 0);
-        d->pc = d->callstack[--d->call_len];
-      )
-      VMCASE(OP_BRANCH,
-        d->pc += longofs;
-      )
-      VMCASE(OP_TAG1,
-        uint8_t expected;
-        CHECK_SUSPEND(curbufleft(d) > 0);
-        expected = (arg >> 8) & 0xff;
-        if (*d->ptr == expected) {
-          advance(d, 1);
-        } else {
-          int8_t shortofs;
-         badtag:
-          shortofs = arg;
-          if (shortofs == LABEL_DISPATCH) {
-            CHECK_RETURN(dispatch(d));
-          } else {
-            d->pc += shortofs;
-            break; /* Avoid checkpoint(). */
-          }
-        }
-      )
-      VMCASE(OP_TAG2,
-        uint16_t expected;
-        CHECK_SUSPEND(curbufleft(d) > 0);
-        expected = (arg >> 8) & 0xffff;
-        if (curbufleft(d) >= 2) {
-          uint16_t actual;
-          memcpy(&actual, d->ptr, 2);
-          if (expected == actual) {
-            advance(d, 2);
-          } else {
-            goto badtag;
-          }
-        } else {
-          int32_t result = upb_pbdecoder_checktag_slow(d, expected);
-          if (result == DECODE_MISMATCH) goto badtag;
-          if (result >= 0) return result;
-        }
-      )
-      VMCASE(OP_TAGN, {
-        uint64_t expected;
-        int32_t result;
-        memcpy(&expected, d->pc, 8);
-        d->pc += 2;
-        result = upb_pbdecoder_checktag_slow(d, expected);
-        if (result == DECODE_MISMATCH) goto badtag;
-        if (result >= 0) return result;
-      })
-      VMCASE(OP_DISPATCH, {
-        CHECK_RETURN(dispatch(d));
-      })
-      VMCASE(OP_HALT, {
-        return d->size_param;
-      })
-    }
-  }
-}
-
-
-/* BytesHandler handlers ******************************************************/
-
-void *upb_pbdecoder_startbc(void *closure, const void *pc, size_t size_hint) {
-  upb_pbdecoder *d = closure;
-  UPB_UNUSED(size_hint);
-  d->top->end_ofs = UINT64_MAX;
-  d->bufstart_ofs = 0;
-  d->call_len = 1;
-  d->callstack[0] = &halt;
-  d->pc = pc;
-  d->skip = 0;
-  return d;
-}
-
-bool upb_pbdecoder_end(void *closure, const void *handler_data) {
-  upb_pbdecoder *d = closure;
-  const upb_pbdecodermethod *method = handler_data;
-  uint64_t end;
-  char dummy;
-
-  if (d->residual_end > d->residual) {
-    seterr(d, "Unexpected EOF: decoder still has buffered unparsed data");
-    return false;
-  }
-
-  if (d->skip) {
-    seterr(d, "Unexpected EOF inside skipped data");
-    return false;
-  }
-
-  if (d->top->end_ofs != UINT64_MAX) {
-    seterr(d, "Unexpected EOF inside delimited string");
-    return false;
-  }
-
-  /* The user's end() call indicates that the message ends here. */
-  end = offset(d);
-  d->top->end_ofs = end;
-
-  {
-    const uint32_t *p = d->pc;
-    d->stack->end_ofs = end;
-    /* Check the previous bytecode, but guard against beginning. */
-    if (p != method->code_base.ptr) p--;
-    if (getop(*p) == OP_CHECKDELIM) {
-      /* Rewind from OP_TAG* to OP_CHECKDELIM. */
-      UPB_ASSERT(getop(*d->pc) == OP_TAG1 ||
-             getop(*d->pc) == OP_TAG2 ||
-             getop(*d->pc) == OP_TAGN ||
-             getop(*d->pc) == OP_DISPATCH);
-      d->pc = p;
-    }
-    upb_pbdecoder_decode(closure, handler_data, &dummy, 0, NULL);
-  }
-
-  if (d->call_len != 0) {
-    seterr(d, "Unexpected EOF inside submessage or group");
-    return false;
-  }
-
-  return true;
-}
-
-size_t upb_pbdecoder_decode(void *decoder, const void *group, const char *buf,
-                            size_t size, const upb_bufhandle *handle) {
-  int32_t result = upb_pbdecoder_resume(decoder, NULL, buf, size, handle);
-
-  if (result == DECODE_ENDGROUP) goto_endmsg(decoder);
-  CHECK_RETURN(result);
-
-  return run_decoder_vm(decoder, group, handle);
-}
-
-
-/* Public API *****************************************************************/
-
-void upb_pbdecoder_reset(upb_pbdecoder *d) {
-  d->top = d->stack;
-  d->top->groupnum = 0;
-  d->ptr = d->residual;
-  d->buf = d->residual;
-  d->end = d->residual;
-  d->residual_end = d->residual;
-}
-
-upb_pbdecoder *upb_pbdecoder_create(upb_arena *a, const upb_pbdecodermethod *m,
-                                    upb_sink sink, upb_status *status) {
-  const size_t default_max_nesting = 64;
-#ifndef NDEBUG
-  size_t size_before = upb_arena_bytesallocated(a);
-#endif
-
-  upb_pbdecoder *d = upb_arena_malloc(a, sizeof(upb_pbdecoder));
-  if (!d) return NULL;
-
-  d->method_ = m;
-  d->callstack = upb_arena_malloc(a, callstacksize(d, default_max_nesting));
-  d->stack = upb_arena_malloc(a, stacksize(d, default_max_nesting));
-  if (!d->stack || !d->callstack) {
-    return NULL;
-  }
-
-  d->arena = a;
-  d->limit = d->stack + default_max_nesting - 1;
-  d->stack_size = default_max_nesting;
-  d->status = status;
-
-  upb_pbdecoder_reset(d);
-  upb_bytessink_reset(&d->input_, &m->input_handler_, d);
-
-  if (d->method_->dest_handlers_) {
-    if (sink.handlers != d->method_->dest_handlers_)
-      return NULL;
-  }
-  d->top->sink = sink;
-
-  /* If this fails, increase the value in decoder.h. */
-  UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(a) - size_before <=
-                      UPB_PB_DECODER_SIZE);
-  return d;
-}
-
-uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d) {
-  return offset(d);
-}
-
-const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d) {
-  return d->method_;
-}
-
-upb_bytessink upb_pbdecoder_input(upb_pbdecoder *d) {
-  return d->input_;
-}
-
-size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d) {
-  return d->stack_size;
-}
-
-bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max) {
-  UPB_ASSERT(d->top >= d->stack);
-
-  if (max < (size_t)(d->top - d->stack)) {
-    /* Can't set a limit smaller than what we are currently at. */
-    return false;
-  }
-
-  if (max > d->stack_size) {
-    /* Need to reallocate stack and callstack to accommodate. */
-    size_t old_size = stacksize(d, d->stack_size);
-    size_t new_size = stacksize(d, max);
-    void *p = upb_arena_realloc(d->arena, d->stack, old_size, new_size);
-    if (!p) {
-      return false;
-    }
-    d->stack = p;
-
-    old_size = callstacksize(d, d->stack_size);
-    new_size = callstacksize(d, max);
-    p = upb_arena_realloc(d->arena, d->callstack, old_size, new_size);
-    if (!p) {
-      return false;
-    }
-    d->callstack = p;
-
-    d->stack_size = max;
-  }
-
-  d->limit = d->stack + max - 1;
-  return true;
-}
-/*
-** upb::Encoder
-**
-** Since we are implementing pure handlers (ie. without any out-of-band access
-** to pre-computed lengths), we have to buffer all submessages before we can
-** emit even their first byte.
-**
-** Not knowing the size of submessages also means we can't write a perfect
-** zero-copy implementation, even with buffering.  Lengths are stored as
-** varints, which means that we don't know how many bytes to reserve for the
-** length until we know what the length is.
-**
-** This leaves us with three main choices:
-**
-** 1. buffer all submessage data in a temporary buffer, then copy it exactly
-**    once into the output buffer.
-**
-** 2. attempt to buffer data directly into the output buffer, estimating how
-**    many bytes each length will take.  When our guesses are wrong, use
-**    memmove() to grow or shrink the allotted space.
-**
-** 3. buffer directly into the output buffer, allocating a max length
-**    ahead-of-time for each submessage length.  If we overallocated, we waste
-**    space, but no memcpy() or memmove() is required.  This approach requires
-**    defining a maximum size for submessages and rejecting submessages that
-**    exceed that size.
-**
-** (2) and (3) have the potential to have better performance, but they are more
-** complicated and subtle to implement:
-**
-**   (3) requires making an arbitrary choice of the maximum message size; it
-**       wastes space when submessages are shorter than this and fails
-**       completely when they are longer.  This makes it more finicky and
-**       requires configuration based on the input.  It also makes it impossible
-**       to perfectly match the output of reference encoders that always use the
-**       optimal amount of space for each length.
-**
-**   (2) requires guessing the the size upfront, and if multiple lengths are
-**       guessed wrong the minimum required number of memmove() operations may
-**       be complicated to compute correctly.  Implemented properly, it may have
-**       a useful amortized or average cost, but more investigation is required
-**       to determine this and what the optimal algorithm is to achieve it.
-**
-**   (1) makes you always pay for exactly one copy, but its implementation is
-**       the simplest and its performance is predictable.
-**
-** So for now, we implement (1) only.  If we wish to optimize later, we should
-** be able to do it without affecting users.
-**
-** The strategy is to buffer the segments of data that do *not* depend on
-** unknown lengths in one buffer, and keep a separate buffer of segment pointers
-** and lengths.  When the top-level submessage ends, we can go beginning to end,
-** alternating the writing of lengths with memcpy() of the rest of the data.
-** At the top level though, no buffering is required.
-*/
-
-
-
-/* The output buffer is divided into segments; a segment is a string of data
- * that is "ready to go" -- it does not need any varint lengths inserted into
- * the middle.  The seams between segments are where varints will be inserted
- * once they are known.
- *
- * We also use the concept of a "run", which is a range of encoded bytes that
- * occur at a single submessage level.  Every segment contains one or more runs.
- *
- * A segment can span messages.  Consider:
- *
- *                  .--Submessage lengths---------.
- *                  |       |                     |
- *                  |       V                     V
- *                  V      | |---------------    | |-----------------
- * Submessages:    | |-----------------------------------------------
- * Top-level msg: ------------------------------------------------------------
- *
- * Segments:          -----   -------------------   -----------------
- * Runs:              *----   *--------------*---   *----------------
- * (* marks the start)
- *
- * Note that the top-level menssage is not in any segment because it does not
- * have any length preceding it.
- *
- * A segment is only interrupted when another length needs to be inserted.  So
- * observe how the second segment spans both the inner submessage and part of
- * the next enclosing message. */
-typedef struct {
-  uint32_t msglen;  /* The length to varint-encode before this segment. */
-  uint32_t seglen;  /* Length of the segment. */
-} upb_pb_encoder_segment;
-
-struct upb_pb_encoder {
-  upb_arena *arena;
-
-  /* Our input and output. */
-  upb_sink input_;
-  upb_bytessink output_;
-
-  /* The "subclosure" -- used as the inner closure as part of the bytessink
-   * protocol. */
-  void *subc;
-
-  /* The output buffer and limit, and our current write position.  "buf"
-   * initially points to "initbuf", but is dynamically allocated if we need to
-   * grow beyond the initial size. */
-  char *buf, *ptr, *limit;
-
-  /* The beginning of the current run, or undefined if we are at the top
-   * level. */
-  char *runbegin;
-
-  /* The list of segments we are accumulating. */
-  upb_pb_encoder_segment *segbuf, *segptr, *seglimit;
-
-  /* The stack of enclosing submessages.  Each entry in the stack points to the
-   * segment where this submessage's length is being accumulated. */
-  int *stack, *top, *stacklimit;
-
-  /* Depth of startmsg/endmsg calls. */
-  int depth;
-};
-
-/* low-level buffering ********************************************************/
-
-/* Low-level functions for interacting with the output buffer. */
-
-/* TODO(haberman): handle pushback */
-static void putbuf(upb_pb_encoder *e, const char *buf, size_t len) {
-  size_t n = upb_bytessink_putbuf(e->output_, e->subc, buf, len, NULL);
-  UPB_ASSERT(n == len);
-}
-
-static upb_pb_encoder_segment *top(upb_pb_encoder *e) {
-  return &e->segbuf[*e->top];
-}
-
-/* Call to ensure that at least "bytes" bytes are available for writing at
- * e->ptr.  Returns false if the bytes could not be allocated. */
-static bool reserve(upb_pb_encoder *e, size_t bytes) {
-  if ((size_t)(e->limit - e->ptr) < bytes) {
-    /* Grow buffer. */
-    char *new_buf;
-    size_t needed = bytes + (e->ptr - e->buf);
-    size_t old_size = e->limit - e->buf;
-
-    size_t new_size = old_size;
-
-    while (new_size < needed) {
-      new_size *= 2;
-    }
-
-    new_buf = upb_arena_realloc(e->arena, e->buf, old_size, new_size);
-
-    if (new_buf == NULL) {
-      return false;
-    }
-
-    e->ptr = new_buf + (e->ptr - e->buf);
-    e->runbegin = new_buf + (e->runbegin - e->buf);
-    e->limit = new_buf + new_size;
-    e->buf = new_buf;
-  }
-
-  return true;
-}
-
-/* Call when "bytes" bytes have been writte at e->ptr.  The caller *must* have
- * previously called reserve() with at least this many bytes. */
-static void encoder_advance(upb_pb_encoder *e, size_t bytes) {
-  UPB_ASSERT((size_t)(e->limit - e->ptr) >= bytes);
-  e->ptr += bytes;
-}
-
-/* Call when all of the bytes for a handler have been written.  Flushes the
- * bytes if possible and necessary, returning false if this failed. */
-static bool commit(upb_pb_encoder *e) {
-  if (!e->top) {
-    /* We aren't inside a delimited region.  Flush our accumulated bytes to
-     * the output.
-     *
-     * TODO(haberman): in the future we may want to delay flushing for
-     * efficiency reasons. */
-    putbuf(e, e->buf, e->ptr - e->buf);
-    e->ptr = e->buf;
-  }
-
-  return true;
-}
-
-/* Writes the given bytes to the buffer, handling reserve/advance. */
-static bool encode_bytes(upb_pb_encoder *e, const void *data, size_t len) {
-  if (!reserve(e, len)) {
-    return false;
-  }
-
-  memcpy(e->ptr, data, len);
-  encoder_advance(e, len);
-  return true;
-}
-
-/* Finish the current run by adding the run totals to the segment and message
- * length. */
-static void accumulate(upb_pb_encoder *e) {
-  size_t run_len;
-  UPB_ASSERT(e->ptr >= e->runbegin);
-  run_len = e->ptr - e->runbegin;
-  e->segptr->seglen += run_len;
-  top(e)->msglen += run_len;
-  e->runbegin = e->ptr;
-}
-
-/* Call to indicate the start of delimited region for which the full length is
- * not yet known.  All data will be buffered until the length is known.
- * Delimited regions may be nested; their lengths will all be tracked properly. */
-static bool start_delim(upb_pb_encoder *e) {
-  if (e->top) {
-    /* We are already buffering, advance to the next segment and push it on the
-     * stack. */
-    accumulate(e);
-
-    if (++e->top == e->stacklimit) {
-      /* TODO(haberman): grow stack? */
-      return false;
-    }
-
-    if (++e->segptr == e->seglimit) {
-      /* Grow segment buffer. */
-      size_t old_size =
-          (e->seglimit - e->segbuf) * sizeof(upb_pb_encoder_segment);
-      size_t new_size = old_size * 2;
-      upb_pb_encoder_segment *new_buf =
-          upb_arena_realloc(e->arena, e->segbuf, old_size, new_size);
-
-      if (new_buf == NULL) {
-        return false;
-      }
-
-      e->segptr = new_buf + (e->segptr - e->segbuf);
-      e->seglimit = new_buf + (new_size / sizeof(upb_pb_encoder_segment));
-      e->segbuf = new_buf;
-    }
-  } else {
-    /* We were previously at the top level, start buffering. */
-    e->segptr = e->segbuf;
-    e->top = e->stack;
-    e->runbegin = e->ptr;
-  }
-
-  *e->top = (int)(e->segptr - e->segbuf);
-  e->segptr->seglen = 0;
-  e->segptr->msglen = 0;
-
-  return true;
-}
-
-/* Call to indicate the end of a delimited region.  We now know the length of
- * the delimited region.  If we are not nested inside any other delimited
- * regions, we can now emit all of the buffered data we accumulated. */
-static bool end_delim(upb_pb_encoder *e) {
-  size_t msglen;
-  accumulate(e);
-  msglen = top(e)->msglen;
-
-  if (e->top == e->stack) {
-    /* All lengths are now available, emit all buffered data. */
-    char buf[UPB_PB_VARINT_MAX_LEN];
-    upb_pb_encoder_segment *s;
-    const char *ptr = e->buf;
-    for (s = e->segbuf; s <= e->segptr; s++) {
-      size_t lenbytes = upb_vencode64(s->msglen, buf);
-      putbuf(e, buf, lenbytes);
-      putbuf(e, ptr, s->seglen);
-      ptr += s->seglen;
-    }
-
-    e->ptr = e->buf;
-    e->top = NULL;
-  } else {
-    /* Need to keep buffering; propagate length info into enclosing
-     * submessages. */
-    --e->top;
-    top(e)->msglen += msglen + upb_varint_size(msglen);
-  }
-
-  return true;
-}
-
-
-/* tag_t **********************************************************************/
-
-/* A precomputed (pre-encoded) tag and length. */
-
-typedef struct {
-  uint8_t bytes;
-  char tag[7];
-} tag_t;
-
-/* Allocates a new tag for this field, and sets it in these handlerattr. */
-static void new_tag(upb_handlers *h, const upb_fielddef *f, upb_wiretype_t wt,
-                    upb_handlerattr *attr) {
-  uint32_t n = upb_fielddef_number(f);
-
-  tag_t *tag = upb_gmalloc(sizeof(tag_t));
-  tag->bytes = upb_vencode64((n << 3) | wt, tag->tag);
-
-  attr->handler_data = tag;
-  upb_handlers_addcleanup(h, tag, upb_gfree);
-}
-
-static bool encode_tag(upb_pb_encoder *e, const tag_t *tag) {
-  return encode_bytes(e, tag->tag, tag->bytes);
-}
-
-
-/* encoding of wire types *****************************************************/
-
-static bool encode_fixed64(upb_pb_encoder *e, uint64_t val) {
-  /* TODO(haberman): byte-swap for big endian. */
-  return encode_bytes(e, &val, sizeof(uint64_t));
-}
-
-static bool encode_fixed32(upb_pb_encoder *e, uint32_t val) {
-  /* TODO(haberman): byte-swap for big endian. */
-  return encode_bytes(e, &val, sizeof(uint32_t));
-}
-
-static bool encode_varint(upb_pb_encoder *e, uint64_t val) {
-  if (!reserve(e, UPB_PB_VARINT_MAX_LEN)) {
-    return false;
-  }
-
-  encoder_advance(e, upb_vencode64(val, e->ptr));
-  return true;
-}
-
-static uint64_t dbl2uint64(double d) {
-  uint64_t ret;
-  memcpy(&ret, &d, sizeof(uint64_t));
-  return ret;
-}
-
-static uint32_t flt2uint32(float d) {
-  uint32_t ret;
-  memcpy(&ret, &d, sizeof(uint32_t));
-  return ret;
-}
-
-
-/* encoding of proto types ****************************************************/
-
-static bool startmsg(void *c, const void *hd) {
-  upb_pb_encoder *e = c;
-  UPB_UNUSED(hd);
-  if (e->depth++ == 0) {
-    upb_bytessink_start(e->output_, 0, &e->subc);
-  }
-  return true;
-}
-
-static bool endmsg(void *c, const void *hd, upb_status *status) {
-  upb_pb_encoder *e = c;
-  UPB_UNUSED(hd);
-  UPB_UNUSED(status);
-  if (--e->depth == 0) {
-    upb_bytessink_end(e->output_);
-  }
-  return true;
-}
-
-static void *encode_startdelimfield(void *c, const void *hd) {
-  bool ok = encode_tag(c, hd) && commit(c) && start_delim(c);
-  return ok ? c : UPB_BREAK;
-}
-
-static bool encode_unknown(void *c, const void *hd, const char *buf,
-                           size_t len) {
-  UPB_UNUSED(hd);
-  return encode_bytes(c, buf, len) && commit(c);
-}
-
-static bool encode_enddelimfield(void *c, const void *hd) {
-  UPB_UNUSED(hd);
-  return end_delim(c);
-}
-
-static void *encode_startgroup(void *c, const void *hd) {
-  return (encode_tag(c, hd) && commit(c)) ? c : UPB_BREAK;
-}
-
-static bool encode_endgroup(void *c, const void *hd) {
-  return encode_tag(c, hd) && commit(c);
-}
-
-static void *encode_startstr(void *c, const void *hd, size_t size_hint) {
-  UPB_UNUSED(size_hint);
-  return encode_startdelimfield(c, hd);
-}
-
-static size_t encode_strbuf(void *c, const void *hd, const char *buf,
-                            size_t len, const upb_bufhandle *h) {
-  UPB_UNUSED(hd);
-  UPB_UNUSED(h);
-  return encode_bytes(c, buf, len) ? len : 0;
-}
-
-#define T(type, ctype, convert, encode)                                  \
-  static bool encode_scalar_##type(void *e, const void *hd, ctype val) { \
-    return encode_tag(e, hd) && encode(e, (convert)(val)) && commit(e);  \
-  }                                                                      \
-  static bool encode_packed_##type(void *e, const void *hd, ctype val) { \
-    UPB_UNUSED(hd);                                                      \
-    return encode(e, (convert)(val));                                    \
-  }
-
-T(double,   double,   dbl2uint64,   encode_fixed64)
-T(float,    float,    flt2uint32,   encode_fixed32)
-T(int64,    int64_t,  uint64_t,     encode_varint)
-T(int32,    int32_t,  int64_t,      encode_varint)
-T(fixed64,  uint64_t, uint64_t,     encode_fixed64)
-T(fixed32,  uint32_t, uint32_t,     encode_fixed32)
-T(bool,     bool,     bool,         encode_varint)
-T(uint32,   uint32_t, uint32_t,     encode_varint)
-T(uint64,   uint64_t, uint64_t,     encode_varint)
-T(enum,     int32_t,  uint32_t,     encode_varint)
-T(sfixed32, int32_t,  uint32_t,     encode_fixed32)
-T(sfixed64, int64_t,  uint64_t,     encode_fixed64)
-T(sint32,   int32_t,  upb_zzenc_32, encode_varint)
-T(sint64,   int64_t,  upb_zzenc_64, encode_varint)
-
-#undef T
-
-
-/* code to build the handlers *************************************************/
-
-#include <stdio.h>
-static void newhandlers_callback(const void *closure, upb_handlers *h) {
-  const upb_msgdef *m;
-  upb_msg_field_iter i;
-
-  UPB_UNUSED(closure);
-
-  upb_handlers_setstartmsg(h, startmsg, NULL);
-  upb_handlers_setendmsg(h, endmsg, NULL);
-  upb_handlers_setunknown(h, encode_unknown, NULL);
-
-  m = upb_handlers_msgdef(h);
-  for(upb_msg_field_begin(&i, m);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    const upb_fielddef *f = upb_msg_iter_field(&i);
-    bool packed = upb_fielddef_isseq(f) && upb_fielddef_isprimitive(f) &&
-                  upb_fielddef_packed(f);
-    upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-    upb_wiretype_t wt =
-        packed ? UPB_WIRE_TYPE_DELIMITED
-               : upb_pb_native_wire_types[upb_fielddef_descriptortype(f)];
-
-    /* Pre-encode the tag for this field. */
-    new_tag(h, f, wt, &attr);
-
-    if (packed) {
-      upb_handlers_setstartseq(h, f, encode_startdelimfield, &attr);
-      upb_handlers_setendseq(h, f, encode_enddelimfield, &attr);
-    }
-
-#define T(upper, lower, upbtype)                                     \
-  case UPB_DESCRIPTOR_TYPE_##upper:                                  \
-    if (packed) {                                                    \
-      upb_handlers_set##upbtype(h, f, encode_packed_##lower, &attr); \
-    } else {                                                         \
-      upb_handlers_set##upbtype(h, f, encode_scalar_##lower, &attr); \
-    }                                                                \
-    break;
-
-    switch (upb_fielddef_descriptortype(f)) {
-      T(DOUBLE,   double,   double);
-      T(FLOAT,    float,    float);
-      T(INT64,    int64,    int64);
-      T(INT32,    int32,    int32);
-      T(FIXED64,  fixed64,  uint64);
-      T(FIXED32,  fixed32,  uint32);
-      T(BOOL,     bool,     bool);
-      T(UINT32,   uint32,   uint32);
-      T(UINT64,   uint64,   uint64);
-      T(ENUM,     enum,     int32);
-      T(SFIXED32, sfixed32, int32);
-      T(SFIXED64, sfixed64, int64);
-      T(SINT32,   sint32,   int32);
-      T(SINT64,   sint64,   int64);
-      case UPB_DESCRIPTOR_TYPE_STRING:
-      case UPB_DESCRIPTOR_TYPE_BYTES:
-        upb_handlers_setstartstr(h, f, encode_startstr, &attr);
-        upb_handlers_setendstr(h, f, encode_enddelimfield, &attr);
-        upb_handlers_setstring(h, f, encode_strbuf, &attr);
-        break;
-      case UPB_DESCRIPTOR_TYPE_MESSAGE:
-        upb_handlers_setstartsubmsg(h, f, encode_startdelimfield, &attr);
-        upb_handlers_setendsubmsg(h, f, encode_enddelimfield, &attr);
-        break;
-      case UPB_DESCRIPTOR_TYPE_GROUP: {
-        /* Endgroup takes a different tag (wire_type = END_GROUP). */
-        upb_handlerattr attr2 = UPB_HANDLERATTR_INIT;
-        new_tag(h, f, UPB_WIRE_TYPE_END_GROUP, &attr2);
-
-        upb_handlers_setstartsubmsg(h, f, encode_startgroup, &attr);
-        upb_handlers_setendsubmsg(h, f, encode_endgroup, &attr2);
-
-        break;
-      }
-    }
-
-#undef T
-  }
-}
-
-void upb_pb_encoder_reset(upb_pb_encoder *e) {
-  e->segptr = NULL;
-  e->top = NULL;
-  e->depth = 0;
-}
-
-
-/* public API *****************************************************************/
-
-upb_handlercache *upb_pb_encoder_newcache(void) {
-  return upb_handlercache_new(newhandlers_callback, NULL);
-}
-
-upb_pb_encoder *upb_pb_encoder_create(upb_arena *arena, const upb_handlers *h,
-                                      upb_bytessink output) {
-  const size_t initial_bufsize = 256;
-  const size_t initial_segbufsize = 16;
-  /* TODO(haberman): make this configurable. */
-  const size_t stack_size = 64;
-#ifndef NDEBUG
-  const size_t size_before = upb_arena_bytesallocated(arena);
-#endif
-
-  upb_pb_encoder *e = upb_arena_malloc(arena, sizeof(upb_pb_encoder));
-  if (!e) return NULL;
-
-  e->buf = upb_arena_malloc(arena, initial_bufsize);
-  e->segbuf = upb_arena_malloc(arena, initial_segbufsize * sizeof(*e->segbuf));
-  e->stack = upb_arena_malloc(arena, stack_size * sizeof(*e->stack));
-
-  if (!e->buf || !e->segbuf || !e->stack) {
-    return NULL;
-  }
-
-  e->limit = e->buf + initial_bufsize;
-  e->seglimit = e->segbuf + initial_segbufsize;
-  e->stacklimit = e->stack + stack_size;
-
-  upb_pb_encoder_reset(e);
-  upb_sink_reset(&e->input_, h, e);
-
-  e->arena = arena;
-  e->output_ = output;
-  e->subc = output.closure;
-  e->ptr = e->buf;
-
-  /* If this fails, increase the value in encoder.h. */
-  UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(arena) - size_before <=
-                      UPB_PB_ENCODER_SIZE);
-  return e;
-}
-
-upb_sink upb_pb_encoder_input(upb_pb_encoder *e) { return e->input_; }
-/*
- * upb::pb::TextPrinter
- *
- * OPT: This is not optimized at all.  It uses printf() which parses the format
- * string every time, and it allocates memory for every put.
- */
-
-
-#include <ctype.h>
-#include <float.h>
-#include <inttypes.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-
-
-struct upb_textprinter {
-  upb_sink input_;
-  upb_bytessink output_;
-  int indent_depth_;
-  bool single_line_;
-  void *subc;
-};
-
-#define CHECK(x) if ((x) < 0) goto err;
-
-static const char *shortname(const char *longname) {
-  const char *last = strrchr(longname, '.');
-  return last ? last + 1 : longname;
-}
-
-static int indent(upb_textprinter *p) {
-  int i;
-  if (!p->single_line_)
-    for (i = 0; i < p->indent_depth_; i++)
-      upb_bytessink_putbuf(p->output_, p->subc, "  ", 2, NULL);
-  return 0;
-}
-
-static int endfield(upb_textprinter *p) {
-  const char ch = (p->single_line_ ? ' ' : '\n');
-  upb_bytessink_putbuf(p->output_, p->subc, &ch, 1, NULL);
-  return 0;
-}
-
-static int putescaped(upb_textprinter *p, const char *buf, size_t len,
-                      bool preserve_utf8) {
-  /* Based on CEscapeInternal() from Google's protobuf release. */
-  char dstbuf[4096], *dst = dstbuf, *dstend = dstbuf + sizeof(dstbuf);
-  const char *end = buf + len;
-
-  /* I think hex is prettier and more useful, but proto2 uses octal; should
-   * investigate whether it can parse hex also. */
-  const bool use_hex = false;
-  bool last_hex_escape = false; /* true if last output char was \xNN */
-
-  for (; buf < end; buf++) {
-    bool is_hex_escape;
-
-    if (dstend - dst < 4) {
-      upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
-      dst = dstbuf;
-    }
-
-    is_hex_escape = false;
-    switch (*buf) {
-      case '\n': *(dst++) = '\\'; *(dst++) = 'n';  break;
-      case '\r': *(dst++) = '\\'; *(dst++) = 'r';  break;
-      case '\t': *(dst++) = '\\'; *(dst++) = 't';  break;
-      case '\"': *(dst++) = '\\'; *(dst++) = '\"'; break;
-      case '\'': *(dst++) = '\\'; *(dst++) = '\''; break;
-      case '\\': *(dst++) = '\\'; *(dst++) = '\\'; break;
-      default:
-        /* Note that if we emit \xNN and the buf character after that is a hex
-         * digit then that digit must be escaped too to prevent it being
-         * interpreted as part of the character code by C. */
-        if ((!preserve_utf8 || (uint8_t)*buf < 0x80) &&
-            (!isprint(*buf) || (last_hex_escape && isxdigit(*buf)))) {
-          sprintf(dst, (use_hex ? "\\x%02x" : "\\%03o"), (uint8_t)*buf);
-          is_hex_escape = use_hex;
-          dst += 4;
-        } else {
-          *(dst++) = *buf; break;
-        }
-    }
-    last_hex_escape = is_hex_escape;
-  }
-  /* Flush remaining data. */
-  upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
-  return 0;
-}
-
-bool putf(upb_textprinter *p, const char *fmt, ...) {
-  va_list args;
-  va_list args_copy;
-  char *str;
-  int written;
-  int len;
-  bool ok;
-
-  va_start(args, fmt);
-
-  /* Run once to get the length of the string. */
-  _upb_va_copy(args_copy, args);
-  len = _upb_vsnprintf(NULL, 0, fmt, args_copy);
-  va_end(args_copy);
-
-  /* + 1 for NULL terminator (vsprintf() requires it even if we don't). */
-  str = upb_gmalloc(len + 1);
-  if (!str) return false;
-  written = vsprintf(str, fmt, args);
-  va_end(args);
-  UPB_ASSERT(written == len);
-
-  ok = upb_bytessink_putbuf(p->output_, p->subc, str, len, NULL);
-  upb_gfree(str);
-  return ok;
-}
-
-
-/* handlers *******************************************************************/
-
-static bool textprinter_startmsg(void *c, const void *hd) {
-  upb_textprinter *p = c;
-  UPB_UNUSED(hd);
-  if (p->indent_depth_ == 0) {
-    upb_bytessink_start(p->output_, 0, &p->subc);
-  }
-  return true;
-}
-
-static bool textprinter_endmsg(void *c, const void *hd, upb_status *s) {
-  upb_textprinter *p = c;
-  UPB_UNUSED(hd);
-  UPB_UNUSED(s);
-  if (p->indent_depth_ == 0) {
-    upb_bytessink_end(p->output_);
-  }
-  return true;
-}
-
-#define TYPE(name, ctype, fmt) \
-  static bool textprinter_put ## name(void *closure, const void *handler_data, \
-                                      ctype val) {                             \
-    upb_textprinter *p = closure;                                              \
-    const upb_fielddef *f = handler_data;                                      \
-    CHECK(indent(p));                                                          \
-    putf(p, "%s: " fmt, upb_fielddef_name(f), val);                            \
-    CHECK(endfield(p));                                                        \
-    return true;                                                               \
-  err:                                                                         \
-    return false;                                                              \
-}
-
-static bool textprinter_putbool(void *closure, const void *handler_data,
-                                bool val) {
-  upb_textprinter *p = closure;
-  const upb_fielddef *f = handler_data;
-  CHECK(indent(p));
-  putf(p, "%s: %s", upb_fielddef_name(f), val ? "true" : "false");
-  CHECK(endfield(p));
-  return true;
-err:
-  return false;
-}
-
-#define STRINGIFY_HELPER(x) #x
-#define STRINGIFY_MACROVAL(x) STRINGIFY_HELPER(x)
-
-TYPE(int32,  int32_t,  "%" PRId32)
-TYPE(int64,  int64_t,  "%" PRId64)
-TYPE(uint32, uint32_t, "%" PRIu32)
-TYPE(uint64, uint64_t, "%" PRIu64)
-TYPE(float,  float,    "%." STRINGIFY_MACROVAL(FLT_DIG) "g")
-TYPE(double, double,   "%." STRINGIFY_MACROVAL(DBL_DIG) "g")
-
-#undef TYPE
-
-/* Output a symbolic value from the enum if found, else just print as int32. */
-static bool textprinter_putenum(void *closure, const void *handler_data,
-                                int32_t val) {
-  upb_textprinter *p = closure;
-  const upb_fielddef *f = handler_data;
-  const upb_enumdef *enum_def = upb_fielddef_enumsubdef(f);
-  const char *label = upb_enumdef_iton(enum_def, val);
-  if (label) {
-    indent(p);
-    putf(p, "%s: %s", upb_fielddef_name(f), label);
-    endfield(p);
-  } else {
-    if (!textprinter_putint32(closure, handler_data, val))
-      return false;
-  }
-  return true;
-}
-
-static void *textprinter_startstr(void *closure, const void *handler_data,
-                      size_t size_hint) {
-  upb_textprinter *p = closure;
-  const upb_fielddef *f = handler_data;
-  UPB_UNUSED(size_hint);
-  indent(p);
-  putf(p, "%s: \"", upb_fielddef_name(f));
-  return p;
-}
-
-static bool textprinter_endstr(void *closure, const void *handler_data) {
-  upb_textprinter *p = closure;
-  UPB_UNUSED(handler_data);
-  putf(p, "\"");
-  endfield(p);
-  return true;
-}
-
-static size_t textprinter_putstr(void *closure, const void *hd, const char *buf,
-                                 size_t len, const upb_bufhandle *handle) {
-  upb_textprinter *p = closure;
-  const upb_fielddef *f = hd;
-  UPB_UNUSED(handle);
-  CHECK(putescaped(p, buf, len, upb_fielddef_type(f) == UPB_TYPE_STRING));
-  return len;
-err:
-  return 0;
-}
-
-static void *textprinter_startsubmsg(void *closure, const void *handler_data) {
-  upb_textprinter *p = closure;
-  const char *name = handler_data;
-  CHECK(indent(p));
-  putf(p, "%s {%c", name, p->single_line_ ? ' ' : '\n');
-  p->indent_depth_++;
-  return p;
-err:
-  return UPB_BREAK;
-}
-
-static bool textprinter_endsubmsg(void *closure, const void *handler_data) {
-  upb_textprinter *p = closure;
-  UPB_UNUSED(handler_data);
-  p->indent_depth_--;
-  CHECK(indent(p));
-  upb_bytessink_putbuf(p->output_, p->subc, "}", 1, NULL);
-  CHECK(endfield(p));
-  return true;
-err:
-  return false;
-}
-
-static void onmreg(const void *c, upb_handlers *h) {
-  const upb_msgdef *m = upb_handlers_msgdef(h);
-  upb_msg_field_iter i;
-  UPB_UNUSED(c);
-
-  upb_handlers_setstartmsg(h, textprinter_startmsg, NULL);
-  upb_handlers_setendmsg(h, textprinter_endmsg, NULL);
-
-  for(upb_msg_field_begin(&i, m);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    upb_fielddef *f = upb_msg_iter_field(&i);
-    upb_handlerattr attr = UPB_HANDLERATTR_INIT;
-    attr.handler_data = f;
-    switch (upb_fielddef_type(f)) {
-      case UPB_TYPE_INT32:
-        upb_handlers_setint32(h, f, textprinter_putint32, &attr);
-        break;
-      case UPB_TYPE_INT64:
-        upb_handlers_setint64(h, f, textprinter_putint64, &attr);
-        break;
-      case UPB_TYPE_UINT32:
-        upb_handlers_setuint32(h, f, textprinter_putuint32, &attr);
-        break;
-      case UPB_TYPE_UINT64:
-        upb_handlers_setuint64(h, f, textprinter_putuint64, &attr);
-        break;
-      case UPB_TYPE_FLOAT:
-        upb_handlers_setfloat(h, f, textprinter_putfloat, &attr);
-        break;
-      case UPB_TYPE_DOUBLE:
-        upb_handlers_setdouble(h, f, textprinter_putdouble, &attr);
-        break;
-      case UPB_TYPE_BOOL:
-        upb_handlers_setbool(h, f, textprinter_putbool, &attr);
-        break;
-      case UPB_TYPE_STRING:
-      case UPB_TYPE_BYTES:
-        upb_handlers_setstartstr(h, f, textprinter_startstr, &attr);
-        upb_handlers_setstring(h, f, textprinter_putstr, &attr);
-        upb_handlers_setendstr(h, f, textprinter_endstr, &attr);
-        break;
-      case UPB_TYPE_MESSAGE: {
-        const char *name =
-            upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_GROUP
-                ? shortname(upb_msgdef_fullname(upb_fielddef_msgsubdef(f)))
-                : upb_fielddef_name(f);
-        attr.handler_data = name;
-        upb_handlers_setstartsubmsg(h, f, textprinter_startsubmsg, &attr);
-        upb_handlers_setendsubmsg(h, f, textprinter_endsubmsg, &attr);
-        break;
-      }
-      case UPB_TYPE_ENUM:
-        upb_handlers_setint32(h, f, textprinter_putenum, &attr);
-        break;
-    }
-  }
-}
-
-static void textprinter_reset(upb_textprinter *p, bool single_line) {
-  p->single_line_ = single_line;
-  p->indent_depth_ = 0;
-}
-
-
-/* Public API *****************************************************************/
-
-upb_textprinter *upb_textprinter_create(upb_arena *arena, const upb_handlers *h,
-                                        upb_bytessink output) {
-  upb_textprinter *p = upb_arena_malloc(arena, sizeof(upb_textprinter));
-  if (!p) return NULL;
-
-  p->output_ = output;
-  upb_sink_reset(&p->input_, h, p);
-  textprinter_reset(p, false);
-
-  return p;
-}
-
-upb_handlercache *upb_textprinter_newcache(void) {
-  return upb_handlercache_new(&onmreg, NULL);
-}
-
-upb_sink upb_textprinter_input(upb_textprinter *p) { return p->input_; }
-
-void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line) {
-  p->single_line_ = single_line;
-}
-
-
-/* Index is descriptor type. */
-const uint8_t upb_pb_native_wire_types[] = {
-  UPB_WIRE_TYPE_END_GROUP,     /* ENDGROUP */
-  UPB_WIRE_TYPE_64BIT,         /* DOUBLE */
-  UPB_WIRE_TYPE_32BIT,         /* FLOAT */
-  UPB_WIRE_TYPE_VARINT,        /* INT64 */
-  UPB_WIRE_TYPE_VARINT,        /* UINT64 */
-  UPB_WIRE_TYPE_VARINT,        /* INT32 */
-  UPB_WIRE_TYPE_64BIT,         /* FIXED64 */
-  UPB_WIRE_TYPE_32BIT,         /* FIXED32 */
-  UPB_WIRE_TYPE_VARINT,        /* BOOL */
-  UPB_WIRE_TYPE_DELIMITED,     /* STRING */
-  UPB_WIRE_TYPE_START_GROUP,   /* GROUP */
-  UPB_WIRE_TYPE_DELIMITED,     /* MESSAGE */
-  UPB_WIRE_TYPE_DELIMITED,     /* BYTES */
-  UPB_WIRE_TYPE_VARINT,        /* UINT32 */
-  UPB_WIRE_TYPE_VARINT,        /* ENUM */
-  UPB_WIRE_TYPE_32BIT,         /* SFIXED32 */
-  UPB_WIRE_TYPE_64BIT,         /* SFIXED64 */
-  UPB_WIRE_TYPE_VARINT,        /* SINT32 */
-  UPB_WIRE_TYPE_VARINT,        /* SINT64 */
-};
-
-/* A basic branch-based decoder, uses 32-bit values to get good performance
- * on 32-bit architectures (but performs well on 64-bits also).
- * This scheme comes from the original Google Protobuf implementation
- * (proto2). */
-upb_decoderet upb_vdecode_max8_branch32(upb_decoderet r) {
-  upb_decoderet err = {NULL, 0};
-  const char *p = r.p;
-  uint32_t low = (uint32_t)r.val;
-  uint32_t high = 0;
-  uint32_t b;
-  b = *(p++); low  |= (b & 0x7fU) << 14; if (!(b & 0x80)) goto done;
-  b = *(p++); low  |= (b & 0x7fU) << 21; if (!(b & 0x80)) goto done;
-  b = *(p++); low  |= (b & 0x7fU) << 28;
-              high  = (b & 0x7fU) >>  4; if (!(b & 0x80)) goto done;
-  b = *(p++); high |= (b & 0x7fU) <<  3; if (!(b & 0x80)) goto done;
-  b = *(p++); high |= (b & 0x7fU) << 10; if (!(b & 0x80)) goto done;
-  b = *(p++); high |= (b & 0x7fU) << 17; if (!(b & 0x80)) goto done;
-  b = *(p++); high |= (b & 0x7fU) << 24; if (!(b & 0x80)) goto done;
-  b = *(p++); high |= (b & 0x7fU) << 31; if (!(b & 0x80)) goto done;
-  return err;
-
-done:
-  r.val = ((uint64_t)high << 32) | low;
-  r.p = p;
-  return r;
-}
-
-/* Like the previous, but uses 64-bit values. */
-upb_decoderet upb_vdecode_max8_branch64(upb_decoderet r) {
-  const char *p = r.p;
-  uint64_t val = r.val;
-  uint64_t b;
-  upb_decoderet err = {NULL, 0};
-  b = *(p++); val |= (b & 0x7fU) << 14; if (!(b & 0x80)) goto done;
-  b = *(p++); val |= (b & 0x7fU) << 21; if (!(b & 0x80)) goto done;
-  b = *(p++); val |= (b & 0x7fU) << 28; if (!(b & 0x80)) goto done;
-  b = *(p++); val |= (b & 0x7fU) << 35; if (!(b & 0x80)) goto done;
-  b = *(p++); val |= (b & 0x7fU) << 42; if (!(b & 0x80)) goto done;
-  b = *(p++); val |= (b & 0x7fU) << 49; if (!(b & 0x80)) goto done;
-  b = *(p++); val |= (b & 0x7fU) << 56; if (!(b & 0x80)) goto done;
-  b = *(p++); val |= (b & 0x7fU) << 63; if (!(b & 0x80)) goto done;
-  return err;
-
-done:
-  r.val = val;
-  r.p = p;
-  return r;
-}
-
-#line 1 "upb/json/parser.rl"
-/*
-** upb::json::Parser (upb_json_parser)
-**
-** A parser that uses the Ragel State Machine Compiler to generate
-** the finite automata.
-**
-** Ragel only natively handles regular languages, but we can manually
-** program it a bit to handle context-free languages like JSON, by using
-** the "fcall" and "fret" constructs.
-**
-** This parser can handle the basics, but needs several things to be fleshed
-** out:
-**
-** - handling of unicode escape sequences (including high surrogate pairs).
-** - properly check and report errors for unknown fields, stack overflow,
-**   improper array nesting (or lack of nesting).
-** - handling of base64 sequences with padding characters.
-** - handling of push-back (non-success returns from sink functions).
-** - handling of keys/escape-sequences/etc that span input buffers.
-*/
-
-#include <ctype.h>
-#include <errno.h>
-#include <float.h>
-#include <math.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <time.h>
-
-
-
-#define UPB_JSON_MAX_DEPTH 64
-
-/* Type of value message */
-enum {
-  VALUE_NULLVALUE   = 0,
-  VALUE_NUMBERVALUE = 1,
-  VALUE_STRINGVALUE = 2,
-  VALUE_BOOLVALUE   = 3,
-  VALUE_STRUCTVALUE = 4,
-  VALUE_LISTVALUE   = 5
-};
-
-/* Forward declare */
-static bool is_top_level(upb_json_parser *p);
-static bool is_wellknown_msg(upb_json_parser *p, upb_wellknowntype_t type);
-static bool is_wellknown_field(upb_json_parser *p, upb_wellknowntype_t type);
-
-static bool is_number_wrapper_object(upb_json_parser *p);
-static bool does_number_wrapper_start(upb_json_parser *p);
-static bool does_number_wrapper_end(upb_json_parser *p);
-
-static bool is_string_wrapper_object(upb_json_parser *p);
-static bool does_string_wrapper_start(upb_json_parser *p);
-static bool does_string_wrapper_end(upb_json_parser *p);
-
-static bool does_fieldmask_start(upb_json_parser *p);
-static bool does_fieldmask_end(upb_json_parser *p);
-static void start_fieldmask_object(upb_json_parser *p);
-static void end_fieldmask_object(upb_json_parser *p);
-
-static void start_wrapper_object(upb_json_parser *p);
-static void end_wrapper_object(upb_json_parser *p);
-
-static void start_value_object(upb_json_parser *p, int value_type);
-static void end_value_object(upb_json_parser *p);
-
-static void start_listvalue_object(upb_json_parser *p);
-static void end_listvalue_object(upb_json_parser *p);
-
-static void start_structvalue_object(upb_json_parser *p);
-static void end_structvalue_object(upb_json_parser *p);
-
-static void start_object(upb_json_parser *p);
-static void end_object(upb_json_parser *p);
-
-static void start_any_object(upb_json_parser *p, const char *ptr);
-static bool end_any_object(upb_json_parser *p, const char *ptr);
-
-static bool start_subobject(upb_json_parser *p);
-static void end_subobject(upb_json_parser *p);
-
-static void start_member(upb_json_parser *p);
-static void end_member(upb_json_parser *p);
-static bool end_membername(upb_json_parser *p);
-
-static void start_any_member(upb_json_parser *p, const char *ptr);
-static void end_any_member(upb_json_parser *p, const char *ptr);
-static bool end_any_membername(upb_json_parser *p);
-
-size_t parse(void *closure, const void *hd, const char *buf, size_t size,
-             const upb_bufhandle *handle);
-static bool end(void *closure, const void *hd);
-
-static const char eof_ch = 'e';
-
-/* stringsink */
-typedef struct {
-  upb_byteshandler handler;
-  upb_bytessink sink;
-  char *ptr;
-  size_t len, size;
-} upb_stringsink;
-
-
-static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) {
-  upb_stringsink *sink = _sink;
-  sink->len = 0;
-  UPB_UNUSED(hd);
-  UPB_UNUSED(size_hint);
-  return sink;
-}
-
-static size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
-                                size_t len, const upb_bufhandle *handle) {
-  upb_stringsink *sink = _sink;
-  size_t new_size = sink->size;
-
-  UPB_UNUSED(hd);
-  UPB_UNUSED(handle);
-
-  while (sink->len + len > new_size) {
-    new_size *= 2;
-  }
-
-  if (new_size != sink->size) {
-    sink->ptr = realloc(sink->ptr, new_size);
-    sink->size = new_size;
-  }
-
-  memcpy(sink->ptr + sink->len, ptr, len);
-  sink->len += len;
-
-  return len;
-}
-
-void upb_stringsink_init(upb_stringsink *sink) {
-  upb_byteshandler_init(&sink->handler);
-  upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL);
-  upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL);
-
-  upb_bytessink_reset(&sink->sink, &sink->handler, sink);
-
-  sink->size = 32;
-  sink->ptr = malloc(sink->size);
-  sink->len = 0;
-}
-
-void upb_stringsink_uninit(upb_stringsink *sink) { free(sink->ptr); }
-
-typedef struct {
-  /* For encoding Any value field in binary format. */
-  upb_handlercache *encoder_handlercache;
-  upb_stringsink stringsink;
-
-  /* For decoding Any value field in json format. */
-  upb_json_codecache *parser_codecache;
-  upb_sink sink;
-  upb_json_parser *parser;
-
-  /* Mark the range of uninterpreted values in json input before type url. */
-  const char *before_type_url_start;
-  const char *before_type_url_end;
-
-  /* Mark the range of uninterpreted values in json input after type url. */
-  const char *after_type_url_start;
-} upb_jsonparser_any_frame;
-
-typedef struct {
-  upb_sink sink;
-
-  /* The current message in which we're parsing, and the field whose value we're
-   * expecting next. */
-  const upb_msgdef *m;
-  const upb_fielddef *f;
-
-  /* The table mapping json name to fielddef for this message. */
-  const upb_strtable *name_table;
-
-  /* We are in a repeated-field context. We need this flag to decide whether to
-   * handle the array as a normal repeated field or a
-   * google.protobuf.ListValue/google.protobuf.Value. */
-  bool is_repeated;
-
-  /* We are in a repeated-field context, ready to emit mapentries as
-   * submessages. This flag alters the start-of-object (open-brace) behavior to
-   * begin a sequence of mapentry messages rather than a single submessage. */
-  bool is_map;
-
-  /* We are in a map-entry message context. This flag is set when parsing the
-   * value field of a single map entry and indicates to all value-field parsers
-   * (subobjects, strings, numbers, and bools) that the map-entry submessage
-   * should end as soon as the value is parsed. */
-  bool is_mapentry;
-
-  /* If |is_map| or |is_mapentry| is true, |mapfield| refers to the parent
-   * message's map field that we're currently parsing. This differs from |f|
-   * because |f| is the field in the *current* message (i.e., the map-entry
-   * message itself), not the parent's field that leads to this map. */
-  const upb_fielddef *mapfield;
-
-  /* We are in an Any message context. This flag is set when parsing the Any
-   * message and indicates to all field parsers (subobjects, strings, numbers,
-   * and bools) that the parsed field should be serialized as binary data or
-   * cached (type url not found yet). */
-  bool is_any;
-
-  /* The type of packed message in Any. */
-  upb_jsonparser_any_frame *any_frame;
-
-  /* True if the field to be parsed is unknown. */
-  bool is_unknown_field;
-} upb_jsonparser_frame;
-
-static void init_frame(upb_jsonparser_frame* frame) {
-  frame->m = NULL;
-  frame->f = NULL;
-  frame->name_table = NULL;
-  frame->is_repeated = false;
-  frame->is_map = false;
-  frame->is_mapentry = false;
-  frame->mapfield = NULL;
-  frame->is_any = false;
-  frame->any_frame = NULL;
-  frame->is_unknown_field = false;
-}
-
-struct upb_json_parser {
-  upb_arena *arena;
-  const upb_json_parsermethod *method;
-  upb_bytessink input_;
-
-  /* Stack to track the JSON scopes we are in. */
-  upb_jsonparser_frame stack[UPB_JSON_MAX_DEPTH];
-  upb_jsonparser_frame *top;
-  upb_jsonparser_frame *limit;
-
-  upb_status *status;
-
-  /* Ragel's internal parsing stack for the parsing state machine. */
-  int current_state;
-  int parser_stack[UPB_JSON_MAX_DEPTH];
-  int parser_top;
-
-  /* The handle for the current buffer. */
-  const upb_bufhandle *handle;
-
-  /* Accumulate buffer.  See details in parser.rl. */
-  const char *accumulated;
-  size_t accumulated_len;
-  char *accumulate_buf;
-  size_t accumulate_buf_size;
-
-  /* Multi-part text data.  See details in parser.rl. */
-  int multipart_state;
-  upb_selector_t string_selector;
-
-  /* Input capture.  See details in parser.rl. */
-  const char *capture;
-
-  /* Intermediate result of parsing a unicode escape sequence. */
-  uint32_t digit;
-
-  /* For resolve type url in Any. */
-  const upb_symtab *symtab;
-
-  /* Whether to proceed if unknown field is met. */
-  bool ignore_json_unknown;
-
-  /* Cache for parsing timestamp due to base and zone are handled in different
-   * handlers. */
-  struct tm tm;
-};
-
-static upb_jsonparser_frame* start_jsonparser_frame(upb_json_parser *p) {
-  upb_jsonparser_frame *inner;
-  inner = p->top + 1;
-  init_frame(inner);
-  return inner;
-}
-
-struct upb_json_codecache {
-  upb_arena *arena;
-  upb_inttable methods;   /* upb_msgdef* -> upb_json_parsermethod* */
-};
-
-struct upb_json_parsermethod {
-  const upb_json_codecache *cache;
-  upb_byteshandler input_handler_;
-
-  /* Maps json_name -> fielddef */
-  upb_strtable name_table;
-};
-
-#define PARSER_CHECK_RETURN(x) if (!(x)) return false
-
-static upb_jsonparser_any_frame *json_parser_any_frame_new(
-    upb_json_parser *p) {
-  upb_jsonparser_any_frame *frame;
-
-  frame = upb_arena_malloc(p->arena, sizeof(upb_jsonparser_any_frame));
-
-  frame->encoder_handlercache = upb_pb_encoder_newcache();
-  frame->parser_codecache = upb_json_codecache_new();
-  frame->parser = NULL;
-  frame->before_type_url_start = NULL;
-  frame->before_type_url_end = NULL;
-  frame->after_type_url_start = NULL;
-
-  upb_stringsink_init(&frame->stringsink);
-
-  return frame;
-}
-
-static void json_parser_any_frame_set_payload_type(
-    upb_json_parser *p,
-    upb_jsonparser_any_frame *frame,
-    const upb_msgdef *payload_type) {
-  const upb_handlers *h;
-  const upb_json_parsermethod *parser_method;
-  upb_pb_encoder *encoder;
-
-  /* Initialize encoder. */
-  h = upb_handlercache_get(frame->encoder_handlercache, payload_type);
-  encoder = upb_pb_encoder_create(p->arena, h, frame->stringsink.sink);
-
-  /* Initialize parser. */
-  parser_method = upb_json_codecache_get(frame->parser_codecache, payload_type);
-  upb_sink_reset(&frame->sink, h, encoder);
-  frame->parser =
-      upb_json_parser_create(p->arena, parser_method, p->symtab, frame->sink,
-                             p->status, p->ignore_json_unknown);
-}
-
-static void json_parser_any_frame_free(upb_jsonparser_any_frame *frame) {
-  upb_handlercache_free(frame->encoder_handlercache);
-  upb_json_codecache_free(frame->parser_codecache);
-  upb_stringsink_uninit(&frame->stringsink);
-}
-
-static bool json_parser_any_frame_has_type_url(
-  upb_jsonparser_any_frame *frame) {
-  return frame->parser != NULL;
-}
-
-static bool json_parser_any_frame_has_value_before_type_url(
-  upb_jsonparser_any_frame *frame) {
-  return frame->before_type_url_start != frame->before_type_url_end;
-}
-
-static bool json_parser_any_frame_has_value_after_type_url(
-  upb_jsonparser_any_frame *frame) {
-  return frame->after_type_url_start != NULL;
-}
-
-static bool json_parser_any_frame_has_value(
-  upb_jsonparser_any_frame *frame) {
-  return json_parser_any_frame_has_value_before_type_url(frame) ||
-         json_parser_any_frame_has_value_after_type_url(frame);
-}
-
-static void json_parser_any_frame_set_before_type_url_end(
-    upb_jsonparser_any_frame *frame,
-    const char *ptr) {
-  if (frame->parser == NULL) {
-    frame->before_type_url_end = ptr;
-  }
-}
-
-static void json_parser_any_frame_set_after_type_url_start_once(
-    upb_jsonparser_any_frame *frame,
-    const char *ptr) {
-  if (json_parser_any_frame_has_type_url(frame) &&
-      frame->after_type_url_start == NULL) {
-    frame->after_type_url_start = ptr;
-  }
-}
-
-/* Used to signal that a capture has been suspended. */
-static char suspend_capture;
-
-static upb_selector_t getsel_for_handlertype(upb_json_parser *p,
-                                             upb_handlertype_t type) {
-  upb_selector_t sel;
-  bool ok = upb_handlers_getselector(p->top->f, type, &sel);
-  UPB_ASSUME(ok);
-  return sel;
-}
-
-static upb_selector_t parser_getsel(upb_json_parser *p) {
-  return getsel_for_handlertype(
-      p, upb_handlers_getprimitivehandlertype(p->top->f));
-}
-
-static bool check_stack(upb_json_parser *p) {
-  if ((p->top + 1) == p->limit) {
-    upb_status_seterrmsg(p->status, "Nesting too deep");
-    return false;
-  }
-
-  return true;
-}
-
-static void set_name_table(upb_json_parser *p, upb_jsonparser_frame *frame) {
-  upb_value v;
-  const upb_json_codecache *cache = p->method->cache;
-  bool ok;
-  const upb_json_parsermethod *method;
-
-  ok = upb_inttable_lookupptr(&cache->methods, frame->m, &v);
-  UPB_ASSUME(ok);
-  method = upb_value_getconstptr(v);
-
-  frame->name_table = &method->name_table;
-}
-
-/* There are GCC/Clang built-ins for overflow checking which we could start
- * using if there was any performance benefit to it. */
-
-static bool checked_add(size_t a, size_t b, size_t *c) {
-  if (SIZE_MAX - a < b) return false;
-  *c = a + b;
-  return true;
-}
-
-static size_t saturating_multiply(size_t a, size_t b) {
-  /* size_t is unsigned, so this is defined behavior even on overflow. */
-  size_t ret = a * b;
-  if (b != 0 && ret / b != a) {
-    ret = SIZE_MAX;
-  }
-  return ret;
-}
-
-
-/* Base64 decoding ************************************************************/
-
-/* TODO(haberman): make this streaming. */
-
-static const signed char b64table[] = {
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      62/*+*/, -1,      -1,      -1,      63/*/ */,
-  52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
-  60/*8*/, 61/*9*/, -1,      -1,      -1,      -1,      -1,      -1,
-  -1,       0/*A*/,  1/*B*/,  2/*C*/,  3/*D*/,  4/*E*/,  5/*F*/,  6/*G*/,
-  07/*H*/,  8/*I*/,  9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
-  15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
-  23/*X*/, 24/*Y*/, 25/*Z*/, -1,      -1,      -1,      -1,      -1,
-  -1,      26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
-  33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
-  41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
-  49/*x*/, 50/*y*/, 51/*z*/, -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1
-};
-
-/* Returns the table value sign-extended to 32 bits.  Knowing that the upper
- * bits will be 1 for unrecognized characters makes it easier to check for
- * this error condition later (see below). */
-int32_t b64lookup(unsigned char ch) { return b64table[ch]; }
-
-/* Returns true if the given character is not a valid base64 character or
- * padding. */
-bool nonbase64(unsigned char ch) { return b64lookup(ch) == -1 && ch != '='; }
-
-static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
-                        size_t len) {
-  const char *limit = ptr + len;
-  for (; ptr < limit; ptr += 4) {
-    uint32_t val;
-    char output[3];
-
-    if (limit - ptr < 4) {
-      upb_status_seterrf(p->status,
-                         "Base64 input for bytes field not a multiple of 4: %s",
-                         upb_fielddef_name(p->top->f));
-      return false;
-    }
-
-    val = b64lookup(ptr[0]) << 18 |
-          b64lookup(ptr[1]) << 12 |
-          b64lookup(ptr[2]) << 6  |
-          b64lookup(ptr[3]);
-
-    /* Test the upper bit; returns true if any of the characters returned -1. */
-    if (val & 0x80000000) {
-      goto otherchar;
-    }
-
-    output[0] = val >> 16;
-    output[1] = (val >> 8) & 0xff;
-    output[2] = val & 0xff;
-    upb_sink_putstring(p->top->sink, sel, output, 3, NULL);
-  }
-  return true;
-
-otherchar:
-  if (nonbase64(ptr[0]) || nonbase64(ptr[1]) || nonbase64(ptr[2]) ||
-      nonbase64(ptr[3]) ) {
-    upb_status_seterrf(p->status,
-                       "Non-base64 characters in bytes field: %s",
-                       upb_fielddef_name(p->top->f));
-    return false;
-  } if (ptr[2] == '=') {
-    uint32_t val;
-    char output;
-
-    /* Last group contains only two input bytes, one output byte. */
-    if (ptr[0] == '=' || ptr[1] == '=' || ptr[3] != '=') {
-      goto badpadding;
-    }
-
-    val = b64lookup(ptr[0]) << 18 |
-          b64lookup(ptr[1]) << 12;
-
-    UPB_ASSERT(!(val & 0x80000000));
-    output = val >> 16;
-    upb_sink_putstring(p->top->sink, sel, &output, 1, NULL);
-    return true;
-  } else {
-    uint32_t val;
-    char output[2];
-
-    /* Last group contains only three input bytes, two output bytes. */
-    if (ptr[0] == '=' || ptr[1] == '=' || ptr[2] == '=') {
-      goto badpadding;
-    }
-
-    val = b64lookup(ptr[0]) << 18 |
-          b64lookup(ptr[1]) << 12 |
-          b64lookup(ptr[2]) << 6;
-
-    output[0] = val >> 16;
-    output[1] = (val >> 8) & 0xff;
-    upb_sink_putstring(p->top->sink, sel, output, 2, NULL);
-    return true;
-  }
-
-badpadding:
-  upb_status_seterrf(p->status,
-                     "Incorrect base64 padding for field: %s (%.*s)",
-                     upb_fielddef_name(p->top->f),
-                     4, ptr);
-  return false;
-}
-
-
-/* Accumulate buffer **********************************************************/
-
-/* Functionality for accumulating a buffer.
- *
- * Some parts of the parser need an entire value as a contiguous string.  For
- * example, to look up a member name in a hash table, or to turn a string into
- * a number, the relevant library routines need the input string to be in
- * contiguous memory, even if the value spanned two or more buffers in the
- * input.  These routines handle that.
- *
- * In the common case we can just point to the input buffer to get this
- * contiguous string and avoid any actual copy.  So we optimistically begin
- * this way.  But there are a few cases where we must instead copy into a
- * separate buffer:
- *
- *   1. The string was not contiguous in the input (it spanned buffers).
- *
- *   2. The string included escape sequences that need to be interpreted to get
- *      the true value in a contiguous buffer. */
-
-static void assert_accumulate_empty(upb_json_parser *p) {
-  UPB_ASSERT(p->accumulated == NULL);
-  UPB_ASSERT(p->accumulated_len == 0);
-}
-
-static void accumulate_clear(upb_json_parser *p) {
-  p->accumulated = NULL;
-  p->accumulated_len = 0;
-}
-
-/* Used internally by accumulate_append(). */
-static bool accumulate_realloc(upb_json_parser *p, size_t need) {
-  void *mem;
-  size_t old_size = p->accumulate_buf_size;
-  size_t new_size = UPB_MAX(old_size, 128);
-  while (new_size < need) {
-    new_size = saturating_multiply(new_size, 2);
-  }
-
-  mem = upb_arena_realloc(p->arena, p->accumulate_buf, old_size, new_size);
-  if (!mem) {
-    upb_status_seterrmsg(p->status, "Out of memory allocating buffer.");
-    return false;
-  }
-
-  p->accumulate_buf = mem;
-  p->accumulate_buf_size = new_size;
-  return true;
-}
-
-/* Logically appends the given data to the append buffer.
- * If "can_alias" is true, we will try to avoid actually copying, but the buffer
- * must be valid until the next accumulate_append() call (if any). */
-static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len,
-                              bool can_alias) {
-  size_t need;
-
-  if (!p->accumulated && can_alias) {
-    p->accumulated = buf;
-    p->accumulated_len = len;
-    return true;
-  }
-
-  if (!checked_add(p->accumulated_len, len, &need)) {
-    upb_status_seterrmsg(p->status, "Integer overflow.");
-    return false;
-  }
-
-  if (need > p->accumulate_buf_size && !accumulate_realloc(p, need)) {
-    return false;
-  }
-
-  if (p->accumulated != p->accumulate_buf) {
-    memcpy(p->accumulate_buf, p->accumulated, p->accumulated_len);
-    p->accumulated = p->accumulate_buf;
-  }
-
-  memcpy(p->accumulate_buf + p->accumulated_len, buf, len);
-  p->accumulated_len += len;
-  return true;
-}
-
-/* Returns a pointer to the data accumulated since the last accumulate_clear()
- * call, and writes the length to *len.  This with point either to the input
- * buffer or a temporary accumulate buffer. */
-static const char *accumulate_getptr(upb_json_parser *p, size_t *len) {
-  UPB_ASSERT(p->accumulated);
-  *len = p->accumulated_len;
-  return p->accumulated;
-}
-
-
-/* Mult-part text data ********************************************************/
-
-/* When we have text data in the input, it can often come in multiple segments.
- * For example, there may be some raw string data followed by an escape
- * sequence.  The two segments are processed with different logic.  Also buffer
- * seams in the input can cause multiple segments.
- *
- * As we see segments, there are two main cases for how we want to process them:
- *
- *  1. we want to push the captured input directly to string handlers.
- *
- *  2. we need to accumulate all the parts into a contiguous buffer for further
- *     processing (field name lookup, string->number conversion, etc). */
-
-/* This is the set of states for p->multipart_state. */
-enum {
-  /* We are not currently processing multipart data. */
-  MULTIPART_INACTIVE = 0,
-
-  /* We are processing multipart data by accumulating it into a contiguous
-   * buffer. */
-  MULTIPART_ACCUMULATE = 1,
-
-  /* We are processing multipart data by pushing each part directly to the
-   * current string handlers. */
-  MULTIPART_PUSHEAGERLY = 2
-};
-
-/* Start a multi-part text value where we accumulate the data for processing at
- * the end. */
-static void multipart_startaccum(upb_json_parser *p) {
-  assert_accumulate_empty(p);
-  UPB_ASSERT(p->multipart_state == MULTIPART_INACTIVE);
-  p->multipart_state = MULTIPART_ACCUMULATE;
-}
-
-/* Start a multi-part text value where we immediately push text data to a string
- * value with the given selector. */
-static void multipart_start(upb_json_parser *p, upb_selector_t sel) {
-  assert_accumulate_empty(p);
-  UPB_ASSERT(p->multipart_state == MULTIPART_INACTIVE);
-  p->multipart_state = MULTIPART_PUSHEAGERLY;
-  p->string_selector = sel;
-}
-
-static bool multipart_text(upb_json_parser *p, const char *buf, size_t len,
-                           bool can_alias) {
-  switch (p->multipart_state) {
-    case MULTIPART_INACTIVE:
-      upb_status_seterrmsg(
-          p->status, "Internal error: unexpected state MULTIPART_INACTIVE");
-      return false;
-
-    case MULTIPART_ACCUMULATE:
-      if (!accumulate_append(p, buf, len, can_alias)) {
-        return false;
-      }
-      break;
-
-    case MULTIPART_PUSHEAGERLY: {
-      const upb_bufhandle *handle = can_alias ? p->handle : NULL;
-      upb_sink_putstring(p->top->sink, p->string_selector, buf, len, handle);
-      break;
-    }
-  }
-
-  return true;
-}
-
-/* Note: this invalidates the accumulate buffer!  Call only after reading its
- * contents. */
-static void multipart_end(upb_json_parser *p) {
-  /* UPB_ASSERT(p->multipart_state != MULTIPART_INACTIVE); */
-  p->multipart_state = MULTIPART_INACTIVE;
-  accumulate_clear(p);
-}
-
-
-/* Input capture **************************************************************/
-
-/* Functionality for capturing a region of the input as text.  Gracefully
- * handles the case where a buffer seam occurs in the middle of the captured
- * region. */
-
-static void capture_begin(upb_json_parser *p, const char *ptr) {
-  UPB_ASSERT(p->multipart_state != MULTIPART_INACTIVE);
-  UPB_ASSERT(p->capture == NULL);
-  p->capture = ptr;
-}
-
-static bool capture_end(upb_json_parser *p, const char *ptr) {
-  UPB_ASSERT(p->capture);
-  if (multipart_text(p, p->capture, ptr - p->capture, true)) {
-    p->capture = NULL;
-    return true;
-  } else {
-    return false;
-  }
-}
-
-/* This is called at the end of each input buffer (ie. when we have hit a
- * buffer seam).  If we are in the middle of capturing the input, this
- * processes the unprocessed capture region. */
-static void capture_suspend(upb_json_parser *p, const char **ptr) {
-  if (!p->capture) return;
-
-  if (multipart_text(p, p->capture, *ptr - p->capture, false)) {
-    /* We use this as a signal that we were in the middle of capturing, and
-     * that capturing should resume at the beginning of the next buffer.
-     * 
-     * We can't use *ptr here, because we have no guarantee that this pointer
-     * will be valid when we resume (if the underlying memory is freed, then
-     * using the pointer at all, even to compare to NULL, is likely undefined
-     * behavior). */
-    p->capture = &suspend_capture;
-  } else {
-    /* Need to back up the pointer to the beginning of the capture, since
-     * we were not able to actually preserve it. */
-    *ptr = p->capture;
-  }
-}
-
-static void capture_resume(upb_json_parser *p, const char *ptr) {
-  if (p->capture) {
-    UPB_ASSERT(p->capture == &suspend_capture);
-    p->capture = ptr;
-  }
-}
-
-
-/* Callbacks from the parser **************************************************/
-
-/* These are the functions called directly from the parser itself.
- * We define these in the same order as their declarations in the parser. */
-
-static char escape_char(char in) {
-  switch (in) {
-    case 'r': return '\r';
-    case 't': return '\t';
-    case 'n': return '\n';
-    case 'f': return '\f';
-    case 'b': return '\b';
-    case '/': return '/';
-    case '"': return '"';
-    case '\\': return '\\';
-    default:
-      UPB_ASSERT(0);
-      return 'x';
-  }
-}
-
-static bool escape(upb_json_parser *p, const char *ptr) {
-  char ch = escape_char(*ptr);
-  return multipart_text(p, &ch, 1, false);
-}
-
-static void start_hex(upb_json_parser *p) {
-  p->digit = 0;
-}
-
-static void hexdigit(upb_json_parser *p, const char *ptr) {
-  char ch = *ptr;
-
-  p->digit <<= 4;
-
-  if (ch >= '0' && ch <= '9') {
-    p->digit += (ch - '0');
-  } else if (ch >= 'a' && ch <= 'f') {
-    p->digit += ((ch - 'a') + 10);
-  } else {
-    UPB_ASSERT(ch >= 'A' && ch <= 'F');
-    p->digit += ((ch - 'A') + 10);
-  }
-}
-
-static bool end_hex(upb_json_parser *p) {
-  uint32_t codepoint = p->digit;
-
-  /* emit the codepoint as UTF-8. */
-  char utf8[3]; /* support \u0000 -- \uFFFF -- need only three bytes. */
-  int length = 0;
-  if (codepoint <= 0x7F) {
-    utf8[0] = codepoint;
-    length = 1;
-  } else if (codepoint <= 0x07FF) {
-    utf8[1] = (codepoint & 0x3F) | 0x80;
-    codepoint >>= 6;
-    utf8[0] = (codepoint & 0x1F) | 0xC0;
-    length = 2;
-  } else /* codepoint <= 0xFFFF */ {
-    utf8[2] = (codepoint & 0x3F) | 0x80;
-    codepoint >>= 6;
-    utf8[1] = (codepoint & 0x3F) | 0x80;
-    codepoint >>= 6;
-    utf8[0] = (codepoint & 0x0F) | 0xE0;
-    length = 3;
-  }
-  /* TODO(haberman): Handle high surrogates: if codepoint is a high surrogate
-   * we have to wait for the next escape to get the full code point). */
-
-  return multipart_text(p, utf8, length, false);
-}
-
-static void start_text(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_text(upb_json_parser *p, const char *ptr) {
-  return capture_end(p, ptr);
-}
-
-static bool start_number(upb_json_parser *p, const char *ptr) {
-  if (is_top_level(p)) {
-    if (is_number_wrapper_object(p)) {
-      start_wrapper_object(p);
-    } else if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-      start_value_object(p, VALUE_NUMBERVALUE);
-    } else {
-      return false;
-    }
-  } else if (does_number_wrapper_start(p)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_wrapper_object(p);
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_value_object(p, VALUE_NUMBERVALUE);
-  }
-
-  multipart_startaccum(p);
-  capture_begin(p, ptr);
-  return true;
-}
-
-static bool parse_number(upb_json_parser *p, bool is_quoted);
-
-static bool end_number_nontop(upb_json_parser *p, const char *ptr) {
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-
-  if (p->top->f == NULL) {
-    multipart_end(p);
-    return true;
-  }
-
-  return parse_number(p, false);
-}
-
-static bool end_number(upb_json_parser *p, const char *ptr) {
-  if (!end_number_nontop(p, ptr)) {
-    return false;
-  }
-
-  if (does_number_wrapper_end(p)) {
-    end_wrapper_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-    end_value_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  return true;
-}
-
-/* |buf| is NULL-terminated. |buf| itself will never include quotes;
- * |is_quoted| tells us whether this text originally appeared inside quotes. */
-static bool parse_number_from_buffer(upb_json_parser *p, const char *buf,
-                                     bool is_quoted) {
-  size_t len = strlen(buf);
-  const char *bufend = buf + len;
-  char *end;
-  upb_fieldtype_t type = upb_fielddef_type(p->top->f);
-  double val;
-  double dummy;
-  double inf = UPB_INFINITY;
-
-  errno = 0;
-
-  if (len == 0 || buf[0] == ' ') {
-    return false;
-  }
-
-  /* For integer types, first try parsing with integer-specific routines.
-   * If these succeed, they will be more accurate for int64/uint64 than
-   * strtod().
-   */
-  switch (type) {
-    case UPB_TYPE_ENUM:
-    case UPB_TYPE_INT32: {
-      long val = strtol(buf, &end, 0);
-      if (errno == ERANGE || end != bufend) {
-        break;
-      } else if (val > INT32_MAX || val < INT32_MIN) {
-        return false;
-      } else {
-        upb_sink_putint32(p->top->sink, parser_getsel(p), (int32_t)val);
-        return true;
-      }
-    }
-    case UPB_TYPE_UINT32: {
-      unsigned long val = strtoul(buf, &end, 0);
-      if (end != bufend) {
-        break;
-      } else if (val > UINT32_MAX || errno == ERANGE) {
-        return false;
-      } else {
-        upb_sink_putuint32(p->top->sink, parser_getsel(p), (uint32_t)val);
-        return true;
-      }
-    }
-    /* XXX: We can't handle [u]int64 properly on 32-bit machines because
-     * strto[u]ll isn't in C89. */
-    case UPB_TYPE_INT64: {
-      long val = strtol(buf, &end, 0);
-      if (errno == ERANGE || end != bufend) {
-        break;
-      } else {
-        upb_sink_putint64(p->top->sink, parser_getsel(p), val);
-        return true;
-      }
-    }
-    case UPB_TYPE_UINT64: {
-      unsigned long val = strtoul(p->accumulated, &end, 0);
-      if (end != bufend) {
-        break;
-      } else if (errno == ERANGE) {
-        return false;
-      } else {
-        upb_sink_putuint64(p->top->sink, parser_getsel(p), val);
-        return true;
-      }
-    }
-    default:
-      break;
-  }
-
-  if (type != UPB_TYPE_DOUBLE && type != UPB_TYPE_FLOAT && is_quoted) {
-    /* Quoted numbers for integer types are not allowed to be in double form. */
-    return false;
-  }
-
-  if (len == strlen("Infinity") && strcmp(buf, "Infinity") == 0) {
-    /* C89 does not have an INFINITY macro. */
-    val = inf;
-  } else if (len == strlen("-Infinity") && strcmp(buf, "-Infinity") == 0) {
-    val = -inf;
-  } else {
-    val = strtod(buf, &end);
-    if (errno == ERANGE || end != bufend) {
-      return false;
-    }
-  }
-
-  switch (type) {
-#define CASE(capitaltype, smalltype, ctype, min, max)                     \
-    case UPB_TYPE_ ## capitaltype: {                                      \
-      if (modf(val, &dummy) != 0 || val > max || val < min) {             \
-        return false;                                                     \
-      } else {                                                            \
-        upb_sink_put ## smalltype(p->top->sink, parser_getsel(p),        \
-                                  (ctype)val);                            \
-        return true;                                                      \
-      }                                                                   \
-      break;                                                              \
-    }
-    case UPB_TYPE_ENUM:
-    CASE(INT32, int32, int32_t, INT32_MIN, INT32_MAX);
-    CASE(INT64, int64, int64_t, INT64_MIN, INT64_MAX);
-    CASE(UINT32, uint32, uint32_t, 0, UINT32_MAX);
-    CASE(UINT64, uint64, uint64_t, 0, UINT64_MAX);
-#undef CASE
-
-    case UPB_TYPE_DOUBLE:
-      upb_sink_putdouble(p->top->sink, parser_getsel(p), val);
-      return true;
-    case UPB_TYPE_FLOAT:
-      if ((val > FLT_MAX || val < -FLT_MAX) && val != inf && val != -inf) {
-        return false;
-      } else {
-        upb_sink_putfloat(p->top->sink, parser_getsel(p), val);
-        return true;
-      }
-    default:
-      return false;
-  }
-}
-
-static bool parse_number(upb_json_parser *p, bool is_quoted) {
-  size_t len;
-  const char *buf;
-
-  /* strtol() and friends unfortunately do not support specifying the length of
-   * the input string, so we need to force a copy into a NULL-terminated buffer. */
-  if (!multipart_text(p, "\0", 1, false)) {
-    return false;
-  }
-
-  buf = accumulate_getptr(p, &len);
-
-  if (parse_number_from_buffer(p, buf, is_quoted)) {
-    multipart_end(p);
-    return true;
-  } else {
-    upb_status_seterrf(p->status, "error parsing number: %s", buf);
-    multipart_end(p);
-    return false;
-  }
-}
-
-static bool parser_putbool(upb_json_parser *p, bool val) {
-  bool ok;
-
-  if (p->top->f == NULL) {
-    return true;
-  }
-
-  if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) {
-    upb_status_seterrf(p->status,
-                       "Boolean value specified for non-bool field: %s",
-                       upb_fielddef_name(p->top->f));
-    return false;
-  }
-
-  ok = upb_sink_putbool(p->top->sink, parser_getsel(p), val);
-  UPB_ASSERT(ok);
-
-  return true;
-}
-
-static bool end_bool(upb_json_parser *p, bool val) {
-  if (is_top_level(p)) {
-    if (is_wellknown_msg(p, UPB_WELLKNOWN_BOOLVALUE)) {
-      start_wrapper_object(p);
-    } else if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-      start_value_object(p, VALUE_BOOLVALUE);
-    } else {
-      return false;
-    }
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_BOOLVALUE)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_wrapper_object(p);
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_value_object(p, VALUE_BOOLVALUE);
-  }
-
-  if (p->top->is_unknown_field) {
-    return true;
-  }
-
-  if (!parser_putbool(p, val)) {
-    return false;
-  }
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_BOOLVALUE)) {
-    end_wrapper_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-    end_value_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  return true;
-}
-
-static bool end_null(upb_json_parser *p) {
-  const char *zero_ptr = "0";
-
-  if (is_top_level(p)) {
-    if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-      start_value_object(p, VALUE_NULLVALUE);
-    } else {
-      return true;
-    }
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_value_object(p, VALUE_NULLVALUE);
-  } else {
-    return true;
-  }
-
-  /* Fill null_value field. */
-  multipart_startaccum(p);
-  capture_begin(p, zero_ptr);
-  capture_end(p, zero_ptr + 1);
-  parse_number(p, false);
-
-  end_value_object(p);
-  if (!is_top_level(p)) {
-    end_subobject(p);
-  }
-
-  return true;
-}
-
-static bool start_any_stringval(upb_json_parser *p) {
-  multipart_startaccum(p);
-  return true;
-}
-
-static bool start_stringval(upb_json_parser *p) {
-  if (is_top_level(p)) {
-    if (is_string_wrapper_object(p) ||
-        is_number_wrapper_object(p)) {
-      start_wrapper_object(p);
-    } else if (is_wellknown_msg(p, UPB_WELLKNOWN_FIELDMASK)) {
-      start_fieldmask_object(p);
-      return true;
-    } else if (is_wellknown_msg(p, UPB_WELLKNOWN_TIMESTAMP) ||
-               is_wellknown_msg(p, UPB_WELLKNOWN_DURATION)) {
-      start_object(p);
-    } else if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-      start_value_object(p, VALUE_STRINGVALUE);
-    } else {
-      return false;
-    }
-  } else if (does_string_wrapper_start(p) ||
-             does_number_wrapper_start(p)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_wrapper_object(p);
-  } else if (does_fieldmask_start(p)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_fieldmask_object(p);
-    return true;
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_TIMESTAMP) ||
-             is_wellknown_field(p, UPB_WELLKNOWN_DURATION)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_object(p);
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) {
-    if (!start_subobject(p)) {
-      return false;
-    }
-    start_value_object(p, VALUE_STRINGVALUE);
-  }
-
-  if (p->top->f == NULL) {
-    multipart_startaccum(p);
-    return true;
-  }
-
-  if (p->top->is_any) {
-    return start_any_stringval(p);
-  }
-
-  if (upb_fielddef_isstring(p->top->f)) {
-    upb_jsonparser_frame *inner;
-    upb_selector_t sel;
-
-    if (!check_stack(p)) return false;
-
-    /* Start a new parser frame: parser frames correspond one-to-one with
-     * handler frames, and string events occur in a sub-frame. */
-    inner = start_jsonparser_frame(p);
-    sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
-    upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
-    inner->m = p->top->m;
-    inner->f = p->top->f;
-    p->top = inner;
-
-    if (upb_fielddef_type(p->top->f) == UPB_TYPE_STRING) {
-      /* For STRING fields we push data directly to the handlers as it is
-       * parsed.  We don't do this yet for BYTES fields, because our base64
-       * decoder is not streaming.
-       *
-       * TODO(haberman): make base64 decoding streaming also. */
-      multipart_start(p, getsel_for_handlertype(p, UPB_HANDLER_STRING));
-      return true;
-    } else {
-      multipart_startaccum(p);
-      return true;
-    }
-  } else if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL &&
-             upb_fielddef_type(p->top->f) != UPB_TYPE_MESSAGE) {
-    /* No need to push a frame -- numeric values in quotes remain in the
-     * current parser frame.  These values must accmulate so we can convert
-     * them all at once at the end. */
-    multipart_startaccum(p);
-    return true;
-  } else {
-    upb_status_seterrf(p->status,
-                       "String specified for bool or submessage field: %s",
-                       upb_fielddef_name(p->top->f));
-    return false;
-  }
-}
-
-static bool end_any_stringval(upb_json_parser *p) {
-  size_t len;
-  const char *buf = accumulate_getptr(p, &len);
-
-  /* Set type_url */
-  upb_selector_t sel;
-  upb_jsonparser_frame *inner;
-  if (!check_stack(p)) return false;
-  inner = p->top + 1;
-
-  sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
-  upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
-  sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
-  upb_sink_putstring(inner->sink, sel, buf, len, NULL);
-  sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
-  upb_sink_endstr(inner->sink, sel);
-
-  multipart_end(p);
-
-  /* Resolve type url */
-  if (strncmp(buf, "type.googleapis.com/", 20) == 0 && len > 20) {
-    const upb_msgdef *payload_type = NULL;
-    buf += 20;
-    len -= 20;
-
-    payload_type = upb_symtab_lookupmsg2(p->symtab, buf, len);
-    if (payload_type == NULL) {
-      upb_status_seterrf(
-          p->status, "Cannot find packed type: %.*s\n", (int)len, buf);
-      return false;
-    }
-
-    json_parser_any_frame_set_payload_type(p, p->top->any_frame, payload_type);
-
-    return true;
-  } else {
-    upb_status_seterrf(
-        p->status, "Invalid type url: %.*s\n", (int)len, buf);
-    return false;
-  }
-}
-
-static bool end_stringval_nontop(upb_json_parser *p) {
-  bool ok = true;
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_TIMESTAMP) ||
-      is_wellknown_msg(p, UPB_WELLKNOWN_DURATION)) {
-    multipart_end(p);
-    return true;
-  }
-
-  if (p->top->f == NULL) {
-    multipart_end(p);
-    return true;
-  }
-
-  if (p->top->is_any) {
-    return end_any_stringval(p);
-  }
-
-  switch (upb_fielddef_type(p->top->f)) {
-    case UPB_TYPE_BYTES:
-      if (!base64_push(p, getsel_for_handlertype(p, UPB_HANDLER_STRING),
-                       p->accumulated, p->accumulated_len)) {
-        return false;
-      }
-      /* Fall through. */
-
-    case UPB_TYPE_STRING: {
-      upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
-      upb_sink_endstr(p->top->sink, sel);
-      p->top--;
-      break;
-    }
-
-    case UPB_TYPE_ENUM: {
-      /* Resolve enum symbolic name to integer value. */
-      const upb_enumdef *enumdef = upb_fielddef_enumsubdef(p->top->f);
-
-      size_t len;
-      const char *buf = accumulate_getptr(p, &len);
-
-      int32_t int_val = 0;
-      ok = upb_enumdef_ntoi(enumdef, buf, len, &int_val);
-
-      if (ok) {
-        upb_selector_t sel = parser_getsel(p);
-        upb_sink_putint32(p->top->sink, sel, int_val);
-      } else {
-        upb_status_seterrf(p->status, "Enum value unknown: '%.*s'", len, buf);
-      }
-
-      break;
-    }
-
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_UINT64:
-    case UPB_TYPE_DOUBLE:
-    case UPB_TYPE_FLOAT:
-      ok = parse_number(p, true);
-      break;
-
-    default:
-      UPB_ASSERT(false);
-      upb_status_seterrmsg(p->status, "Internal error in JSON decoder");
-      ok = false;
-      break;
-  }
-
-  multipart_end(p);
-
-  return ok;
-}
-
-static bool end_stringval(upb_json_parser *p) {
-  /* FieldMask's stringvals have been ended when handling them. Only need to
-   * close FieldMask here.*/
-  if (does_fieldmask_end(p)) {
-    end_fieldmask_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  if (!end_stringval_nontop(p)) {
-    return false;
-  }
-
-  if (does_string_wrapper_end(p) ||
-      does_number_wrapper_end(p)) {
-    end_wrapper_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-    end_value_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_TIMESTAMP) ||
-      is_wellknown_msg(p, UPB_WELLKNOWN_DURATION) ||
-      is_wellknown_msg(p, UPB_WELLKNOWN_FIELDMASK)) {
-    end_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-    return true;
-  }
-
-  return true;
-}
-
-static void start_duration_base(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_duration_base(upb_json_parser *p, const char *ptr) {
-  size_t len;
-  const char *buf;
-  char seconds_buf[14];
-  char nanos_buf[12];
-  char *end;
-  int64_t seconds = 0;
-  int32_t nanos = 0;
-  double val = 0.0;
-  const char *seconds_membername = "seconds";
-  const char *nanos_membername = "nanos";
-  size_t fraction_start;
-
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-
-  buf = accumulate_getptr(p, &len);
-
-  memset(seconds_buf, 0, 14);
-  memset(nanos_buf, 0, 12);
-
-  /* Find out base end. The maximus duration is 315576000000, which cannot be
-   * represented by double without losing precision. Thus, we need to handle
-   * fraction and base separately. */
-  for (fraction_start = 0; fraction_start < len && buf[fraction_start] != '.';
-       fraction_start++);
-
-  /* Parse base */
-  memcpy(seconds_buf, buf, fraction_start);
-  seconds = strtol(seconds_buf, &end, 10);
-  if (errno == ERANGE || end != seconds_buf + fraction_start) {
-    upb_status_seterrf(p->status, "error parsing duration: %s",
-                       seconds_buf);
-    return false;
-  }
-
-  if (seconds > 315576000000) {
-    upb_status_seterrf(p->status, "error parsing duration: "
-                                   "maximum acceptable value is "
-                                   "315576000000");
-    return false;
-  }
-
-  if (seconds < -315576000000) {
-    upb_status_seterrf(p->status, "error parsing duration: "
-                                   "minimum acceptable value is "
-                                   "-315576000000");
-    return false;
-  }
-
-  /* Parse fraction */
-  nanos_buf[0] = '0';
-  memcpy(nanos_buf + 1, buf + fraction_start, len - fraction_start);
-  val = strtod(nanos_buf, &end);
-  if (errno == ERANGE || end != nanos_buf + len - fraction_start + 1) {
-    upb_status_seterrf(p->status, "error parsing duration: %s",
-                       nanos_buf);
-    return false;
-  }
-
-  nanos = val * 1000000000;
-  if (seconds < 0) nanos = -nanos;
-
-  /* Clean up buffer */
-  multipart_end(p);
-
-  /* Set seconds */
-  start_member(p);
-  capture_begin(p, seconds_membername);
-  capture_end(p, seconds_membername + 7);
-  end_membername(p);
-  upb_sink_putint64(p->top->sink, parser_getsel(p), seconds);
-  end_member(p);
-
-  /* Set nanos */
-  start_member(p);
-  capture_begin(p, nanos_membername);
-  capture_end(p, nanos_membername + 5);
-  end_membername(p);
-  upb_sink_putint32(p->top->sink, parser_getsel(p), nanos);
-  end_member(p);
-
-  /* Continue previous arena */
-  multipart_startaccum(p);
-
-  return true;
-}
-
-static int parse_timestamp_number(upb_json_parser *p) {
-  size_t len;
-  const char *buf;
-  int val;
-
-  /* atoi() and friends unfortunately do not support specifying the length of
-   * the input string, so we need to force a copy into a NULL-terminated buffer. */
-  multipart_text(p, "\0", 1, false);
-
-  buf = accumulate_getptr(p, &len);
-  val = atoi(buf);
-  multipart_end(p);
-  multipart_startaccum(p);
-
-  return val;
-}
-
-static void start_year(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_year(upb_json_parser *p, const char *ptr) {
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-  p->tm.tm_year = parse_timestamp_number(p) - 1900;
-  return true;
-}
-
-static void start_month(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_month(upb_json_parser *p, const char *ptr) {
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-  p->tm.tm_mon = parse_timestamp_number(p) - 1;
-  return true;
-}
-
-static void start_day(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_day(upb_json_parser *p, const char *ptr) {
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-  p->tm.tm_mday = parse_timestamp_number(p);
-  return true;
-}
-
-static void start_hour(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_hour(upb_json_parser *p, const char *ptr) {
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-  p->tm.tm_hour = parse_timestamp_number(p);
-  return true;
-}
-
-static void start_minute(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_minute(upb_json_parser *p, const char *ptr) {
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-  p->tm.tm_min = parse_timestamp_number(p);
-  return true;
-}
-
-static void start_second(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_second(upb_json_parser *p, const char *ptr) {
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-  p->tm.tm_sec = parse_timestamp_number(p);
-  return true;
-}
-
-static void start_timestamp_base(upb_json_parser *p) {
-  memset(&p->tm, 0, sizeof(struct tm));
-}
-
-static void start_timestamp_fraction(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_timestamp_fraction(upb_json_parser *p, const char *ptr) {
-  size_t len;
-  const char *buf;
-  char nanos_buf[12];
-  char *end;
-  double val = 0.0;
-  int32_t nanos;
-  const char *nanos_membername = "nanos";
-
-  memset(nanos_buf, 0, 12);
-
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-
-  buf = accumulate_getptr(p, &len);
-
-  if (len > 10) {
-    upb_status_seterrf(p->status,
-        "error parsing timestamp: at most 9-digit fraction.");
-    return false;
-  }
-
-  /* Parse nanos */
-  nanos_buf[0] = '0';
-  memcpy(nanos_buf + 1, buf, len);
-  val = strtod(nanos_buf, &end);
-
-  if (errno == ERANGE || end != nanos_buf + len + 1) {
-    upb_status_seterrf(p->status, "error parsing timestamp nanos: %s",
-                       nanos_buf);
-    return false;
-  }
-
-  nanos = val * 1000000000;
-
-  /* Clean up previous environment */
-  multipart_end(p);
-
-  /* Set nanos */
-  start_member(p);
-  capture_begin(p, nanos_membername);
-  capture_end(p, nanos_membername + 5);
-  end_membername(p);
-  upb_sink_putint32(p->top->sink, parser_getsel(p), nanos);
-  end_member(p);
-
-  /* Continue previous environment */
-  multipart_startaccum(p);
-
-  return true;
-}
-
-static void start_timestamp_zone(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static int div_round_up2(int n, int d) {
-  return (n + d - 1) / d;
-}
-
-/* epoch_days(1970, 1, 1) == 1970-01-01 == 0. */
-static int epoch_days(int year, int month, int day) {
-  static const uint16_t month_yday[12] = {0,   31,  59,  90,  120, 151,
-                                          181, 212, 243, 273, 304, 334};
-  int febs_since_0 = month > 2 ? year + 1 : year;
-  int leap_days_since_0 = div_round_up2(febs_since_0, 4) -
-                          div_round_up2(febs_since_0, 100) +
-                          div_round_up2(febs_since_0, 400);
-  int days_since_0 =
-      365 * year + month_yday[month - 1] + (day - 1) + leap_days_since_0;
-
-  /* Convert from 0-epoch (0001-01-01 BC) to Unix Epoch (1970-01-01 AD).
-   * Since the "BC" system does not have a year zero, 1 BC == year zero. */
-  return days_since_0 - 719528;
-}
-
-static int64_t upb_timegm(const struct tm *tp) {
-  int64_t ret = epoch_days(tp->tm_year + 1900, tp->tm_mon + 1, tp->tm_mday);
-  ret = (ret * 24) + tp->tm_hour;
-  ret = (ret * 60) + tp->tm_min;
-  ret = (ret * 60) + tp->tm_sec;
-  return ret;
-}
-
-static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) {
-  size_t len;
-  const char *buf;
-  int hours;
-  int64_t seconds;
-  const char *seconds_membername = "seconds";
-
-  if (!capture_end(p, ptr)) {
-    return false;
-  }
-
-  buf = accumulate_getptr(p, &len);
-
-  if (buf[0] != 'Z') {
-    if (sscanf(buf + 1, "%2d:00", &hours) != 1) {
-      upb_status_seterrf(p->status, "error parsing timestamp offset");
-      return false;
-    }
-
-    if (buf[0] == '+') {
-      hours = -hours;
-    }
-
-    p->tm.tm_hour += hours;
-  }
-
-  /* Normalize tm */
-  seconds = upb_timegm(&p->tm);
-
-  /* Check timestamp boundary */
-  if (seconds < -62135596800) {
-    upb_status_seterrf(p->status, "error parsing timestamp: "
-                                   "minimum acceptable value is "
-                                   "0001-01-01T00:00:00Z");
-    return false;
-  }
-
-  /* Clean up previous environment */
-  multipart_end(p);
-
-  /* Set seconds */
-  start_member(p);
-  capture_begin(p, seconds_membername);
-  capture_end(p, seconds_membername + 7);
-  end_membername(p);
-  upb_sink_putint64(p->top->sink, parser_getsel(p), seconds);
-  end_member(p);
-
-  /* Continue previous environment */
-  multipart_startaccum(p);
-
-  return true;
-}
-
-static void start_fieldmask_path_text(upb_json_parser *p, const char *ptr) {
-  capture_begin(p, ptr);
-}
-
-static bool end_fieldmask_path_text(upb_json_parser *p, const char *ptr) {
-  return capture_end(p, ptr);
-}
-
-static bool start_fieldmask_path(upb_json_parser *p) {
-  upb_jsonparser_frame *inner;
-  upb_selector_t sel;
-
-  if (!check_stack(p)) return false;
-
-  /* Start a new parser frame: parser frames correspond one-to-one with
-   * handler frames, and string events occur in a sub-frame. */
-  inner = start_jsonparser_frame(p);
-  sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
-  upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
-  inner->m = p->top->m;
-  inner->f = p->top->f;
-  p->top = inner;
-
-  multipart_startaccum(p);
-  return true;
-}
-
-static bool lower_camel_push(
-    upb_json_parser *p, upb_selector_t sel, const char *ptr, size_t len) {
-  const char *limit = ptr + len;
-  bool first = true;
-  for (;ptr < limit; ptr++) {
-    if (*ptr >= 'A' && *ptr <= 'Z' && !first) {
-      char lower = tolower(*ptr);
-      upb_sink_putstring(p->top->sink, sel, "_", 1, NULL);
-      upb_sink_putstring(p->top->sink, sel, &lower, 1, NULL);
-    } else {
-      upb_sink_putstring(p->top->sink, sel, ptr, 1, NULL);
-    }
-    first = false;
-  }
-  return true;
-}
-
-static bool end_fieldmask_path(upb_json_parser *p) {
-  upb_selector_t sel;
-
-  if (!lower_camel_push(
-           p, getsel_for_handlertype(p, UPB_HANDLER_STRING),
-           p->accumulated, p->accumulated_len)) {
-    return false;
-  }
-
-  sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
-  upb_sink_endstr(p->top->sink, sel);
-  p->top--;
-
-  multipart_end(p);
-  return true;
-}
-
-static void start_member(upb_json_parser *p) {
-  UPB_ASSERT(!p->top->f);
-  multipart_startaccum(p);
-}
-
-/* Helper: invoked during parse_mapentry() to emit the mapentry message's key
- * field based on the current contents of the accumulate buffer. */
-static bool parse_mapentry_key(upb_json_parser *p) {
-
-  size_t len;
-  const char *buf = accumulate_getptr(p, &len);
-
-  /* Emit the key field. We do a bit of ad-hoc parsing here because the
-   * parser state machine has already decided that this is a string field
-   * name, and we are reinterpreting it as some arbitrary key type. In
-   * particular, integer and bool keys are quoted, so we need to parse the
-   * quoted string contents here. */
-
-  p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY);
-  if (p->top->f == NULL) {
-    upb_status_seterrmsg(p->status, "mapentry message has no key");
-    return false;
-  }
-  switch (upb_fielddef_type(p->top->f)) {
-    case UPB_TYPE_INT32:
-    case UPB_TYPE_INT64:
-    case UPB_TYPE_UINT32:
-    case UPB_TYPE_UINT64:
-      /* Invoke end_number. The accum buffer has the number's text already. */
-      if (!parse_number(p, true)) {
-        return false;
-      }
-      break;
-    case UPB_TYPE_BOOL:
-      if (len == 4 && !strncmp(buf, "true", 4)) {
-        if (!parser_putbool(p, true)) {
-          return false;
-        }
-      } else if (len == 5 && !strncmp(buf, "false", 5)) {
-        if (!parser_putbool(p, false)) {
-          return false;
-        }
-      } else {
-        upb_status_seterrmsg(p->status,
-                             "Map bool key not 'true' or 'false'");
-        return false;
-      }
-      multipart_end(p);
-      break;
-    case UPB_TYPE_STRING:
-    case UPB_TYPE_BYTES: {
-      upb_sink subsink;
-      upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
-      upb_sink_startstr(p->top->sink, sel, len, &subsink);
-      sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
-      upb_sink_putstring(subsink, sel, buf, len, NULL);
-      sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
-      upb_sink_endstr(subsink, sel);
-      multipart_end(p);
-      break;
-    }
-    default:
-      upb_status_seterrmsg(p->status, "Invalid field type for map key");
-      return false;
-  }
-
-  return true;
-}
-
-/* Helper: emit one map entry (as a submessage in the map field sequence). This
- * is invoked from end_membername(), at the end of the map entry's key string,
- * with the map key in the accumulate buffer. It parses the key from that
- * buffer, emits the handler calls to start the mapentry submessage (setting up
- * its subframe in the process), and sets up state in the subframe so that the
- * value parser (invoked next) will emit the mapentry's value field and then
- * end the mapentry message. */
-
-static bool handle_mapentry(upb_json_parser *p) {
-  const upb_fielddef *mapfield;
-  const upb_msgdef *mapentrymsg;
-  upb_jsonparser_frame *inner;
-  upb_selector_t sel;
-
-  /* Map entry: p->top->sink is the seq frame, so we need to start a frame
-   * for the mapentry itself, and then set |f| in that frame so that the map
-   * value field is parsed, and also set a flag to end the frame after the
-   * map-entry value is parsed. */
-  if (!check_stack(p)) return false;
-
-  mapfield = p->top->mapfield;
-  mapentrymsg = upb_fielddef_msgsubdef(mapfield);
-
-  inner = start_jsonparser_frame(p);
-  p->top->f = mapfield;
-  sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
-  upb_sink_startsubmsg(p->top->sink, sel, &inner->sink);
-  inner->m = mapentrymsg;
-  inner->mapfield = mapfield;
-
-  /* Don't set this to true *yet* -- we reuse parsing handlers below to push
-   * the key field value to the sink, and these handlers will pop the frame
-   * if they see is_mapentry (when invoked by the parser state machine, they
-   * would have just seen the map-entry value, not key). */
-  inner->is_mapentry = false;
-  p->top = inner;
-
-  /* send STARTMSG in submsg frame. */
-  upb_sink_startmsg(p->top->sink);
-
-  parse_mapentry_key(p);
-
-  /* Set up the value field to receive the map-entry value. */
-  p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_VALUE);
-  p->top->is_mapentry = true;  /* set up to pop frame after value is parsed. */
-  p->top->mapfield = mapfield;
-  if (p->top->f == NULL) {
-    upb_status_seterrmsg(p->status, "mapentry message has no value");
-    return false;
-  }
-
-  return true;
-}
-
-static bool end_membername(upb_json_parser *p) {
-  UPB_ASSERT(!p->top->f);
-
-  if (!p->top->m) {
-    p->top->is_unknown_field = true;
-    multipart_end(p);
-    return true;
-  }
-
-  if (p->top->is_any) {
-    return end_any_membername(p);
-  } else if (p->top->is_map) {
-    return handle_mapentry(p);
-  } else {
-    size_t len;
-    const char *buf = accumulate_getptr(p, &len);
-    upb_value v;
-
-    if (upb_strtable_lookup2(p->top->name_table, buf, len, &v)) {
-      p->top->f = upb_value_getconstptr(v);
-      multipart_end(p);
-
-      return true;
-    } else if (p->ignore_json_unknown) {
-      p->top->is_unknown_field = true;
-      multipart_end(p);
-      return true;
-    } else {
-      upb_status_seterrf(p->status, "No such field: %.*s\n", (int)len, buf);
-      return false;
-    }
-  }
-}
-
-static bool end_any_membername(upb_json_parser *p) {
-  size_t len;
-  const char *buf = accumulate_getptr(p, &len);
-  upb_value v;
-
-  if (len == 5 && strncmp(buf, "@type", len) == 0) {
-    upb_strtable_lookup2(p->top->name_table, "type_url", 8, &v);
-    p->top->f = upb_value_getconstptr(v);
-    multipart_end(p);
-    return true;
-  } else {
-    p->top->is_unknown_field = true;
-    multipart_end(p);
-    return true;
-  }
-}
-
-static void end_member(upb_json_parser *p) {
-  /* If we just parsed a map-entry value, end that frame too. */
-  if (p->top->is_mapentry) {
-    upb_selector_t sel;
-    bool ok;
-    const upb_fielddef *mapfield;
-
-    UPB_ASSERT(p->top > p->stack);
-    /* send ENDMSG on submsg. */
-    upb_sink_endmsg(p->top->sink, p->status);
-    mapfield = p->top->mapfield;
-
-    /* send ENDSUBMSG in repeated-field-of-mapentries frame. */
-    p->top--;
-    ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel);
-    UPB_ASSUME(ok);
-    upb_sink_endsubmsg(p->top->sink, (p->top + 1)->sink, sel);
-  }
-
-  p->top->f = NULL;
-  p->top->is_unknown_field = false;
-}
-
-static void start_any_member(upb_json_parser *p, const char *ptr) {
-  start_member(p);
-  json_parser_any_frame_set_after_type_url_start_once(p->top->any_frame, ptr);
-}
-
-static void end_any_member(upb_json_parser *p, const char *ptr) {
-  json_parser_any_frame_set_before_type_url_end(p->top->any_frame, ptr);
-  end_member(p);
-}
-
-static bool start_subobject(upb_json_parser *p) {
-  if (p->top->is_unknown_field) {
-    if (!check_stack(p)) return false;
-
-    p->top = start_jsonparser_frame(p);
-    return true;
-  }
-
-  if (upb_fielddef_ismap(p->top->f)) {
-    upb_jsonparser_frame *inner;
-    upb_selector_t sel;
-
-    /* Beginning of a map. Start a new parser frame in a repeated-field
-     * context. */
-    if (!check_stack(p)) return false;
-
-    inner = start_jsonparser_frame(p);
-    sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
-    upb_sink_startseq(p->top->sink, sel, &inner->sink);
-    inner->m = upb_fielddef_msgsubdef(p->top->f);
-    inner->mapfield = p->top->f;
-    inner->is_map = true;
-    p->top = inner;
-
-    return true;
-  } else if (upb_fielddef_issubmsg(p->top->f)) {
-    upb_jsonparser_frame *inner;
-    upb_selector_t sel;
-
-    /* Beginning of a subobject. Start a new parser frame in the submsg
-     * context. */
-    if (!check_stack(p)) return false;
-
-    inner = start_jsonparser_frame(p);
-    sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
-    upb_sink_startsubmsg(p->top->sink, sel, &inner->sink);
-    inner->m = upb_fielddef_msgsubdef(p->top->f);
-    set_name_table(p, inner);
-    p->top = inner;
-
-    if (is_wellknown_msg(p, UPB_WELLKNOWN_ANY)) {
-      p->top->is_any = true;
-      p->top->any_frame = json_parser_any_frame_new(p);
-    } else {
-      p->top->is_any = false;
-      p->top->any_frame = NULL;
-    }
-
-    return true;
-  } else {
-    upb_status_seterrf(p->status,
-                       "Object specified for non-message/group field: %s",
-                       upb_fielddef_name(p->top->f));
-    return false;
-  }
-}
-
-static bool start_subobject_full(upb_json_parser *p) {
-  if (is_top_level(p)) {
-    if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-      start_value_object(p, VALUE_STRUCTVALUE);
-      if (!start_subobject(p)) return false;
-      start_structvalue_object(p);
-    } else if (is_wellknown_msg(p, UPB_WELLKNOWN_STRUCT)) {
-      start_structvalue_object(p);
-    } else {
-      return true;
-    }
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_STRUCT)) {
-    if (!start_subobject(p)) return false;
-    start_structvalue_object(p);
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE)) {
-    if (!start_subobject(p)) return false;
-    start_value_object(p, VALUE_STRUCTVALUE);
-    if (!start_subobject(p)) return false;
-    start_structvalue_object(p);
-  }
-
-  return start_subobject(p);
-}
-
-static void end_subobject(upb_json_parser *p) {
-  if (is_top_level(p)) {
-    return;
-  }
-
-  if (p->top->is_map) {
-    upb_selector_t sel;
-    p->top--;
-    sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
-    upb_sink_endseq(p->top->sink, sel);
-  } else {
-    upb_selector_t sel;
-    bool is_unknown = p->top->m == NULL;
-    p->top--;
-    if (!is_unknown) {
-      sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG);
-      upb_sink_endsubmsg(p->top->sink, (p->top + 1)->sink, sel);
-    }
-  }
-}
-
-static void end_subobject_full(upb_json_parser *p) {
-  end_subobject(p);
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_STRUCT)) {
-    end_structvalue_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-  }
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-    end_value_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-  }
-}
-
-static bool start_array(upb_json_parser *p) {
-  upb_jsonparser_frame *inner;
-  upb_selector_t sel;
-
-  if (is_top_level(p)) {
-    if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-      start_value_object(p, VALUE_LISTVALUE);
-      if (!start_subobject(p)) return false;
-      start_listvalue_object(p);
-    } else if (is_wellknown_msg(p, UPB_WELLKNOWN_LISTVALUE)) {
-      start_listvalue_object(p);
-    } else {
-      return false;
-    }
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_LISTVALUE) &&
-             (!upb_fielddef_isseq(p->top->f) ||
-              p->top->is_repeated)) {
-    if (!start_subobject(p)) return false;
-    start_listvalue_object(p);
-  } else if (is_wellknown_field(p, UPB_WELLKNOWN_VALUE) &&
-             (!upb_fielddef_isseq(p->top->f) ||
-              p->top->is_repeated)) {
-    if (!start_subobject(p)) return false;
-    start_value_object(p, VALUE_LISTVALUE);
-    if (!start_subobject(p)) return false;
-    start_listvalue_object(p);
-  }
-
-  if (p->top->is_unknown_field) {
-    inner = start_jsonparser_frame(p);
-    inner->is_unknown_field = true;
-    p->top = inner;
-
-    return true;
-  }
-
-  if (!upb_fielddef_isseq(p->top->f)) {
-    upb_status_seterrf(p->status,
-                       "Array specified for non-repeated field: %s",
-                       upb_fielddef_name(p->top->f));
-    return false;
-  }
-
-  if (!check_stack(p)) return false;
-
-  inner = start_jsonparser_frame(p);
-  sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
-  upb_sink_startseq(p->top->sink, sel, &inner->sink);
-  inner->m = p->top->m;
-  inner->f = p->top->f;
-  inner->is_repeated = true;
-  p->top = inner;
-
-  return true;
-}
-
-static void end_array(upb_json_parser *p) {
-  upb_selector_t sel;
-
-  UPB_ASSERT(p->top > p->stack);
-
-  p->top--;
-
-  if (p->top->is_unknown_field) {
-    return;
-  }
-
-  sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
-  upb_sink_endseq(p->top->sink, sel);
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_LISTVALUE)) {
-    end_listvalue_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-  }
-
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_VALUE)) {
-    end_value_object(p);
-    if (!is_top_level(p)) {
-      end_subobject(p);
-    }
-  }
-}
-
-static void start_object(upb_json_parser *p) {
-  if (!p->top->is_map && p->top->m != NULL) {
-    upb_sink_startmsg(p->top->sink);
-  }
-}
-
-static void end_object(upb_json_parser *p) {
-  if (!p->top->is_map && p->top->m != NULL) {
-    upb_sink_endmsg(p->top->sink, p->status);
-  }
-}
-
-static void start_any_object(upb_json_parser *p, const char *ptr) {
-  start_object(p);
-  p->top->any_frame->before_type_url_start = ptr;
-  p->top->any_frame->before_type_url_end = ptr;
-}
-
-static bool end_any_object(upb_json_parser *p, const char *ptr) {
-  const char *value_membername = "value";
-  bool is_well_known_packed = false;
-  const char *packed_end = ptr + 1;
-  upb_selector_t sel;
-  upb_jsonparser_frame *inner;
-
-  if (json_parser_any_frame_has_value(p->top->any_frame) &&
-      !json_parser_any_frame_has_type_url(p->top->any_frame)) {
-    upb_status_seterrmsg(p->status, "No valid type url");
-    return false;
-  }
-
-  /* Well known types data is represented as value field. */
-  if (upb_msgdef_wellknowntype(p->top->any_frame->parser->top->m) !=
-          UPB_WELLKNOWN_UNSPECIFIED) {
-    is_well_known_packed = true;
-
-    if (json_parser_any_frame_has_value_before_type_url(p->top->any_frame)) {
-      p->top->any_frame->before_type_url_start =
-          memchr(p->top->any_frame->before_type_url_start, ':',
-                 p->top->any_frame->before_type_url_end -
-                 p->top->any_frame->before_type_url_start);
-      if (p->top->any_frame->before_type_url_start == NULL) {
-        upb_status_seterrmsg(p->status, "invalid data for well known type.");
-        return false;
-      }
-      p->top->any_frame->before_type_url_start++;
-    }
-
-    if (json_parser_any_frame_has_value_after_type_url(p->top->any_frame)) {
-      p->top->any_frame->after_type_url_start =
-          memchr(p->top->any_frame->after_type_url_start, ':',
-                 (ptr + 1) -
-                 p->top->any_frame->after_type_url_start);
-      if (p->top->any_frame->after_type_url_start == NULL) {
-        upb_status_seterrmsg(p->status, "Invalid data for well known type.");
-        return false;
-      }
-      p->top->any_frame->after_type_url_start++;
-      packed_end = ptr;
-    }
-  }
-
-  if (json_parser_any_frame_has_value_before_type_url(p->top->any_frame)) {
-    if (!parse(p->top->any_frame->parser, NULL,
-               p->top->any_frame->before_type_url_start,
-               p->top->any_frame->before_type_url_end -
-               p->top->any_frame->before_type_url_start, NULL)) {
-      return false;
-    }
-  } else {
-    if (!is_well_known_packed) {
-      if (!parse(p->top->any_frame->parser, NULL, "{", 1, NULL)) {
-        return false;
-      }
-    }
-  }
-
-  if (json_parser_any_frame_has_value_before_type_url(p->top->any_frame) &&
-      json_parser_any_frame_has_value_after_type_url(p->top->any_frame)) {
-    if (!parse(p->top->any_frame->parser, NULL, ",", 1, NULL)) {
-      return false;
-    }
-  }
-
-  if (json_parser_any_frame_has_value_after_type_url(p->top->any_frame)) {
-    if (!parse(p->top->any_frame->parser, NULL,
-               p->top->any_frame->after_type_url_start,
-               packed_end - p->top->any_frame->after_type_url_start, NULL)) {
-      return false;
-    }
-  } else {
-    if (!is_well_known_packed) {
-      if (!parse(p->top->any_frame->parser, NULL, "}", 1, NULL)) {
-        return false;
-      }
-    }
-  }
-
-  if (!end(p->top->any_frame->parser, NULL)) {
-    return false;
-  }
-
-  p->top->is_any = false;
-
-  /* Set value */
-  start_member(p);
-  capture_begin(p, value_membername);
-  capture_end(p, value_membername + 5);
-  end_membername(p);
-
-  if (!check_stack(p)) return false;
-  inner = p->top + 1;
-
-  sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
-  upb_sink_startstr(p->top->sink, sel, 0, &inner->sink);
-  sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
-  upb_sink_putstring(inner->sink, sel, p->top->any_frame->stringsink.ptr,
-                     p->top->any_frame->stringsink.len, NULL);
-  sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
-  upb_sink_endstr(inner->sink, sel);
-
-  end_member(p);
-
-  end_object(p);
-
-  /* Deallocate any parse frame. */
-  json_parser_any_frame_free(p->top->any_frame);
-
-  return true;
-}
-
-static bool is_string_wrapper(const upb_msgdef *m) {
-  upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
-  return type == UPB_WELLKNOWN_STRINGVALUE ||
-         type == UPB_WELLKNOWN_BYTESVALUE;
-}
-
-static bool is_fieldmask(const upb_msgdef *m) {
-  upb_wellknowntype_t type = upb_msgdef_wellknowntype(m);
-  return type == UPB_WELLKNOWN_FIELDMASK;
-}
-
-static void start_fieldmask_object(upb_json_parser *p) {
-  const char *membername = "paths";
-
-  start_object(p);
-
-  /* Set up context for parsing value */
-  start_member(p);
-  capture_begin(p, membername);
-  capture_end(p, membername + 5);
-  end_membername(p);
-
-  start_array(p);
-}
-
-static void end_fieldmask_object(upb_json_parser *p) {
-  end_array(p);
-  end_member(p);
-  end_object(p);
-}
-
-static void start_wrapper_object(upb_json_parser *p) {
-  const char *membername = "value";
-
-  start_object(p);
-
-  /* Set up context for parsing value */
-  start_member(p);
-  capture_begin(p, membername);
-  capture_end(p, membername + 5);
-  end_membername(p);
-}
-
-static void end_wrapper_object(upb_json_parser *p) {
-  end_member(p);
-  end_object(p);
-}
-
-static void start_value_object(upb_json_parser *p, int value_type) {
-  const char *nullmember = "null_value";
-  const char *numbermember = "number_value";
-  const char *stringmember = "string_value";
-  const char *boolmember = "bool_value";
-  const char *structmember = "struct_value";
-  const char *listmember = "list_value";
-  const char *membername = "";
-
-  switch (value_type) {
-    case VALUE_NULLVALUE:
-      membername = nullmember;
-      break;
-    case VALUE_NUMBERVALUE:
-      membername = numbermember;
-      break;
-    case VALUE_STRINGVALUE:
-      membername = stringmember;
-      break;
-    case VALUE_BOOLVALUE:
-      membername = boolmember;
-      break;
-    case VALUE_STRUCTVALUE:
-      membername = structmember;
-      break;
-    case VALUE_LISTVALUE:
-      membername = listmember;
-      break;
-  }
-
-  start_object(p);
-
-  /* Set up context for parsing value */
-  start_member(p);
-  capture_begin(p, membername);
-  capture_end(p, membername + strlen(membername));
-  end_membername(p);
-}
-
-static void end_value_object(upb_json_parser *p) {
-  end_member(p);
-  end_object(p);
-}
-
-static void start_listvalue_object(upb_json_parser *p) {
-  const char *membername = "values";
-
-  start_object(p);
-
-  /* Set up context for parsing value */
-  start_member(p);
-  capture_begin(p, membername);
-  capture_end(p, membername + strlen(membername));
-  end_membername(p);
-}
-
-static void end_listvalue_object(upb_json_parser *p) {
-  end_member(p);
-  end_object(p);
-}
-
-static void start_structvalue_object(upb_json_parser *p) {
-  const char *membername = "fields";
-
-  start_object(p);
-
-  /* Set up context for parsing value */
-  start_member(p);
-  capture_begin(p, membername);
-  capture_end(p, membername + strlen(membername));
-  end_membername(p);
-}
-
-static void end_structvalue_object(upb_json_parser *p) {
-  end_member(p);
-  end_object(p);
-}
-
-static bool is_top_level(upb_json_parser *p) {
-  return p->top == p->stack && p->top->f == NULL && !p->top->is_unknown_field;
-}
-
-static bool is_wellknown_msg(upb_json_parser *p, upb_wellknowntype_t type) {
-  return p->top->m != NULL && upb_msgdef_wellknowntype(p->top->m) == type;
-}
-
-static bool is_wellknown_field(upb_json_parser *p, upb_wellknowntype_t type) {
-  return p->top->f != NULL &&
-         upb_fielddef_issubmsg(p->top->f) &&
-         (upb_msgdef_wellknowntype(upb_fielddef_msgsubdef(p->top->f))
-              == type);
-}
-
-static bool does_number_wrapper_start(upb_json_parser *p) {
-  return p->top->f != NULL &&
-         upb_fielddef_issubmsg(p->top->f) &&
-         upb_msgdef_isnumberwrapper(upb_fielddef_msgsubdef(p->top->f));
-}
-
-static bool does_number_wrapper_end(upb_json_parser *p) {
-  return p->top->m != NULL && upb_msgdef_isnumberwrapper(p->top->m);
-}
-
-static bool is_number_wrapper_object(upb_json_parser *p) {
-  return p->top->m != NULL && upb_msgdef_isnumberwrapper(p->top->m);
-}
-
-static bool does_string_wrapper_start(upb_json_parser *p) {
-  return p->top->f != NULL &&
-         upb_fielddef_issubmsg(p->top->f) &&
-         is_string_wrapper(upb_fielddef_msgsubdef(p->top->f));
-}
-
-static bool does_string_wrapper_end(upb_json_parser *p) {
-  return p->top->m != NULL && is_string_wrapper(p->top->m);
-}
-
-static bool is_string_wrapper_object(upb_json_parser *p) {
-  return p->top->m != NULL && is_string_wrapper(p->top->m);
-}
-
-static bool does_fieldmask_start(upb_json_parser *p) {
-  return p->top->f != NULL &&
-         upb_fielddef_issubmsg(p->top->f) &&
-         is_fieldmask(upb_fielddef_msgsubdef(p->top->f));
-}
-
-static bool does_fieldmask_end(upb_json_parser *p) {
-  return p->top->m != NULL && is_fieldmask(p->top->m);
-}
-
-#define CHECK_RETURN_TOP(x) if (!(x)) goto error
-
-
-/* The actual parser **********************************************************/
-
-/* What follows is the Ragel parser itself.  The language is specified in Ragel
- * and the actions call our C functions above.
- *
- * Ragel has an extensive set of functionality, and we use only a small part of
- * it.  There are many action types but we only use a few:
- *
- *   ">" -- transition into a machine
- *   "%" -- transition out of a machine
- *   "@" -- transition into a final state of a machine.
- *
- * "@" transitions are tricky because a machine can transition into a final
- * state repeatedly.  But in some cases we know this can't happen, for example
- * a string which is delimited by a final '"' can only transition into its
- * final state once, when the closing '"' is seen. */
-
-
-#line 2780 "upb/json/parser.rl"
-
-
-
-#line 2583 "upb/json/parser.c"
-static const char _json_actions[] = {
-	0, 1, 0, 1, 1, 1, 3, 1, 
-	4, 1, 6, 1, 7, 1, 8, 1, 
-	9, 1, 11, 1, 12, 1, 13, 1, 
-	14, 1, 15, 1, 16, 1, 17, 1, 
-	18, 1, 19, 1, 20, 1, 22, 1, 
-	23, 1, 24, 1, 35, 1, 37, 1, 
-	39, 1, 40, 1, 42, 1, 43, 1, 
-	44, 1, 46, 1, 48, 1, 49, 1, 
-	50, 1, 51, 1, 53, 1, 54, 2, 
-	4, 9, 2, 5, 6, 2, 7, 3, 
-	2, 7, 9, 2, 21, 26, 2, 25, 
-	10, 2, 27, 28, 2, 29, 30, 2, 
-	32, 34, 2, 33, 31, 2, 38, 36, 
-	2, 40, 42, 2, 45, 2, 2, 46, 
-	54, 2, 47, 36, 2, 49, 54, 2, 
-	50, 54, 2, 51, 54, 2, 52, 41, 
-	2, 53, 54, 3, 32, 34, 35, 4, 
-	21, 26, 27, 28
-};
-
-static const short _json_key_offsets[] = {
-	0, 0, 12, 13, 18, 23, 28, 29, 
-	30, 31, 32, 33, 34, 35, 36, 37, 
-	38, 43, 44, 48, 53, 58, 63, 67, 
-	71, 74, 77, 79, 83, 87, 89, 91, 
-	96, 98, 100, 109, 115, 121, 127, 133, 
-	135, 139, 142, 144, 146, 149, 150, 154, 
-	156, 158, 160, 162, 163, 165, 167, 168, 
-	170, 172, 173, 175, 177, 178, 180, 182, 
-	183, 185, 187, 191, 193, 195, 196, 197, 
-	198, 199, 201, 206, 208, 210, 212, 221, 
-	222, 222, 222, 227, 232, 237, 238, 239, 
-	240, 241, 241, 242, 243, 244, 244, 245, 
-	246, 247, 247, 252, 253, 257, 262, 267, 
-	272, 276, 276, 279, 282, 285, 288, 291, 
-	294, 294, 294, 294, 294, 294
-};
-
-static const char _json_trans_keys[] = {
-	32, 34, 45, 91, 102, 110, 116, 123, 
-	9, 13, 48, 57, 34, 32, 93, 125, 
-	9, 13, 32, 44, 93, 9, 13, 32, 
-	93, 125, 9, 13, 97, 108, 115, 101, 
-	117, 108, 108, 114, 117, 101, 32, 34, 
-	125, 9, 13, 34, 32, 58, 9, 13, 
-	32, 93, 125, 9, 13, 32, 44, 125, 
-	9, 13, 32, 44, 125, 9, 13, 32, 
-	34, 9, 13, 45, 48, 49, 57, 48, 
-	49, 57, 46, 69, 101, 48, 57, 69, 
-	101, 48, 57, 43, 45, 48, 57, 48, 
-	57, 48, 57, 46, 69, 101, 48, 57, 
-	34, 92, 34, 92, 34, 47, 92, 98, 
-	102, 110, 114, 116, 117, 48, 57, 65, 
-	70, 97, 102, 48, 57, 65, 70, 97, 
-	102, 48, 57, 65, 70, 97, 102, 48, 
-	57, 65, 70, 97, 102, 34, 92, 45, 
-	48, 49, 57, 48, 49, 57, 46, 115, 
-	48, 57, 115, 48, 57, 34, 46, 115, 
-	48, 57, 48, 57, 48, 57, 48, 57, 
-	48, 57, 45, 48, 57, 48, 57, 45, 
-	48, 57, 48, 57, 84, 48, 57, 48, 
-	57, 58, 48, 57, 48, 57, 58, 48, 
-	57, 48, 57, 43, 45, 46, 90, 48, 
-	57, 48, 57, 58, 48, 48, 34, 48, 
-	57, 43, 45, 90, 48, 57, 34, 44, 
-	34, 44, 34, 44, 34, 45, 91, 102, 
-	110, 116, 123, 48, 57, 34, 32, 93, 
-	125, 9, 13, 32, 44, 93, 9, 13, 
-	32, 93, 125, 9, 13, 97, 108, 115, 
-	101, 117, 108, 108, 114, 117, 101, 32, 
-	34, 125, 9, 13, 34, 32, 58, 9, 
-	13, 32, 93, 125, 9, 13, 32, 44, 
-	125, 9, 13, 32, 44, 125, 9, 13, 
-	32, 34, 9, 13, 32, 9, 13, 32, 
-	9, 13, 32, 9, 13, 32, 9, 13, 
-	32, 9, 13, 32, 9, 13, 0
-};
-
-static const char _json_single_lengths[] = {
-	0, 8, 1, 3, 3, 3, 1, 1, 
-	1, 1, 1, 1, 1, 1, 1, 1, 
-	3, 1, 2, 3, 3, 3, 2, 2, 
-	1, 3, 0, 2, 2, 0, 0, 3, 
-	2, 2, 9, 0, 0, 0, 0, 2, 
-	2, 1, 2, 0, 1, 1, 2, 0, 
-	0, 0, 0, 1, 0, 0, 1, 0, 
-	0, 1, 0, 0, 1, 0, 0, 1, 
-	0, 0, 4, 0, 0, 1, 1, 1, 
-	1, 0, 3, 2, 2, 2, 7, 1, 
-	0, 0, 3, 3, 3, 1, 1, 1, 
-	1, 0, 1, 1, 1, 0, 1, 1, 
-	1, 0, 3, 1, 2, 3, 3, 3, 
-	2, 0, 1, 1, 1, 1, 1, 1, 
-	0, 0, 0, 0, 0, 0
-};
-
-static const char _json_range_lengths[] = {
-	0, 2, 0, 1, 1, 1, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	1, 0, 1, 1, 1, 1, 1, 1, 
-	1, 0, 1, 1, 1, 1, 1, 1, 
-	0, 0, 0, 3, 3, 3, 3, 0, 
-	1, 1, 0, 1, 1, 0, 1, 1, 
-	1, 1, 1, 0, 1, 1, 0, 1, 
-	1, 0, 1, 1, 0, 1, 1, 0, 
-	1, 1, 0, 1, 1, 0, 0, 0, 
-	0, 1, 1, 0, 0, 0, 1, 0, 
-	0, 0, 1, 1, 1, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 1, 0, 1, 1, 1, 1, 
-	1, 0, 1, 1, 1, 1, 1, 1, 
-	0, 0, 0, 0, 0, 0
-};
-
-static const short _json_index_offsets[] = {
-	0, 0, 11, 13, 18, 23, 28, 30, 
-	32, 34, 36, 38, 40, 42, 44, 46, 
-	48, 53, 55, 59, 64, 69, 74, 78, 
-	82, 85, 89, 91, 95, 99, 101, 103, 
-	108, 111, 114, 124, 128, 132, 136, 140, 
-	143, 147, 150, 153, 155, 158, 160, 164, 
-	166, 168, 170, 172, 174, 176, 178, 180, 
-	182, 184, 186, 188, 190, 192, 194, 196, 
-	198, 200, 202, 207, 209, 211, 213, 215, 
-	217, 219, 221, 226, 229, 232, 235, 244, 
-	246, 247, 248, 253, 258, 263, 265, 267, 
-	269, 271, 272, 274, 276, 278, 279, 281, 
-	283, 285, 286, 291, 293, 297, 302, 307, 
-	312, 316, 317, 320, 323, 326, 329, 332, 
-	335, 336, 337, 338, 339, 340
-};
-
-static const unsigned char _json_indicies[] = {
-	0, 2, 3, 4, 5, 6, 7, 8, 
-	0, 3, 1, 9, 1, 11, 12, 1, 
-	11, 10, 13, 14, 12, 13, 1, 14, 
-	1, 1, 14, 10, 15, 1, 16, 1, 
-	17, 1, 18, 1, 19, 1, 20, 1, 
-	21, 1, 22, 1, 23, 1, 24, 1, 
-	25, 26, 27, 25, 1, 28, 1, 29, 
-	30, 29, 1, 30, 1, 1, 30, 31, 
-	32, 33, 34, 32, 1, 35, 36, 27, 
-	35, 1, 36, 26, 36, 1, 37, 38, 
-	39, 1, 38, 39, 1, 41, 42, 42, 
-	40, 43, 1, 42, 42, 43, 40, 44, 
-	44, 45, 1, 45, 1, 45, 40, 41, 
-	42, 42, 39, 40, 47, 48, 46, 50, 
-	51, 49, 52, 52, 52, 52, 52, 52, 
-	52, 52, 53, 1, 54, 54, 54, 1, 
-	55, 55, 55, 1, 56, 56, 56, 1, 
-	57, 57, 57, 1, 59, 60, 58, 61, 
-	62, 63, 1, 64, 65, 1, 66, 67, 
-	1, 68, 1, 67, 68, 1, 69, 1, 
-	66, 67, 65, 1, 70, 1, 71, 1, 
-	72, 1, 73, 1, 74, 1, 75, 1, 
-	76, 1, 77, 1, 78, 1, 79, 1, 
-	80, 1, 81, 1, 82, 1, 83, 1, 
-	84, 1, 85, 1, 86, 1, 87, 1, 
-	88, 1, 89, 89, 90, 91, 1, 92, 
-	1, 93, 1, 94, 1, 95, 1, 96, 
-	1, 97, 1, 98, 1, 99, 99, 100, 
-	98, 1, 102, 1, 101, 104, 105, 103, 
-	1, 1, 101, 106, 107, 108, 109, 110, 
-	111, 112, 107, 1, 113, 1, 114, 115, 
-	117, 118, 1, 117, 116, 119, 120, 118, 
-	119, 1, 120, 1, 1, 120, 116, 121, 
-	1, 122, 1, 123, 1, 124, 1, 125, 
-	126, 1, 127, 1, 128, 1, 129, 130, 
-	1, 131, 1, 132, 1, 133, 134, 135, 
-	136, 134, 1, 137, 1, 138, 139, 138, 
-	1, 139, 1, 1, 139, 140, 141, 142, 
-	143, 141, 1, 144, 145, 136, 144, 1, 
-	145, 135, 145, 1, 146, 147, 147, 1, 
-	148, 148, 1, 149, 149, 1, 150, 150, 
-	1, 151, 151, 1, 152, 152, 1, 1, 
-	1, 1, 1, 1, 1, 0
-};
-
-static const char _json_trans_targs[] = {
-	1, 0, 2, 107, 3, 6, 10, 13, 
-	16, 106, 4, 3, 106, 4, 5, 7, 
-	8, 9, 108, 11, 12, 109, 14, 15, 
-	110, 16, 17, 111, 18, 18, 19, 20, 
-	21, 22, 111, 21, 22, 24, 25, 31, 
-	112, 26, 28, 27, 29, 30, 33, 113, 
-	34, 33, 113, 34, 32, 35, 36, 37, 
-	38, 39, 33, 113, 34, 41, 42, 46, 
-	42, 46, 43, 45, 44, 114, 48, 49, 
-	50, 51, 52, 53, 54, 55, 56, 57, 
-	58, 59, 60, 61, 62, 63, 64, 65, 
-	66, 67, 73, 72, 68, 69, 70, 71, 
-	72, 115, 74, 67, 72, 76, 116, 76, 
-	116, 77, 79, 81, 82, 85, 90, 94, 
-	98, 80, 117, 117, 83, 82, 80, 83, 
-	84, 86, 87, 88, 89, 117, 91, 92, 
-	93, 117, 95, 96, 97, 117, 98, 99, 
-	105, 100, 100, 101, 102, 103, 104, 105, 
-	103, 104, 117, 106, 106, 106, 106, 106, 
-	106
-};
-
-static const unsigned char _json_trans_actions[] = {
-	0, 0, 113, 107, 53, 0, 0, 0, 
-	125, 59, 45, 0, 55, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 101, 51, 47, 0, 0, 45, 
-	49, 49, 104, 0, 0, 0, 0, 0, 
-	3, 0, 0, 0, 0, 0, 5, 15, 
-	0, 0, 71, 7, 13, 0, 74, 9, 
-	9, 9, 77, 80, 11, 37, 37, 37, 
-	0, 0, 0, 39, 0, 41, 86, 0, 
-	0, 0, 17, 19, 0, 21, 23, 0, 
-	25, 27, 0, 29, 31, 0, 33, 35, 
-	0, 135, 83, 135, 0, 0, 0, 0, 
-	0, 92, 0, 89, 89, 98, 43, 0, 
-	131, 95, 113, 107, 53, 0, 0, 0, 
-	125, 59, 69, 110, 45, 0, 55, 0, 
-	0, 0, 0, 0, 0, 119, 0, 0, 
-	0, 122, 0, 0, 0, 116, 0, 101, 
-	51, 47, 0, 0, 45, 49, 49, 104, 
-	0, 0, 128, 0, 57, 63, 65, 61, 
-	67
-};
-
-static const unsigned char _json_eof_actions[] = {
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 1, 0, 1, 0, 0, 1, 1, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 0, 0, 0, 0, 0, 
-	0, 0, 0, 57, 63, 65, 61, 67, 
-	0, 0, 0, 0, 0, 0
-};
-
-static const int json_start = 1;
-
-static const int json_en_number_machine = 23;
-static const int json_en_string_machine = 32;
-static const int json_en_duration_machine = 40;
-static const int json_en_timestamp_machine = 47;
-static const int json_en_fieldmask_machine = 75;
-static const int json_en_value_machine = 78;
-static const int json_en_main = 1;
-
-
-#line 2783 "upb/json/parser.rl"
-
-size_t parse(void *closure, const void *hd, const char *buf, size_t size,
-             const upb_bufhandle *handle) {
-  upb_json_parser *parser = closure;
-
-  /* Variables used by Ragel's generated code. */
-  int cs = parser->current_state;
-  int *stack = parser->parser_stack;
-  int top = parser->parser_top;
-
-  const char *p = buf;
-  const char *pe = buf + size;
-  const char *eof = &eof_ch;
-
-  parser->handle = handle;
-
-  UPB_UNUSED(hd);
-  UPB_UNUSED(handle);
-
-  capture_resume(parser, buf);
-
-  
-#line 2861 "upb/json/parser.c"
-	{
-	int _klen;
-	unsigned int _trans;
-	const char *_acts;
-	unsigned int _nacts;
-	const char *_keys;
-
-	if ( p == pe )
-		goto _test_eof;
-	if ( cs == 0 )
-		goto _out;
-_resume:
-	_keys = _json_trans_keys + _json_key_offsets[cs];
-	_trans = _json_index_offsets[cs];
-
-	_klen = _json_single_lengths[cs];
-	if ( _klen > 0 ) {
-		const char *_lower = _keys;
-		const char *_mid;
-		const char *_upper = _keys + _klen - 1;
-		while (1) {
-			if ( _upper < _lower )
-				break;
-
-			_mid = _lower + ((_upper-_lower) >> 1);
-			if ( (*p) < *_mid )
-				_upper = _mid - 1;
-			else if ( (*p) > *_mid )
-				_lower = _mid + 1;
-			else {
-				_trans += (unsigned int)(_mid - _keys);
-				goto _match;
-			}
-		}
-		_keys += _klen;
-		_trans += _klen;
-	}
-
-	_klen = _json_range_lengths[cs];
-	if ( _klen > 0 ) {
-		const char *_lower = _keys;
-		const char *_mid;
-		const char *_upper = _keys + (_klen<<1) - 2;
-		while (1) {
-			if ( _upper < _lower )
-				break;
-
-			_mid = _lower + (((_upper-_lower) >> 1) & ~1);
-			if ( (*p) < _mid[0] )
-				_upper = _mid - 2;
-			else if ( (*p) > _mid[1] )
-				_lower = _mid + 2;
-			else {
-				_trans += (unsigned int)((_mid - _keys)>>1);
-				goto _match;
-			}
-		}
-		_trans += _klen;
-	}
-
-_match:
-	_trans = _json_indicies[_trans];
-	cs = _json_trans_targs[_trans];
-
-	if ( _json_trans_actions[_trans] == 0 )
-		goto _again;
-
-	_acts = _json_actions + _json_trans_actions[_trans];
-	_nacts = (unsigned int) *_acts++;
-	while ( _nacts-- > 0 )
-	{
-		switch ( *_acts++ )
-		{
-	case 1:
-#line 2588 "upb/json/parser.rl"
-	{ p--; {cs = stack[--top]; goto _again;} }
-	break;
-	case 2:
-#line 2590 "upb/json/parser.rl"
-	{ p--; {stack[top++] = cs; cs = 23;goto _again;} }
-	break;
-	case 3:
-#line 2594 "upb/json/parser.rl"
-	{ start_text(parser, p); }
-	break;
-	case 4:
-#line 2595 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_text(parser, p)); }
-	break;
-	case 5:
-#line 2601 "upb/json/parser.rl"
-	{ start_hex(parser); }
-	break;
-	case 6:
-#line 2602 "upb/json/parser.rl"
-	{ hexdigit(parser, p); }
-	break;
-	case 7:
-#line 2603 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_hex(parser)); }
-	break;
-	case 8:
-#line 2609 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(escape(parser, p)); }
-	break;
-	case 9:
-#line 2615 "upb/json/parser.rl"
-	{ p--; {cs = stack[--top]; goto _again;} }
-	break;
-	case 10:
-#line 2620 "upb/json/parser.rl"
-	{ start_year(parser, p); }
-	break;
-	case 11:
-#line 2621 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_year(parser, p)); }
-	break;
-	case 12:
-#line 2625 "upb/json/parser.rl"
-	{ start_month(parser, p); }
-	break;
-	case 13:
-#line 2626 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_month(parser, p)); }
-	break;
-	case 14:
-#line 2630 "upb/json/parser.rl"
-	{ start_day(parser, p); }
-	break;
-	case 15:
-#line 2631 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_day(parser, p)); }
-	break;
-	case 16:
-#line 2635 "upb/json/parser.rl"
-	{ start_hour(parser, p); }
-	break;
-	case 17:
-#line 2636 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_hour(parser, p)); }
-	break;
-	case 18:
-#line 2640 "upb/json/parser.rl"
-	{ start_minute(parser, p); }
-	break;
-	case 19:
-#line 2641 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_minute(parser, p)); }
-	break;
-	case 20:
-#line 2645 "upb/json/parser.rl"
-	{ start_second(parser, p); }
-	break;
-	case 21:
-#line 2646 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_second(parser, p)); }
-	break;
-	case 22:
-#line 2651 "upb/json/parser.rl"
-	{ start_duration_base(parser, p); }
-	break;
-	case 23:
-#line 2652 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_duration_base(parser, p)); }
-	break;
-	case 24:
-#line 2654 "upb/json/parser.rl"
-	{ p--; {cs = stack[--top]; goto _again;} }
-	break;
-	case 25:
-#line 2659 "upb/json/parser.rl"
-	{ start_timestamp_base(parser); }
-	break;
-	case 26:
-#line 2661 "upb/json/parser.rl"
-	{ start_timestamp_fraction(parser, p); }
-	break;
-	case 27:
-#line 2662 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); }
-	break;
-	case 28:
-#line 2664 "upb/json/parser.rl"
-	{ start_timestamp_zone(parser, p); }
-	break;
-	case 29:
-#line 2665 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); }
-	break;
-	case 30:
-#line 2667 "upb/json/parser.rl"
-	{ p--; {cs = stack[--top]; goto _again;} }
-	break;
-	case 31:
-#line 2672 "upb/json/parser.rl"
-	{ start_fieldmask_path_text(parser, p); }
-	break;
-	case 32:
-#line 2673 "upb/json/parser.rl"
-	{ end_fieldmask_path_text(parser, p); }
-	break;
-	case 33:
-#line 2678 "upb/json/parser.rl"
-	{ start_fieldmask_path(parser); }
-	break;
-	case 34:
-#line 2679 "upb/json/parser.rl"
-	{ end_fieldmask_path(parser); }
-	break;
-	case 35:
-#line 2685 "upb/json/parser.rl"
-	{ p--; {cs = stack[--top]; goto _again;} }
-	break;
-	case 36:
-#line 2690 "upb/json/parser.rl"
-	{
-        if (is_wellknown_msg(parser, UPB_WELLKNOWN_TIMESTAMP)) {
-          {stack[top++] = cs; cs = 47;goto _again;}
-        } else if (is_wellknown_msg(parser, UPB_WELLKNOWN_DURATION)) {
-          {stack[top++] = cs; cs = 40;goto _again;}
-        } else if (is_wellknown_msg(parser, UPB_WELLKNOWN_FIELDMASK)) {
-          {stack[top++] = cs; cs = 75;goto _again;}
-        } else {
-          {stack[top++] = cs; cs = 32;goto _again;}
-        }
-      }
-	break;
-	case 37:
-#line 2703 "upb/json/parser.rl"
-	{ p--; {stack[top++] = cs; cs = 78;goto _again;} }
-	break;
-	case 38:
-#line 2708 "upb/json/parser.rl"
-	{
-        if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
-          start_any_member(parser, p);
-        } else {
-          start_member(parser);
-        }
-      }
-	break;
-	case 39:
-#line 2715 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_membername(parser)); }
-	break;
-	case 40:
-#line 2718 "upb/json/parser.rl"
-	{
-        if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
-          end_any_member(parser, p);
-        } else {
-          end_member(parser);
-        }
-      }
-	break;
-	case 41:
-#line 2729 "upb/json/parser.rl"
-	{
-        if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
-          start_any_object(parser, p);
-        } else {
-          start_object(parser);
-        }
-      }
-	break;
-	case 42:
-#line 2738 "upb/json/parser.rl"
-	{
-        if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) {
-          CHECK_RETURN_TOP(end_any_object(parser, p));
-        } else {
-          end_object(parser);
-        }
-      }
-	break;
-	case 43:
-#line 2750 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(start_array(parser)); }
-	break;
-	case 44:
-#line 2754 "upb/json/parser.rl"
-	{ end_array(parser); }
-	break;
-	case 45:
-#line 2759 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(start_number(parser, p)); }
-	break;
-	case 46:
-#line 2760 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_number(parser, p)); }
-	break;
-	case 47:
-#line 2762 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(start_stringval(parser)); }
-	break;
-	case 48:
-#line 2763 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_stringval(parser)); }
-	break;
-	case 49:
-#line 2765 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_bool(parser, true)); }
-	break;
-	case 50:
-#line 2767 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_bool(parser, false)); }
-	break;
-	case 51:
-#line 2769 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_null(parser)); }
-	break;
-	case 52:
-#line 2771 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(start_subobject_full(parser)); }
-	break;
-	case 53:
-#line 2772 "upb/json/parser.rl"
-	{ end_subobject_full(parser); }
-	break;
-	case 54:
-#line 2777 "upb/json/parser.rl"
-	{ p--; {cs = stack[--top]; goto _again;} }
-	break;
-#line 3185 "upb/json/parser.c"
-		}
-	}
-
-_again:
-	if ( cs == 0 )
-		goto _out;
-	if ( ++p != pe )
-		goto _resume;
-	_test_eof: {}
-	if ( p == eof )
-	{
-	const char *__acts = _json_actions + _json_eof_actions[cs];
-	unsigned int __nacts = (unsigned int) *__acts++;
-	while ( __nacts-- > 0 ) {
-		switch ( *__acts++ ) {
-	case 0:
-#line 2586 "upb/json/parser.rl"
-	{ p--; {cs = stack[--top]; 	if ( p == pe )
-		goto _test_eof;
-goto _again;} }
-	break;
-	case 46:
-#line 2760 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_number(parser, p)); }
-	break;
-	case 49:
-#line 2765 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_bool(parser, true)); }
-	break;
-	case 50:
-#line 2767 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_bool(parser, false)); }
-	break;
-	case 51:
-#line 2769 "upb/json/parser.rl"
-	{ CHECK_RETURN_TOP(end_null(parser)); }
-	break;
-	case 53:
-#line 2772 "upb/json/parser.rl"
-	{ end_subobject_full(parser); }
-	break;
-#line 3227 "upb/json/parser.c"
-		}
-	}
-	}
-
-	_out: {}
-	}
-
-#line 2805 "upb/json/parser.rl"
-
-  if (p != pe) {
-    upb_status_seterrf(parser->status, "Parse error at '%.*s'\n", pe - p, p);
-  } else {
-    capture_suspend(parser, &p);
-  }
-
-error:
-  /* Save parsing state back to parser. */
-  parser->current_state = cs;
-  parser->parser_top = top;
-
-  return p - buf;
-}
-
-static bool end(void *closure, const void *hd) {
-  upb_json_parser *parser = closure;
-
-  /* Prevent compile warning on unused static constants. */
-  UPB_UNUSED(json_start);
-  UPB_UNUSED(json_en_duration_machine);
-  UPB_UNUSED(json_en_fieldmask_machine);
-  UPB_UNUSED(json_en_number_machine);
-  UPB_UNUSED(json_en_string_machine);
-  UPB_UNUSED(json_en_timestamp_machine);
-  UPB_UNUSED(json_en_value_machine);
-  UPB_UNUSED(json_en_main);
-
-  parse(parser, hd, &eof_ch, 0, NULL);
-
-  return parser->current_state >= 106;
-}
-
-static void json_parser_reset(upb_json_parser *p) {
-  int cs;
-  int top;
-
-  p->top = p->stack;
-  init_frame(p->top);
-
-  /* Emit Ragel initialization of the parser. */
-  
-#line 3278 "upb/json/parser.c"
-	{
-	cs = json_start;
-	top = 0;
-	}
-
-#line 2847 "upb/json/parser.rl"
-  p->current_state = cs;
-  p->parser_top = top;
-  accumulate_clear(p);
-  p->multipart_state = MULTIPART_INACTIVE;
-  p->capture = NULL;
-  p->accumulated = NULL;
-}
-
-static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c,
-                                               const upb_msgdef *md) {
-  upb_msg_field_iter i;
-  upb_alloc *alloc = upb_arena_alloc(c->arena);
-
-  upb_json_parsermethod *m = upb_malloc(alloc, sizeof(*m));
-
-  m->cache = c;
-
-  upb_byteshandler_init(&m->input_handler_);
-  upb_byteshandler_setstring(&m->input_handler_, parse, m);
-  upb_byteshandler_setendstr(&m->input_handler_, end, m);
-
-  upb_strtable_init2(&m->name_table, UPB_CTYPE_CONSTPTR, alloc);
-
-  /* Build name_table */
-
-  for(upb_msg_field_begin(&i, md);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    const upb_fielddef *f = upb_msg_iter_field(&i);
-    upb_value v = upb_value_constptr(f);
-    const char *name;
-
-    /* Add an entry for the JSON name. */
-    name = upb_fielddef_jsonname(f);
-    upb_strtable_insert3(&m->name_table, name, strlen(name), v, alloc);
-
-    if (strcmp(name, upb_fielddef_name(f)) != 0) {
-      /* Since the JSON name is different from the regular field name, add an
-       * entry for the raw name (compliant proto3 JSON parsers must accept
-       * both). */
-      const char *name = upb_fielddef_name(f);
-      upb_strtable_insert3(&m->name_table, name, strlen(name), v, alloc);
-    }
-  }
-
-  return m;
-}
-
-/* Public API *****************************************************************/
-
-upb_json_parser *upb_json_parser_create(upb_arena *arena,
-                                        const upb_json_parsermethod *method,
-                                        const upb_symtab* symtab,
-                                        upb_sink output,
-                                        upb_status *status,
-                                        bool ignore_json_unknown) {
-#ifndef NDEBUG
-  const size_t size_before = upb_arena_bytesallocated(arena);
-#endif
-  upb_json_parser *p = upb_arena_malloc(arena, sizeof(upb_json_parser));
-  if (!p) return false;
-
-  p->arena = arena;
-  p->method = method;
-  p->status = status;
-  p->limit = p->stack + UPB_JSON_MAX_DEPTH;
-  p->accumulate_buf = NULL;
-  p->accumulate_buf_size = 0;
-  upb_bytessink_reset(&p->input_, &method->input_handler_, p);
-
-  json_parser_reset(p);
-  p->top->sink = output;
-  p->top->m = upb_handlers_msgdef(output.handlers);
-  if (is_wellknown_msg(p, UPB_WELLKNOWN_ANY)) {
-    p->top->is_any = true;
-    p->top->any_frame = json_parser_any_frame_new(p);
-  } else {
-    p->top->is_any = false;
-    p->top->any_frame = NULL;
-  }
-  set_name_table(p, p->top);
-  p->symtab = symtab;
-
-  p->ignore_json_unknown = ignore_json_unknown;
-
-  /* If this fails, uncomment and increase the value in parser.h. */
-  /* fprintf(stderr, "%zd\n", upb_arena_bytesallocated(arena) - size_before); */
-  UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(arena) - size_before <=
-                      UPB_JSON_PARSER_SIZE);
-  return p;
-}
-
-upb_bytessink upb_json_parser_input(upb_json_parser *p) {
-  return p->input_;
-}
-
-const upb_byteshandler *upb_json_parsermethod_inputhandler(
-    const upb_json_parsermethod *m) {
-  return &m->input_handler_;
-}
-
-upb_json_codecache *upb_json_codecache_new(void) {
-  upb_alloc *alloc;
-  upb_json_codecache *c;
-
-  c = upb_gmalloc(sizeof(*c));
-
-  c->arena = upb_arena_new();
-  alloc = upb_arena_alloc(c->arena);
-
-  upb_inttable_init2(&c->methods, UPB_CTYPE_CONSTPTR, alloc);
-
-  return c;
-}
-
-void upb_json_codecache_free(upb_json_codecache *c) {
-  upb_arena_free(c->arena);
-  upb_gfree(c);
-}
-
-const upb_json_parsermethod *upb_json_codecache_get(upb_json_codecache *c,
-                                                    const upb_msgdef *md) {
-  upb_json_parsermethod *m;
-  upb_value v;
-  upb_msg_field_iter i;
-  upb_alloc *alloc = upb_arena_alloc(c->arena);
-
-  if (upb_inttable_lookupptr(&c->methods, md, &v)) {
-    return upb_value_getconstptr(v);
-  }
-
-  m = parsermethod_new(c, md);
-  v = upb_value_constptr(m);
-
-  if (!m) return NULL;
-  if (!upb_inttable_insertptr2(&c->methods, md, v, alloc)) return NULL;
-
-  /* Populate parser methods for all submessages, so the name tables will
-   * be available during parsing. */
-  for(upb_msg_field_begin(&i, md);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    upb_fielddef *f = upb_msg_iter_field(&i);
-
-    if (upb_fielddef_issubmsg(f)) {
-      const upb_msgdef *subdef = upb_fielddef_msgsubdef(f);
-      const upb_json_parsermethod *sub_method =
-          upb_json_codecache_get(c, subdef);
-
-      if (!sub_method) return NULL;
-    }
-  }
-
-  return m;
-}
-/*
-** This currently uses snprintf() to format primitives, and could be optimized
-** further.
-*/
-
-
-#include <ctype.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <string.h>
-#include <time.h>
-
-
-struct upb_json_printer {
-  upb_sink input_;
-  /* BytesSink closure. */
-  void *subc_;
-  upb_bytessink output_;
-
-  /* We track the depth so that we know when to emit startstr/endstr on the
-   * output. */
-  int depth_;
-
-  /* Have we emitted the first element? This state is necessary to emit commas
-   * without leaving a trailing comma in arrays/maps. We keep this state per
-   * frame depth.
-   *
-   * Why max_depth * 2? UPB_MAX_HANDLER_DEPTH counts depth as nested messages.
-   * We count frames (contexts in which we separate elements by commas) as both
-   * repeated fields and messages (maps), and the worst case is a
-   * message->repeated field->submessage->repeated field->... nesting. */
-  bool first_elem_[UPB_MAX_HANDLER_DEPTH * 2];
-
-  /* To print timestamp, printer needs to cache its seconds and nanos values
-   * and convert them when ending timestamp message. See comments of
-   * printer_sethandlers_timestamp for more detail. */
-  int64_t seconds;
-  int32_t nanos;
-};
-
-/* StringPiece; a pointer plus a length. */
-typedef struct {
-  char *ptr;
-  size_t len;
-} strpc;
-
-void freestrpc(void *ptr) {
-  strpc *pc = ptr;
-  upb_gfree(pc->ptr);
-  upb_gfree(pc);
-}
-
-typedef struct {
-  bool preserve_fieldnames;
-} upb_json_printercache;
-
-/* Convert fielddef name to JSON name and return as a string piece. */
-strpc *newstrpc(upb_handlers *h, const upb_fielddef *f,
-                bool preserve_fieldnames) {
-  /* TODO(haberman): handle malloc failure. */
-  strpc *ret = upb_gmalloc(sizeof(*ret));
-  if (preserve_fieldnames) {
-    ret->ptr = upb_gstrdup(upb_fielddef_name(f));
-    ret->len = strlen(ret->ptr);
-  } else {
-    ret->ptr = upb_gstrdup(upb_fielddef_jsonname(f));
-    ret->len = strlen(ret->ptr);
-  }
-
-  upb_handlers_addcleanup(h, ret, freestrpc);
-  return ret;
-}
-
-/* Convert a null-terminated const char* to a string piece. */
-strpc *newstrpc_str(upb_handlers *h, const char * str) {
-  strpc * ret = upb_gmalloc(sizeof(*ret));
-  ret->ptr = upb_gstrdup(str);
-  ret->len = strlen(str);
-  upb_handlers_addcleanup(h, ret, freestrpc);
-  return ret;
-}
-
-/* ------------ JSON string printing: values, maps, arrays ------------------ */
-
-static void print_data(
-    upb_json_printer *p, const char *buf, size_t len) {
-  /* TODO: Will need to change if we support pushback from the sink. */
-  size_t n = upb_bytessink_putbuf(p->output_, p->subc_, buf, len, NULL);
-  UPB_ASSERT(n == len);
-}
-
-static void print_comma(upb_json_printer *p) {
-  if (!p->first_elem_[p->depth_]) {
-    print_data(p, ",", 1);
-  }
-  p->first_elem_[p->depth_] = false;
-}
-
-/* Helpers that print properly formatted elements to the JSON output stream. */
-
-/* Used for escaping control chars in strings. */
-static const char kControlCharLimit = 0x20;
-
-UPB_INLINE bool is_json_escaped(char c) {
-  /* See RFC 4627. */
-  unsigned char uc = (unsigned char)c;
-  return uc < kControlCharLimit || uc == '"' || uc == '\\';
-}
-
-UPB_INLINE const char* json_nice_escape(char c) {
-  switch (c) {
-    case '"':  return "\\\"";
-    case '\\': return "\\\\";
-    case '\b': return "\\b";
-    case '\f': return "\\f";
-    case '\n': return "\\n";
-    case '\r': return "\\r";
-    case '\t': return "\\t";
-    default:   return NULL;
-  }
-}
-
-/* Write a properly escaped string chunk. The surrounding quotes are *not*
- * printed; this is so that the caller has the option of emitting the string
- * content in chunks. */
-static void putstring(upb_json_printer *p, const char *buf, size_t len) {
-  const char* unescaped_run = NULL;
-  unsigned int i;
-  for (i = 0; i < len; i++) {
-    char c = buf[i];
-    /* Handle escaping. */
-    if (is_json_escaped(c)) {
-      /* Use a "nice" escape, like \n, if one exists for this character. */
-      const char* escape = json_nice_escape(c);
-      /* If we don't have a specific 'nice' escape code, use a \uXXXX-style
-       * escape. */
-      char escape_buf[8];
-      if (!escape) {
-        unsigned char byte = (unsigned char)c;
-        _upb_snprintf(escape_buf, sizeof(escape_buf), "\\u%04x", (int)byte);
-        escape = escape_buf;
-      }
-
-      /* N.B. that we assume that the input encoding is equal to the output
-       * encoding (both UTF-8 for  now), so for chars >= 0x20 and != \, ", we
-       * can simply pass the bytes through. */
-
-      /* If there's a current run of unescaped chars, print that run first. */
-      if (unescaped_run) {
-        print_data(p, unescaped_run, &buf[i] - unescaped_run);
-        unescaped_run = NULL;
-      }
-      /* Then print the escape code. */
-      print_data(p, escape, strlen(escape));
-    } else {
-      /* Add to the current unescaped run of characters. */
-      if (unescaped_run == NULL) {
-        unescaped_run = &buf[i];
-      }
-    }
-  }
-
-  /* If the string ended in a run of unescaped characters, print that last run. */
-  if (unescaped_run) {
-    print_data(p, unescaped_run, &buf[len] - unescaped_run);
-  }
-}
-
-#define CHKLENGTH(x) if (!(x)) return -1;
-
-/* Helpers that format floating point values according to our custom formats.
- * Right now we use %.8g and %.17g for float/double, respectively, to match
- * proto2::util::JsonFormat's defaults.  May want to change this later. */
-
-const char neginf[] = "\"-Infinity\"";
-const char inf[] = "\"Infinity\"";
-
-static size_t fmt_double(double val, char* buf, size_t length) {
-  if (val == UPB_INFINITY) {
-    CHKLENGTH(length >= strlen(inf));
-    strcpy(buf, inf);
-    return strlen(inf);
-  } else if (val == -UPB_INFINITY) {
-    CHKLENGTH(length >= strlen(neginf));
-    strcpy(buf, neginf);
-    return strlen(neginf);
-  } else {
-    size_t n = _upb_snprintf(buf, length, "%.17g", val);
-    CHKLENGTH(n > 0 && n < length);
-    return n;
-  }
-}
-
-static size_t fmt_float(float val, char* buf, size_t length) {
-  size_t n = _upb_snprintf(buf, length, "%.8g", val);
-  CHKLENGTH(n > 0 && n < length);
-  return n;
-}
-
-static size_t fmt_bool(bool val, char* buf, size_t length) {
-  size_t n = _upb_snprintf(buf, length, "%s", (val ? "true" : "false"));
-  CHKLENGTH(n > 0 && n < length);
-  return n;
-}
-
-static size_t fmt_int64_as_number(int64_t val, char* buf, size_t length) {
-  size_t n = _upb_snprintf(buf, length, "%" PRId64, val);
-  CHKLENGTH(n > 0 && n < length);
-  return n;
-}
-
-static size_t fmt_uint64_as_number(uint64_t val, char* buf, size_t length) {
-  size_t n = _upb_snprintf(buf, length, "%" PRIu64, val);
-  CHKLENGTH(n > 0 && n < length);
-  return n;
-}
-
-static size_t fmt_int64_as_string(int64_t val, char* buf, size_t length) {
-  size_t n = _upb_snprintf(buf, length, "\"%" PRId64 "\"", val);
-  CHKLENGTH(n > 0 && n < length);
-  return n;
-}
-
-static size_t fmt_uint64_as_string(uint64_t val, char* buf, size_t length) {
-  size_t n = _upb_snprintf(buf, length, "\"%" PRIu64 "\"", val);
-  CHKLENGTH(n > 0 && n < length);
-  return n;
-}
-
-/* Print a map key given a field name. Called by scalar field handlers and by
- * startseq for repeated fields. */
-static bool putkey(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  const strpc *key = handler_data;
-  print_comma(p);
-  print_data(p, "\"", 1);
-  putstring(p, key->ptr, key->len);
-  print_data(p, "\":", 2);
-  return true;
-}
-
-#define CHKFMT(val) if ((val) == (size_t)-1) return false;
-#define CHK(val)    if (!(val)) return false;
-
-#define TYPE_HANDLERS(type, fmt_func)                                        \
-  static bool put##type(void *closure, const void *handler_data, type val) { \
-    upb_json_printer *p = closure;                                           \
-    char data[64];                                                           \
-    size_t length = fmt_func(val, data, sizeof(data));                       \
-    UPB_UNUSED(handler_data);                                                \
-    CHKFMT(length);                                                          \
-    print_data(p, data, length);                                             \
-    return true;                                                             \
-  }                                                                          \
-  static bool scalar_##type(void *closure, const void *handler_data,         \
-                            type val) {                                      \
-    CHK(putkey(closure, handler_data));                                      \
-    CHK(put##type(closure, handler_data, val));                              \
-    return true;                                                             \
-  }                                                                          \
-  static bool repeated_##type(void *closure, const void *handler_data,       \
-                              type val) {                                    \
-    upb_json_printer *p = closure;                                           \
-    print_comma(p);                                                          \
-    CHK(put##type(closure, handler_data, val));                              \
-    return true;                                                             \
-  }
-
-#define TYPE_HANDLERS_MAPKEY(type, fmt_func)                                 \
-  static bool putmapkey_##type(void *closure, const void *handler_data,      \
-                            type val) {                                      \
-    upb_json_printer *p = closure;                                           \
-    char data[64];                                                           \
-    size_t length = fmt_func(val, data, sizeof(data));                       \
-    UPB_UNUSED(handler_data);                                                \
-    print_data(p, "\"", 1);                                                  \
-    print_data(p, data, length);                                             \
-    print_data(p, "\":", 2);                                                 \
-    return true;                                                             \
-  }
-
-TYPE_HANDLERS(double,   fmt_double)
-TYPE_HANDLERS(float,    fmt_float)
-TYPE_HANDLERS(bool,     fmt_bool)
-TYPE_HANDLERS(int32_t,  fmt_int64_as_number)
-TYPE_HANDLERS(uint32_t, fmt_int64_as_number)
-TYPE_HANDLERS(int64_t,  fmt_int64_as_string)
-TYPE_HANDLERS(uint64_t, fmt_uint64_as_string)
-
-/* double and float are not allowed to be map keys. */
-TYPE_HANDLERS_MAPKEY(bool,     fmt_bool)
-TYPE_HANDLERS_MAPKEY(int32_t,  fmt_int64_as_number)
-TYPE_HANDLERS_MAPKEY(uint32_t, fmt_int64_as_number)
-TYPE_HANDLERS_MAPKEY(int64_t,  fmt_int64_as_number)
-TYPE_HANDLERS_MAPKEY(uint64_t, fmt_uint64_as_number)
-
-#undef TYPE_HANDLERS
-#undef TYPE_HANDLERS_MAPKEY
-
-typedef struct {
-  void *keyname;
-  const upb_enumdef *enumdef;
-} EnumHandlerData;
-
-static bool scalar_enum(void *closure, const void *handler_data,
-                        int32_t val) {
-  const EnumHandlerData *hd = handler_data;
-  upb_json_printer *p = closure;
-  const char *symbolic_name;
-
-  CHK(putkey(closure, hd->keyname));
-
-  symbolic_name = upb_enumdef_iton(hd->enumdef, val);
-  if (symbolic_name) {
-    print_data(p, "\"", 1);
-    putstring(p, symbolic_name, strlen(symbolic_name));
-    print_data(p, "\"", 1);
-  } else {
-    putint32_t(closure, NULL, val);
-  }
-
-  return true;
-}
-
-static void print_enum_symbolic_name(upb_json_printer *p,
-                                     const upb_enumdef *def,
-                                     int32_t val) {
-  const char *symbolic_name = upb_enumdef_iton(def, val);
-  if (symbolic_name) {
-    print_data(p, "\"", 1);
-    putstring(p, symbolic_name, strlen(symbolic_name));
-    print_data(p, "\"", 1);
-  } else {
-    putint32_t(p, NULL, val);
-  }
-}
-
-static bool repeated_enum(void *closure, const void *handler_data,
-                          int32_t val) {
-  const EnumHandlerData *hd = handler_data;
-  upb_json_printer *p = closure;
-  print_comma(p);
-
-  print_enum_symbolic_name(p, hd->enumdef, val);
-
-  return true;
-}
-
-static bool mapvalue_enum(void *closure, const void *handler_data,
-                          int32_t val) {
-  const EnumHandlerData *hd = handler_data;
-  upb_json_printer *p = closure;
-
-  print_enum_symbolic_name(p, hd->enumdef, val);
-
-  return true;
-}
-
-static void *scalar_startsubmsg(void *closure, const void *handler_data) {
-  return putkey(closure, handler_data) ? closure : UPB_BREAK;
-}
-
-static void *repeated_startsubmsg(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  print_comma(p);
-  return closure;
-}
-
-static void start_frame(upb_json_printer *p) {
-  p->depth_++;
-  p->first_elem_[p->depth_] = true;
-  print_data(p, "{", 1);
-}
-
-static void end_frame(upb_json_printer *p) {
-  print_data(p, "}", 1);
-  p->depth_--;
-}
-
-static bool printer_startmsg(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  if (p->depth_ == 0) {
-    upb_bytessink_start(p->output_, 0, &p->subc_);
-  }
-  start_frame(p);
-  return true;
-}
-
-static bool printer_endmsg(void *closure, const void *handler_data, upb_status *s) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(s);
-  end_frame(p);
-  if (p->depth_ == 0) {
-    upb_bytessink_end(p->output_);
-  }
-  return true;
-}
-
-static void *startseq(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  CHK(putkey(closure, handler_data));
-  p->depth_++;
-  p->first_elem_[p->depth_] = true;
-  print_data(p, "[", 1);
-  return closure;
-}
-
-static bool endseq(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  print_data(p, "]", 1);
-  p->depth_--;
-  return true;
-}
-
-static void *startmap(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  CHK(putkey(closure, handler_data));
-  p->depth_++;
-  p->first_elem_[p->depth_] = true;
-  print_data(p, "{", 1);
-  return closure;
-}
-
-static bool endmap(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  print_data(p, "}", 1);
-  p->depth_--;
-  return true;
-}
-
-static size_t putstr(void *closure, const void *handler_data, const char *str,
-                     size_t len, const upb_bufhandle *handle) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(handle);
-  putstring(p, str, len);
-  return len;
-}
-
-/* This has to Base64 encode the bytes, because JSON has no "bytes" type. */
-static size_t putbytes(void *closure, const void *handler_data, const char *str,
-                       size_t len, const upb_bufhandle *handle) {
-  upb_json_printer *p = closure;
-
-  /* This is the regular base64, not the "web-safe" version. */
-  static const char base64[] =
-      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-  /* Base64-encode. */
-  char data[16000];
-  const char *limit = data + sizeof(data);
-  const unsigned char *from = (const unsigned char*)str;
-  char *to = data;
-  size_t remaining = len;
-  size_t bytes;
-
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(handle);
-
-  print_data(p, "\"", 1);
-
-  while (remaining > 2) {
-    if (limit - to < 4) {
-      bytes = to - data;
-      putstring(p, data, bytes);
-      to = data;
-    }
-
-    to[0] = base64[from[0] >> 2];
-    to[1] = base64[((from[0] & 0x3) << 4) | (from[1] >> 4)];
-    to[2] = base64[((from[1] & 0xf) << 2) | (from[2] >> 6)];
-    to[3] = base64[from[2] & 0x3f];
-
-    remaining -= 3;
-    to += 4;
-    from += 3;
-  }
-
-  switch (remaining) {
-    case 2:
-      to[0] = base64[from[0] >> 2];
-      to[1] = base64[((from[0] & 0x3) << 4) | (from[1] >> 4)];
-      to[2] = base64[(from[1] & 0xf) << 2];
-      to[3] = '=';
-      to += 4;
-      from += 2;
-      break;
-    case 1:
-      to[0] = base64[from[0] >> 2];
-      to[1] = base64[((from[0] & 0x3) << 4)];
-      to[2] = '=';
-      to[3] = '=';
-      to += 4;
-      from += 1;
-      break;
-  }
-
-  bytes = to - data;
-  putstring(p, data, bytes);
-  print_data(p, "\"", 1);
-  return len;
-}
-
-static void *scalar_startstr(void *closure, const void *handler_data,
-                             size_t size_hint) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(size_hint);
-  CHK(putkey(closure, handler_data));
-  print_data(p, "\"", 1);
-  return p;
-}
-
-static size_t scalar_str(void *closure, const void *handler_data,
-                         const char *str, size_t len,
-                         const upb_bufhandle *handle) {
-  CHK(putstr(closure, handler_data, str, len, handle));
-  return len;
-}
-
-static bool scalar_endstr(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  print_data(p, "\"", 1);
-  return true;
-}
-
-static void *repeated_startstr(void *closure, const void *handler_data,
-                               size_t size_hint) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(size_hint);
-  print_comma(p);
-  print_data(p, "\"", 1);
-  return p;
-}
-
-static size_t repeated_str(void *closure, const void *handler_data,
-                           const char *str, size_t len,
-                           const upb_bufhandle *handle) {
-  CHK(putstr(closure, handler_data, str, len, handle));
-  return len;
-}
-
-static bool repeated_endstr(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  print_data(p, "\"", 1);
-  return true;
-}
-
-static void *mapkeyval_startstr(void *closure, const void *handler_data,
-                                size_t size_hint) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(size_hint);
-  print_data(p, "\"", 1);
-  return p;
-}
-
-static size_t mapkey_str(void *closure, const void *handler_data,
-                         const char *str, size_t len,
-                         const upb_bufhandle *handle) {
-  CHK(putstr(closure, handler_data, str, len, handle));
-  return len;
-}
-
-static bool mapkey_endstr(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  print_data(p, "\":", 2);
-  return true;
-}
-
-static bool mapvalue_endstr(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  print_data(p, "\"", 1);
-  return true;
-}
-
-static size_t scalar_bytes(void *closure, const void *handler_data,
-                           const char *str, size_t len,
-                           const upb_bufhandle *handle) {
-  CHK(putkey(closure, handler_data));
-  CHK(putbytes(closure, handler_data, str, len, handle));
-  return len;
-}
-
-static size_t repeated_bytes(void *closure, const void *handler_data,
-                             const char *str, size_t len,
-                             const upb_bufhandle *handle) {
-  upb_json_printer *p = closure;
-  print_comma(p);
-  CHK(putbytes(closure, handler_data, str, len, handle));
-  return len;
-}
-
-static size_t mapkey_bytes(void *closure, const void *handler_data,
-                           const char *str, size_t len,
-                           const upb_bufhandle *handle) {
-  upb_json_printer *p = closure;
-  CHK(putbytes(closure, handler_data, str, len, handle));
-  print_data(p, ":", 1);
-  return len;
-}
-
-static void set_enum_hd(upb_handlers *h,
-                        const upb_fielddef *f,
-                        bool preserve_fieldnames,
-                        upb_handlerattr *attr) {
-  EnumHandlerData *hd = upb_gmalloc(sizeof(EnumHandlerData));
-  hd->enumdef = upb_fielddef_enumsubdef(f);
-  hd->keyname = newstrpc(h, f, preserve_fieldnames);
-  upb_handlers_addcleanup(h, hd, upb_gfree);
-  attr->handler_data = hd;
-}
-
-/* Set up handlers for a mapentry submessage (i.e., an individual key/value pair
- * in a map).
- *
- * TODO: Handle missing key, missing value, out-of-order key/value, or repeated
- * key or value cases properly. The right way to do this is to allocate a
- * temporary structure at the start of a mapentry submessage, store key and
- * value data in it as key and value handlers are called, and then print the
- * key/value pair once at the end of the submessage. If we don't do this, we
- * should at least detect the case and throw an error. However, so far all of
- * our sources that emit mapentry messages do so canonically (with one key
- * field, and then one value field), so this is not a pressing concern at the
- * moment. */
-void printer_sethandlers_mapentry(const void *closure, bool preserve_fieldnames,
-                                  upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-
-  /* A mapentry message is printed simply as '"key": value'. Rather than
-   * special-case key and value for every type below, we just handle both
-   * fields explicitly here. */
-  const upb_fielddef* key_field = upb_msgdef_itof(md, UPB_MAPENTRY_KEY);
-  const upb_fielddef* value_field = upb_msgdef_itof(md, UPB_MAPENTRY_VALUE);
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  UPB_UNUSED(closure);
-
-  switch (upb_fielddef_type(key_field)) {
-    case UPB_TYPE_INT32:
-      upb_handlers_setint32(h, key_field, putmapkey_int32_t, &empty_attr);
-      break;
-    case UPB_TYPE_INT64:
-      upb_handlers_setint64(h, key_field, putmapkey_int64_t, &empty_attr);
-      break;
-    case UPB_TYPE_UINT32:
-      upb_handlers_setuint32(h, key_field, putmapkey_uint32_t, &empty_attr);
-      break;
-    case UPB_TYPE_UINT64:
-      upb_handlers_setuint64(h, key_field, putmapkey_uint64_t, &empty_attr);
-      break;
-    case UPB_TYPE_BOOL:
-      upb_handlers_setbool(h, key_field, putmapkey_bool, &empty_attr);
-      break;
-    case UPB_TYPE_STRING:
-      upb_handlers_setstartstr(h, key_field, mapkeyval_startstr, &empty_attr);
-      upb_handlers_setstring(h, key_field, mapkey_str, &empty_attr);
-      upb_handlers_setendstr(h, key_field, mapkey_endstr, &empty_attr);
-      break;
-    case UPB_TYPE_BYTES:
-      upb_handlers_setstring(h, key_field, mapkey_bytes, &empty_attr);
-      break;
-    default:
-      UPB_ASSERT(false);
-      break;
-  }
-
-  switch (upb_fielddef_type(value_field)) {
-    case UPB_TYPE_INT32:
-      upb_handlers_setint32(h, value_field, putint32_t, &empty_attr);
-      break;
-    case UPB_TYPE_INT64:
-      upb_handlers_setint64(h, value_field, putint64_t, &empty_attr);
-      break;
-    case UPB_TYPE_UINT32:
-      upb_handlers_setuint32(h, value_field, putuint32_t, &empty_attr);
-      break;
-    case UPB_TYPE_UINT64:
-      upb_handlers_setuint64(h, value_field, putuint64_t, &empty_attr);
-      break;
-    case UPB_TYPE_BOOL:
-      upb_handlers_setbool(h, value_field, putbool, &empty_attr);
-      break;
-    case UPB_TYPE_FLOAT:
-      upb_handlers_setfloat(h, value_field, putfloat, &empty_attr);
-      break;
-    case UPB_TYPE_DOUBLE:
-      upb_handlers_setdouble(h, value_field, putdouble, &empty_attr);
-      break;
-    case UPB_TYPE_STRING:
-      upb_handlers_setstartstr(h, value_field, mapkeyval_startstr, &empty_attr);
-      upb_handlers_setstring(h, value_field, putstr, &empty_attr);
-      upb_handlers_setendstr(h, value_field, mapvalue_endstr, &empty_attr);
-      break;
-    case UPB_TYPE_BYTES:
-      upb_handlers_setstring(h, value_field, putbytes, &empty_attr);
-      break;
-    case UPB_TYPE_ENUM: {
-      upb_handlerattr enum_attr = UPB_HANDLERATTR_INIT;
-      set_enum_hd(h, value_field, preserve_fieldnames, &enum_attr);
-      upb_handlers_setint32(h, value_field, mapvalue_enum, &enum_attr);
-      break;
-    }
-    case UPB_TYPE_MESSAGE:
-      /* No handler necessary -- the submsg handlers will print the message
-       * as appropriate. */
-      break;
-  }
-}
-
-static bool putseconds(void *closure, const void *handler_data,
-                       int64_t seconds) {
-  upb_json_printer *p = closure;
-  p->seconds = seconds;
-  UPB_UNUSED(handler_data);
-  return true;
-}
-
-static bool putnanos(void *closure, const void *handler_data,
-                     int32_t nanos) {
-  upb_json_printer *p = closure;
-  p->nanos = nanos;
-  UPB_UNUSED(handler_data);
-  return true;
-}
-
-static void *scalar_startstr_nokey(void *closure, const void *handler_data,
-                                   size_t size_hint) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(size_hint);
-  print_data(p, "\"", 1);
-  return p;
-}
-
-static size_t putstr_nokey(void *closure, const void *handler_data,
-                           const char *str, size_t len,
-                           const upb_bufhandle *handle) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(handle);
-  print_data(p, "\"", 1);
-  putstring(p, str, len);
-  print_data(p, "\"", 1);
-  return len + 2;
-}
-
-static void *startseq_nokey(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  p->depth_++;
-  p->first_elem_[p->depth_] = true;
-  print_data(p, "[", 1);
-  return closure;
-}
-
-static void *startseq_fieldmask(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  p->depth_++;
-  p->first_elem_[p->depth_] = true;
-  return closure;
-}
-
-static bool endseq_fieldmask(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  p->depth_--;
-  return true;
-}
-
-static void *repeated_startstr_fieldmask(
-    void *closure, const void *handler_data,
-    size_t size_hint) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(size_hint);
-  print_comma(p);
-  return p;
-}
-
-static size_t repeated_str_fieldmask(
-    void *closure, const void *handler_data,
-    const char *str, size_t len,
-    const upb_bufhandle *handle) {
-  const char* limit = str + len;
-  bool upper = false;
-  size_t result_len = 0;
-  for (; str < limit; str++) {
-    if (*str == '_') {
-      upper = true;
-      continue;
-    }
-    if (upper && *str >= 'a' && *str <= 'z') {
-      char upper_char = toupper(*str);
-      CHK(putstr(closure, handler_data, &upper_char, 1, handle));
-    } else {
-      CHK(putstr(closure, handler_data, str, 1, handle));
-    }
-    upper = false;
-    result_len++;
-  }
-  return result_len;
-}
-
-static void *startmap_nokey(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  p->depth_++;
-  p->first_elem_[p->depth_] = true;
-  print_data(p, "{", 1);
-  return closure;
-}
-
-static bool putnull(void *closure, const void *handler_data,
-                    int32_t null) {
-  upb_json_printer *p = closure;
-  print_data(p, "null", 4);
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(null);
-  return true;
-}
-
-static bool printer_startdurationmsg(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  if (p->depth_ == 0) {
-    upb_bytessink_start(p->output_, 0, &p->subc_);
-  }
-  return true;
-}
-
-#define UPB_DURATION_MAX_JSON_LEN 23
-#define UPB_DURATION_MAX_NANO_LEN 9
-
-static bool printer_enddurationmsg(void *closure, const void *handler_data,
-                                   upb_status *s) {
-  upb_json_printer *p = closure;
-  char buffer[UPB_DURATION_MAX_JSON_LEN];
-  size_t base_len;
-  size_t curr;
-  size_t i;
-
-  memset(buffer, 0, UPB_DURATION_MAX_JSON_LEN);
-
-  if (p->seconds < -315576000000) {
-    upb_status_seterrf(s, "error parsing duration: "
-                          "minimum acceptable value is "
-                          "-315576000000");
-    return false;
-  }
-
-  if (p->seconds > 315576000000) {
-    upb_status_seterrf(s, "error serializing duration: "
-                          "maximum acceptable value is "
-                          "315576000000");
-    return false;
-  }
-
-  _upb_snprintf(buffer, sizeof(buffer), "%ld", (long)p->seconds);
-  base_len = strlen(buffer);
-
-  if (p->nanos != 0) {
-    char nanos_buffer[UPB_DURATION_MAX_NANO_LEN + 3];
-    _upb_snprintf(nanos_buffer, sizeof(nanos_buffer), "%.9f",
-                  p->nanos / 1000000000.0);
-    /* Remove trailing 0. */
-    for (i = UPB_DURATION_MAX_NANO_LEN + 2;
-         nanos_buffer[i] == '0'; i--) {
-      nanos_buffer[i] = 0;
-    }
-    strcpy(buffer + base_len, nanos_buffer + 1);
-  }
-
-  curr = strlen(buffer);
-  strcpy(buffer + curr, "s");
-
-  p->seconds = 0;
-  p->nanos = 0;
-
-  print_data(p, "\"", 1);
-  print_data(p, buffer, strlen(buffer));
-  print_data(p, "\"", 1);
-
-  if (p->depth_ == 0) {
-    upb_bytessink_end(p->output_);
-  }
-
-  UPB_UNUSED(handler_data);
-  return true;
-}
-
-static bool printer_starttimestampmsg(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  if (p->depth_ == 0) {
-    upb_bytessink_start(p->output_, 0, &p->subc_);
-  }
-  return true;
-}
-
-#define UPB_TIMESTAMP_MAX_JSON_LEN 31
-#define UPB_TIMESTAMP_BEFORE_NANO_LEN 19
-#define UPB_TIMESTAMP_MAX_NANO_LEN 9
-
-static bool printer_endtimestampmsg(void *closure, const void *handler_data,
-                                    upb_status *s) {
-  upb_json_printer *p = closure;
-  char buffer[UPB_TIMESTAMP_MAX_JSON_LEN];
-  time_t time = p->seconds;
-  size_t curr;
-  size_t i;
-  size_t year_length =
-      strftime(buffer, UPB_TIMESTAMP_MAX_JSON_LEN, "%Y", gmtime(&time));
-
-  if (p->seconds < -62135596800) {
-    upb_status_seterrf(s, "error parsing timestamp: "
-                          "minimum acceptable value is "
-                          "0001-01-01T00:00:00Z");
-    return false;
-  }
-
-  if (p->seconds > 253402300799) {
-    upb_status_seterrf(s, "error parsing timestamp: "
-                          "maximum acceptable value is "
-                          "9999-12-31T23:59:59Z");
-    return false;
-  }
-
-  /* strftime doesn't guarantee 4 digits for year. Prepend 0 by ourselves. */
-  for (i = 0; i < 4 - year_length; i++) {
-    buffer[i] = '0';
-  }
-
-  strftime(buffer + (4 - year_length), UPB_TIMESTAMP_MAX_JSON_LEN,
-           "%Y-%m-%dT%H:%M:%S", gmtime(&time));
-  if (p->nanos != 0) {
-    char nanos_buffer[UPB_TIMESTAMP_MAX_NANO_LEN + 3];
-    _upb_snprintf(nanos_buffer, sizeof(nanos_buffer), "%.9f",
-                  p->nanos / 1000000000.0);
-    /* Remove trailing 0. */
-    for (i = UPB_TIMESTAMP_MAX_NANO_LEN + 2;
-         nanos_buffer[i] == '0'; i--) {
-      nanos_buffer[i] = 0;
-    }
-    strcpy(buffer + UPB_TIMESTAMP_BEFORE_NANO_LEN, nanos_buffer + 1);
-  }
-
-  curr = strlen(buffer);
-  strcpy(buffer + curr, "Z");
-
-  p->seconds = 0;
-  p->nanos = 0;
-
-  print_data(p, "\"", 1);
-  print_data(p, buffer, strlen(buffer));
-  print_data(p, "\"", 1);
-
-  if (p->depth_ == 0) {
-    upb_bytessink_end(p->output_);
-  }
-
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(s);
-  return true;
-}
-
-static bool printer_startmsg_noframe(void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  if (p->depth_ == 0) {
-    upb_bytessink_start(p->output_, 0, &p->subc_);
-  }
-  return true;
-}
-
-static bool printer_endmsg_noframe(
-    void *closure, const void *handler_data, upb_status *s) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(s);
-  if (p->depth_ == 0) {
-    upb_bytessink_end(p->output_);
-  }
-  return true;
-}
-
-static bool printer_startmsg_fieldmask(
-    void *closure, const void *handler_data) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  if (p->depth_ == 0) {
-    upb_bytessink_start(p->output_, 0, &p->subc_);
-  }
-  print_data(p, "\"", 1);
-  return true;
-}
-
-static bool printer_endmsg_fieldmask(
-    void *closure, const void *handler_data, upb_status *s) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(handler_data);
-  UPB_UNUSED(s);
-  print_data(p, "\"", 1);
-  if (p->depth_ == 0) {
-    upb_bytessink_end(p->output_);
-  }
-  return true;
-}
-
-static void *scalar_startstr_onlykey(
-    void *closure, const void *handler_data, size_t size_hint) {
-  upb_json_printer *p = closure;
-  UPB_UNUSED(size_hint);
-  CHK(putkey(closure, handler_data));
-  return p;
-}
-
-/* Set up handlers for an Any submessage. */
-void printer_sethandlers_any(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-
-  const upb_fielddef* type_field = upb_msgdef_itof(md, UPB_ANY_TYPE);
-  const upb_fielddef* value_field = upb_msgdef_itof(md, UPB_ANY_VALUE);
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  /* type_url's json name is "@type" */
-  upb_handlerattr type_name_attr = UPB_HANDLERATTR_INIT;
-  upb_handlerattr value_name_attr = UPB_HANDLERATTR_INIT;
-  strpc *type_url_json_name = newstrpc_str(h, "@type");
-  strpc *value_json_name = newstrpc_str(h, "value");
-
-  type_name_attr.handler_data = type_url_json_name;
-  value_name_attr.handler_data = value_json_name;
-
-  /* Set up handlers. */
-  upb_handlers_setstartmsg(h, printer_startmsg, &empty_attr);
-  upb_handlers_setendmsg(h, printer_endmsg, &empty_attr);
-
-  upb_handlers_setstartstr(h, type_field, scalar_startstr, &type_name_attr);
-  upb_handlers_setstring(h, type_field, scalar_str, &empty_attr);
-  upb_handlers_setendstr(h, type_field, scalar_endstr, &empty_attr);
-
-  /* This is not the full and correct JSON encoding for the Any value field. It
-   * requires further processing by the wrapper code based on the type URL.
-   */
-  upb_handlers_setstartstr(h, value_field, scalar_startstr_onlykey,
-                           &value_name_attr);
-
-  UPB_UNUSED(closure);
-}
-
-/* Set up handlers for a fieldmask submessage. */
-void printer_sethandlers_fieldmask(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-  const upb_fielddef* f = upb_msgdef_itof(md, 1);
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_setstartseq(h, f, startseq_fieldmask, &empty_attr);
-  upb_handlers_setendseq(h, f, endseq_fieldmask, &empty_attr);
-
-  upb_handlers_setstartmsg(h, printer_startmsg_fieldmask, &empty_attr);
-  upb_handlers_setendmsg(h, printer_endmsg_fieldmask, &empty_attr);
-
-  upb_handlers_setstartstr(h, f, repeated_startstr_fieldmask, &empty_attr);
-  upb_handlers_setstring(h, f, repeated_str_fieldmask, &empty_attr);
-
-  UPB_UNUSED(closure);
-}
-
-/* Set up handlers for a duration submessage. */
-void printer_sethandlers_duration(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-
-  const upb_fielddef* seconds_field =
-      upb_msgdef_itof(md, UPB_DURATION_SECONDS);
-  const upb_fielddef* nanos_field =
-      upb_msgdef_itof(md, UPB_DURATION_NANOS);
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_setstartmsg(h, printer_startdurationmsg, &empty_attr);
-  upb_handlers_setint64(h, seconds_field, putseconds, &empty_attr);
-  upb_handlers_setint32(h, nanos_field, putnanos, &empty_attr);
-  upb_handlers_setendmsg(h, printer_enddurationmsg, &empty_attr);
-
-  UPB_UNUSED(closure);
-}
-
-/* Set up handlers for a timestamp submessage. Instead of printing fields
- * separately, the json representation of timestamp follows RFC 3339 */
-void printer_sethandlers_timestamp(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-
-  const upb_fielddef* seconds_field =
-      upb_msgdef_itof(md, UPB_TIMESTAMP_SECONDS);
-  const upb_fielddef* nanos_field =
-      upb_msgdef_itof(md, UPB_TIMESTAMP_NANOS);
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_setstartmsg(h, printer_starttimestampmsg, &empty_attr);
-  upb_handlers_setint64(h, seconds_field, putseconds, &empty_attr);
-  upb_handlers_setint32(h, nanos_field, putnanos, &empty_attr);
-  upb_handlers_setendmsg(h, printer_endtimestampmsg, &empty_attr);
-
-  UPB_UNUSED(closure);
-}
-
-void printer_sethandlers_value(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-  upb_msg_field_iter i;
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr);
-  upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr);
-
-  upb_msg_field_begin(&i, md);
-  for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) {
-    const upb_fielddef *f = upb_msg_iter_field(&i);
-
-    switch (upb_fielddef_type(f)) {
-      case UPB_TYPE_ENUM:
-        upb_handlers_setint32(h, f, putnull, &empty_attr);
-        break;
-      case UPB_TYPE_DOUBLE:
-        upb_handlers_setdouble(h, f, putdouble, &empty_attr);
-        break;
-      case UPB_TYPE_STRING:
-        upb_handlers_setstartstr(h, f, scalar_startstr_nokey, &empty_attr);
-        upb_handlers_setstring(h, f, scalar_str, &empty_attr);
-        upb_handlers_setendstr(h, f, scalar_endstr, &empty_attr);
-        break;
-      case UPB_TYPE_BOOL:
-        upb_handlers_setbool(h, f, putbool, &empty_attr);
-        break;
-      case UPB_TYPE_MESSAGE:
-        break;
-      default:
-        UPB_ASSERT(false);
-        break;
-    }
-  }
-
-  UPB_UNUSED(closure);
-}
-
-#define WRAPPER_SETHANDLERS(wrapper, type, putmethod)                      \
-void printer_sethandlers_##wrapper(const void *closure, upb_handlers *h) { \
-  const upb_msgdef *md = upb_handlers_msgdef(h);                           \
-  const upb_fielddef* f = upb_msgdef_itof(md, 1);                          \
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;                \
-  upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr);      \
-  upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr);          \
-  upb_handlers_set##type(h, f, putmethod, &empty_attr);                    \
-  UPB_UNUSED(closure);                                                     \
-}
-
-WRAPPER_SETHANDLERS(doublevalue, double, putdouble)
-WRAPPER_SETHANDLERS(floatvalue,  float,  putfloat)
-WRAPPER_SETHANDLERS(int64value,  int64,  putint64_t)
-WRAPPER_SETHANDLERS(uint64value, uint64, putuint64_t)
-WRAPPER_SETHANDLERS(int32value,  int32,  putint32_t)
-WRAPPER_SETHANDLERS(uint32value, uint32, putuint32_t)
-WRAPPER_SETHANDLERS(boolvalue,   bool,   putbool)
-WRAPPER_SETHANDLERS(stringvalue, string, putstr_nokey)
-WRAPPER_SETHANDLERS(bytesvalue,  string, putbytes)
-
-#undef WRAPPER_SETHANDLERS
-
-void printer_sethandlers_listvalue(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-  const upb_fielddef* f = upb_msgdef_itof(md, 1);
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_setstartseq(h, f, startseq_nokey, &empty_attr);
-  upb_handlers_setendseq(h, f, endseq, &empty_attr);
-
-  upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr);
-  upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr);
-
-  upb_handlers_setstartsubmsg(h, f, repeated_startsubmsg, &empty_attr);
-
-  UPB_UNUSED(closure);
-}
-
-void printer_sethandlers_structvalue(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-  const upb_fielddef* f = upb_msgdef_itof(md, 1);
-
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-
-  upb_handlers_setstartseq(h, f, startmap_nokey, &empty_attr);
-  upb_handlers_setendseq(h, f, endmap, &empty_attr);
-
-  upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr);
-  upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr);
-
-  upb_handlers_setstartsubmsg(h, f, repeated_startsubmsg, &empty_attr);
-
-  UPB_UNUSED(closure);
-}
-
-void printer_sethandlers(const void *closure, upb_handlers *h) {
-  const upb_msgdef *md = upb_handlers_msgdef(h);
-  bool is_mapentry = upb_msgdef_mapentry(md);
-  upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT;
-  upb_msg_field_iter i;
-  const upb_json_printercache *cache = closure;
-  const bool preserve_fieldnames = cache->preserve_fieldnames;
-
-  if (is_mapentry) {
-    /* mapentry messages are sufficiently different that we handle them
-     * separately. */
-    printer_sethandlers_mapentry(closure, preserve_fieldnames, h);
-    return;
-  }
-
-  switch (upb_msgdef_wellknowntype(md)) {
-    case UPB_WELLKNOWN_UNSPECIFIED:
-      break;
-    case UPB_WELLKNOWN_ANY:
-      printer_sethandlers_any(closure, h);
-      return;
-    case UPB_WELLKNOWN_FIELDMASK:
-      printer_sethandlers_fieldmask(closure, h);
-      return;
-    case UPB_WELLKNOWN_DURATION:
-      printer_sethandlers_duration(closure, h);
-      return;
-    case UPB_WELLKNOWN_TIMESTAMP:
-      printer_sethandlers_timestamp(closure, h);
-      return;
-    case UPB_WELLKNOWN_VALUE:
-      printer_sethandlers_value(closure, h);
-      return;
-    case UPB_WELLKNOWN_LISTVALUE:
-      printer_sethandlers_listvalue(closure, h);
-      return;
-    case UPB_WELLKNOWN_STRUCT:
-      printer_sethandlers_structvalue(closure, h);
-      return;
-#define WRAPPER(wellknowntype, name)        \
-  case wellknowntype:                       \
-    printer_sethandlers_##name(closure, h); \
-    return;                                 \
-
-    WRAPPER(UPB_WELLKNOWN_DOUBLEVALUE, doublevalue);
-    WRAPPER(UPB_WELLKNOWN_FLOATVALUE, floatvalue);
-    WRAPPER(UPB_WELLKNOWN_INT64VALUE, int64value);
-    WRAPPER(UPB_WELLKNOWN_UINT64VALUE, uint64value);
-    WRAPPER(UPB_WELLKNOWN_INT32VALUE, int32value);
-    WRAPPER(UPB_WELLKNOWN_UINT32VALUE, uint32value);
-    WRAPPER(UPB_WELLKNOWN_BOOLVALUE, boolvalue);
-    WRAPPER(UPB_WELLKNOWN_STRINGVALUE, stringvalue);
-    WRAPPER(UPB_WELLKNOWN_BYTESVALUE, bytesvalue);
-
-#undef WRAPPER
-  }
-
-  upb_handlers_setstartmsg(h, printer_startmsg, &empty_attr);
-  upb_handlers_setendmsg(h, printer_endmsg, &empty_attr);
-
-#define TYPE(type, name, ctype)                                               \
-  case type:                                                                  \
-    if (upb_fielddef_isseq(f)) {                                              \
-      upb_handlers_set##name(h, f, repeated_##ctype, &empty_attr);            \
-    } else {                                                                  \
-      upb_handlers_set##name(h, f, scalar_##ctype, &name_attr);               \
-    }                                                                         \
-    break;
-
-  upb_msg_field_begin(&i, md);
-  for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) {
-    const upb_fielddef *f = upb_msg_iter_field(&i);
-
-    upb_handlerattr name_attr = UPB_HANDLERATTR_INIT;
-    name_attr.handler_data = newstrpc(h, f, preserve_fieldnames);
-
-    if (upb_fielddef_ismap(f)) {
-      upb_handlers_setstartseq(h, f, startmap, &name_attr);
-      upb_handlers_setendseq(h, f, endmap, &name_attr);
-    } else if (upb_fielddef_isseq(f)) {
-      upb_handlers_setstartseq(h, f, startseq, &name_attr);
-      upb_handlers_setendseq(h, f, endseq, &empty_attr);
-    }
-
-    switch (upb_fielddef_type(f)) {
-      TYPE(UPB_TYPE_FLOAT,  float,  float);
-      TYPE(UPB_TYPE_DOUBLE, double, double);
-      TYPE(UPB_TYPE_BOOL,   bool,   bool);
-      TYPE(UPB_TYPE_INT32,  int32,  int32_t);
-      TYPE(UPB_TYPE_UINT32, uint32, uint32_t);
-      TYPE(UPB_TYPE_INT64,  int64,  int64_t);
-      TYPE(UPB_TYPE_UINT64, uint64, uint64_t);
-      case UPB_TYPE_ENUM: {
-        /* For now, we always emit symbolic names for enums. We may want an
-         * option later to control this behavior, but we will wait for a real
-         * need first. */
-        upb_handlerattr enum_attr = UPB_HANDLERATTR_INIT;
-        set_enum_hd(h, f, preserve_fieldnames, &enum_attr);
-
-        if (upb_fielddef_isseq(f)) {
-          upb_handlers_setint32(h, f, repeated_enum, &enum_attr);
-        } else {
-          upb_handlers_setint32(h, f, scalar_enum, &enum_attr);
-        }
-
-        break;
-      }
-      case UPB_TYPE_STRING:
-        if (upb_fielddef_isseq(f)) {
-          upb_handlers_setstartstr(h, f, repeated_startstr, &empty_attr);
-          upb_handlers_setstring(h, f, repeated_str, &empty_attr);
-          upb_handlers_setendstr(h, f, repeated_endstr, &empty_attr);
-        } else {
-          upb_handlers_setstartstr(h, f, scalar_startstr, &name_attr);
-          upb_handlers_setstring(h, f, scalar_str, &empty_attr);
-          upb_handlers_setendstr(h, f, scalar_endstr, &empty_attr);
-        }
-        break;
-      case UPB_TYPE_BYTES:
-        /* XXX: this doesn't support strings that span buffers yet. The base64
-         * encoder will need to be made resumable for this to work properly. */
-        if (upb_fielddef_isseq(f)) {
-          upb_handlers_setstring(h, f, repeated_bytes, &empty_attr);
-        } else {
-          upb_handlers_setstring(h, f, scalar_bytes, &name_attr);
-        }
-        break;
-      case UPB_TYPE_MESSAGE:
-        if (upb_fielddef_isseq(f)) {
-          upb_handlers_setstartsubmsg(h, f, repeated_startsubmsg, &name_attr);
-        } else {
-          upb_handlers_setstartsubmsg(h, f, scalar_startsubmsg, &name_attr);
-        }
-        break;
-    }
-  }
-
-#undef TYPE
-}
-
-static void json_printer_reset(upb_json_printer *p) {
-  p->depth_ = 0;
-}
-
-
-/* Public API *****************************************************************/
-
-upb_json_printer *upb_json_printer_create(upb_arena *a, const upb_handlers *h,
-                                          upb_bytessink output) {
-#ifndef NDEBUG
-  size_t size_before = upb_arena_bytesallocated(a);
-#endif
-
-  upb_json_printer *p = upb_arena_malloc(a, sizeof(upb_json_printer));
-  if (!p) return NULL;
-
-  p->output_ = output;
-  json_printer_reset(p);
-  upb_sink_reset(&p->input_, h, p);
-  p->seconds = 0;
-  p->nanos = 0;
-
-  /* If this fails, increase the value in printer.h. */
-  UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(a) - size_before <=
-                      UPB_JSON_PRINTER_SIZE);
-  return p;
-}
-
-upb_sink upb_json_printer_input(upb_json_printer *p) {
-  return p->input_;
-}
-
-upb_handlercache *upb_json_printer_newcache(bool preserve_proto_fieldnames) {
-  upb_json_printercache *cache = upb_gmalloc(sizeof(*cache));
-  upb_handlercache *ret = upb_handlercache_new(printer_sethandlers, cache);
-
-  cache->preserve_fieldnames = preserve_proto_fieldnames;
-  upb_handlercache_addcleanup(ret, cache, upb_gfree);
-
-  return ret;
-}
-/* See port_def.inc.  This should #undef all macros #defined there. */
-
-#undef UPB_MAPTYPE_STRING
-#undef UPB_SIZE
-#undef UPB_PTR_AT
-#undef UPB_READ_ONEOF
-#undef UPB_WRITE_ONEOF
-#undef UPB_INLINE
-#undef UPB_FORCEINLINE
-#undef UPB_NOINLINE
-#undef UPB_NORETURN
-#undef UPB_MAX
-#undef UPB_MIN
-#undef UPB_UNUSED
-#undef UPB_ASSUME
-#undef UPB_ASSERT
-#undef UPB_ASSERT_DEBUGVAR
-#undef UPB_UNREACHABLE
-#undef UPB_INFINITY
-#undef UPB_MSVC_VSNPRINTF
-#undef _upb_snprintf
-#undef _upb_vsnprintf
-#undef _upb_va_copy
diff --git a/ruby/ext/google/protobuf_c/upb.h b/ruby/ext/google/protobuf_c/upb.h
deleted file mode 100644
index b7da76f..0000000
--- a/ruby/ext/google/protobuf_c/upb.h
+++ /dev/null
@@ -1,6777 +0,0 @@
-/* Amalgamated source file */
-#include <stdint.h>/*
-* This is where we define macros used across upb.
-*
-* All of these macros are undef'd in port_undef.inc to avoid leaking them to
-* users.
-*
-* The correct usage is:
-*
-*   #include "upb/foobar.h"
-*   #include "upb/baz.h"
-*
-*   // MUST be last included header.
-*   #include "upb/port_def.inc"
-*
-*   // Code for this file.
-*   // <...>
-*
-*   // Can be omitted for .c files, required for .h.
-*   #include "upb/port_undef.inc"
-*
-* This file is private and must not be included by users!
-*/
-#include <stdint.h>
-
-#if UINTPTR_MAX == 0xffffffff
-#define UPB_SIZE(size32, size64) size32
-#else
-#define UPB_SIZE(size32, size64) size64
-#endif
-
-/* If we always read/write as a consistent type to each address, this shouldn't
- * violate aliasing.
- */
-#define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs)))
-
-#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \
-  *UPB_PTR_AT(msg, case_offset, int) == case_val                              \
-      ? *UPB_PTR_AT(msg, offset, fieldtype)                                   \
-      : default
-
-#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \
-  *UPB_PTR_AT(msg, case_offset, int) = case_val;                             \
-  *UPB_PTR_AT(msg, offset, fieldtype) = value;
-
-#define UPB_MAPTYPE_STRING 0
-
-/* UPB_INLINE: inline if possible, emit standalone code if required. */
-#ifdef __cplusplus
-#define UPB_INLINE inline
-#elif defined (__GNUC__) || defined(__clang__)
-#define UPB_INLINE static __inline__
-#else
-#define UPB_INLINE static
-#endif
-
-/* Hints to the compiler about likely/unlikely branches. */
-#if defined (__GNUC__) || defined(__clang__)
-#define UPB_LIKELY(x) __builtin_expect((x),1)
-#define UPB_UNLIKELY(x) __builtin_expect((x),0)
-#else
-#define UPB_LIKELY(x) (x)
-#define UPB_UNLIKELY(x) (x)
-#endif
-
-/* Define UPB_BIG_ENDIAN manually if you're on big endian and your compiler
- * doesn't provide these preprocessor symbols. */
-#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
-#define UPB_BIG_ENDIAN
-#endif
-
-/* Macros for function attributes on compilers that support them. */
-#ifdef __GNUC__
-#define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
-#define UPB_NOINLINE __attribute__((noinline))
-#define UPB_NORETURN __attribute__((__noreturn__))
-#else  /* !defined(__GNUC__) */
-#define UPB_FORCEINLINE
-#define UPB_NOINLINE
-#define UPB_NORETURN
-#endif
-
-#if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L
-/* C99/C++11 versions. */
-#include <stdio.h>
-#define _upb_snprintf snprintf
-#define _upb_vsnprintf vsnprintf
-#define _upb_va_copy(a, b) va_copy(a, b)
-#elif defined(_MSC_VER)
-/* Microsoft C/C++ versions. */
-#include <stdarg.h>
-#include <stdio.h>
-#if _MSC_VER < 1900
-int msvc_snprintf(char* s, size_t n, const char* format, ...);
-int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg);
-#define UPB_MSVC_VSNPRINTF
-#define _upb_snprintf msvc_snprintf
-#define _upb_vsnprintf msvc_vsnprintf
-#else
-#define _upb_snprintf snprintf
-#define _upb_vsnprintf vsnprintf
-#endif
-#define _upb_va_copy(a, b) va_copy(a, b)
-#elif defined __GNUC__
-/* A few hacky workarounds for functions not in C89.
- * For internal use only!
- * TODO(haberman): fix these by including our own implementations, or finding
- * another workaround.
- */
-#define _upb_snprintf __builtin_snprintf
-#define _upb_vsnprintf __builtin_vsnprintf
-#define _upb_va_copy(a, b) __va_copy(a, b)
-#else
-#error Need implementations of [v]snprintf and va_copy
-#endif
-
-#ifdef __cplusplus
-#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || \
-    (defined(_MSC_VER) && _MSC_VER >= 1900)
-/* C++11 is present */
-#else
-#error upb requires C++11 for C++ support
-#endif
-#endif
-
-#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
-#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
-
-#define UPB_UNUSED(var) (void)var
-
-/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true.
- */
-#ifdef NDEBUG
-#ifdef __GNUC__
-#define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable()
-#else
-#define UPB_ASSUME(expr) do {} if (false && (expr))
-#endif
-#else
-#define UPB_ASSUME(expr) assert(expr)
-#endif
-
-/* UPB_ASSERT(): in release mode, we use the expression without letting it be
- * evaluated.  This prevents "unused variable" warnings. */
-#ifdef NDEBUG
-#define UPB_ASSERT(expr) do {} while (false && (expr))
-#else
-#define UPB_ASSERT(expr) assert(expr)
-#endif
-
-/* UPB_ASSERT_DEBUGVAR(): assert that uses functions or variables that only
- * exist in debug mode.  This turns into regular assert. */
-#define UPB_ASSERT_DEBUGVAR(expr) assert(expr)
-
-#if defined(__GNUC__) || defined(__clang__)
-#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0)
-#else
-#define UPB_UNREACHABLE() do { assert(0); } while(0)
-#endif
-
-/* UPB_INFINITY representing floating-point positive infinity. */
-#include <math.h>
-#ifdef INFINITY
-#define UPB_INFINITY INFINITY
-#else
-#define UPB_INFINITY (1.0 / 0.0)
-#endif
-/*
-** upb_decode: parsing into a upb_msg using a upb_msglayout.
-*/
-
-#ifndef UPB_DECODE_H_
-#define UPB_DECODE_H_
-
-/*
-** Our memory representation for parsing tables and messages themselves.
-** Functions in this file are used by generated code and possibly reflection.
-**
-** The definitions in this file are internal to upb.
-**/
-
-#ifndef UPB_MSG_H_
-#define UPB_MSG_H_
-
-#include <stdint.h>
-#include <string.h>
-
-/*
-** upb_table
-**
-** This header is INTERNAL-ONLY!  Its interfaces are not public or stable!
-** This file defines very fast int->upb_value (inttable) and string->upb_value
-** (strtable) hash tables.
-**
-** The table uses chained scatter with Brent's variation (inspired by the Lua
-** implementation of hash tables).  The hash function for strings is Austin
-** Appleby's "MurmurHash."
-**
-** The inttable uses uintptr_t as its key, which guarantees it can be used to
-** store pointers or integers of at least 32 bits (upb isn't really useful on
-** systems where sizeof(void*) < 4).
-**
-** The table must be homogeneous (all values of the same type).  In debug
-** mode, we check this on insert and lookup.
-*/
-
-#ifndef UPB_TABLE_H_
-#define UPB_TABLE_H_
-
-#include <stdint.h>
-#include <string.h>
-/*
-** This file contains shared definitions that are widely used across upb.
-*/
-
-#ifndef UPB_H_
-#define UPB_H_
-
-#include <assert.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* upb_status *****************************************************************/
-
-#define UPB_STATUS_MAX_MESSAGE 127
-
-typedef struct {
-  bool ok;
-  char msg[UPB_STATUS_MAX_MESSAGE];  /* Error message; NULL-terminated. */
-} upb_status;
-
-const char *upb_status_errmsg(const upb_status *status);
-bool upb_ok(const upb_status *status);
-
-/* These are no-op if |status| is NULL. */
-void upb_status_clear(upb_status *status);
-void upb_status_seterrmsg(upb_status *status, const char *msg);
-void upb_status_seterrf(upb_status *status, const char *fmt, ...);
-void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args);
-
-/** upb_strview ************************************************************/
-
-typedef struct {
-  const char *data;
-  size_t size;
-} upb_strview;
-
-UPB_INLINE upb_strview upb_strview_make(const char *data, size_t size) {
-  upb_strview ret;
-  ret.data = data;
-  ret.size = size;
-  return ret;
-}
-
-UPB_INLINE upb_strview upb_strview_makez(const char *data) {
-  return upb_strview_make(data, strlen(data));
-}
-
-UPB_INLINE bool upb_strview_eql(upb_strview a, upb_strview b) {
-  return a.size == b.size && memcmp(a.data, b.data, a.size) == 0;
-}
-
-#define UPB_STRVIEW_INIT(ptr, len) {ptr, len}
-
-#define UPB_STRVIEW_FORMAT "%.*s"
-#define UPB_STRVIEW_ARGS(view) (int)(view).size, (view).data
-
-/** upb_alloc *****************************************************************/
-
-/* A upb_alloc is a possibly-stateful allocator object.
- *
- * It could either be an arena allocator (which doesn't require individual
- * free() calls) or a regular malloc() (which does).  The client must therefore
- * free memory unless it knows that the allocator is an arena allocator. */
-
-struct upb_alloc;
-typedef struct upb_alloc upb_alloc;
-
-/* A malloc()/free() function.
- * If "size" is 0 then the function acts like free(), otherwise it acts like
- * realloc().  Only "oldsize" bytes from a previous allocation are preserved. */
-typedef void *upb_alloc_func(upb_alloc *alloc, void *ptr, size_t oldsize,
-                             size_t size);
-
-struct upb_alloc {
-  upb_alloc_func *func;
-};
-
-UPB_INLINE void *upb_malloc(upb_alloc *alloc, size_t size) {
-  UPB_ASSERT(alloc);
-  return alloc->func(alloc, NULL, 0, size);
-}
-
-UPB_INLINE void *upb_realloc(upb_alloc *alloc, void *ptr, size_t oldsize,
-                             size_t size) {
-  UPB_ASSERT(alloc);
-  return alloc->func(alloc, ptr, oldsize, size);
-}
-
-UPB_INLINE void upb_free(upb_alloc *alloc, void *ptr) {
-  assert(alloc);
-  alloc->func(alloc, ptr, 0, 0);
-}
-
-/* The global allocator used by upb.  Uses the standard malloc()/free(). */
-
-extern upb_alloc upb_alloc_global;
-
-/* Functions that hard-code the global malloc.
- *
- * We still get benefit because we can put custom logic into our global
- * allocator, like injecting out-of-memory faults in debug/testing builds. */
-
-UPB_INLINE void *upb_gmalloc(size_t size) {
-  return upb_malloc(&upb_alloc_global, size);
-}
-
-UPB_INLINE void *upb_grealloc(void *ptr, size_t oldsize, size_t size) {
-  return upb_realloc(&upb_alloc_global, ptr, oldsize, size);
-}
-
-UPB_INLINE void upb_gfree(void *ptr) {
-  upb_free(&upb_alloc_global, ptr);
-}
-
-/* upb_arena ******************************************************************/
-
-/* upb_arena is a specific allocator implementation that uses arena allocation.
- * The user provides an allocator that will be used to allocate the underlying
- * arena blocks.  Arenas by nature do not require the individual allocations
- * to be freed.  However the Arena does allow users to register cleanup
- * functions that will run when the arena is destroyed.
- *
- * A upb_arena is *not* thread-safe.
- *
- * You could write a thread-safe arena allocator that satisfies the
- * upb_alloc interface, but it would not be as efficient for the
- * single-threaded case. */
-
-typedef void upb_cleanup_func(void *ud);
-
-struct upb_arena;
-typedef struct upb_arena upb_arena;
-
-typedef struct {
-  /* We implement the allocator interface.
-   * This must be the first member of upb_arena! */
-  upb_alloc alloc;
-
-  char *ptr, *end;
-} _upb_arena_head;
-
-UPB_INLINE size_t _upb_arena_alignup(size_t size) {
-  const size_t maxalign = 16;
-  return ((size + maxalign - 1) / maxalign) * maxalign;
-}
-
-/* Creates an arena from the given initial block (if any -- n may be 0).
- * Additional blocks will be allocated from |alloc|.  If |alloc| is NULL, this
- * is a fixed-size arena and cannot grow. */
-upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc);
-void upb_arena_free(upb_arena *a);
-bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func);
-size_t upb_arena_bytesallocated(const upb_arena *a);
-void *_upb_arena_slowmalloc(upb_arena *a, size_t size);
-
-UPB_INLINE upb_alloc *upb_arena_alloc(upb_arena *a) { return (upb_alloc*)a; }
-
-UPB_INLINE void *upb_arena_malloc(upb_arena *a, size_t size) {
-  _upb_arena_head *h = (_upb_arena_head*)a;
-  size = _upb_arena_alignup(size);
-  if (UPB_LIKELY((size_t)(h->end - h->ptr) >= size)) {
-    void* ret = h->ptr;
-    h->ptr += size;
-    return ret;
-  } else {
-    return _upb_arena_slowmalloc(a, size);
-  }
-}
-
-UPB_INLINE void *upb_arena_realloc(upb_arena *a, void *ptr, size_t oldsize,
-                                   size_t size) {
-  if (oldsize == 0) {
-    return upb_arena_malloc(a, size);
-  } else {
-    return upb_realloc(upb_arena_alloc(a), ptr, oldsize, size);
-  }
-}
-
-UPB_INLINE upb_arena *upb_arena_new(void) {
-  return upb_arena_init(NULL, 0, &upb_alloc_global);
-}
-
-/* Constants ******************************************************************/
-
-/* Generic function type. */
-typedef void upb_func(void);
-
-/* A list of types as they are encoded on-the-wire. */
-typedef enum {
-  UPB_WIRE_TYPE_VARINT      = 0,
-  UPB_WIRE_TYPE_64BIT       = 1,
-  UPB_WIRE_TYPE_DELIMITED   = 2,
-  UPB_WIRE_TYPE_START_GROUP = 3,
-  UPB_WIRE_TYPE_END_GROUP   = 4,
-  UPB_WIRE_TYPE_32BIT       = 5
-} upb_wiretype_t;
-
-/* The types a field can have.  Note that this list is not identical to the
- * types defined in descriptor.proto, which gives INT32 and SINT32 separate
- * types (we distinguish the two with the "integer encoding" enum below). */
-typedef enum {
-  UPB_TYPE_BOOL     = 1,
-  UPB_TYPE_FLOAT    = 2,
-  UPB_TYPE_INT32    = 3,
-  UPB_TYPE_UINT32   = 4,
-  UPB_TYPE_ENUM     = 5,  /* Enum values are int32. */
-  UPB_TYPE_MESSAGE  = 6,
-  UPB_TYPE_DOUBLE   = 7,
-  UPB_TYPE_INT64    = 8,
-  UPB_TYPE_UINT64   = 9,
-  UPB_TYPE_STRING   = 10,
-  UPB_TYPE_BYTES    = 11
-} upb_fieldtype_t;
-
-/* The repeated-ness of each field; this matches descriptor.proto. */
-typedef enum {
-  UPB_LABEL_OPTIONAL = 1,
-  UPB_LABEL_REQUIRED = 2,
-  UPB_LABEL_REPEATED = 3
-} upb_label_t;
-
-/* Descriptor types, as defined in descriptor.proto. */
-typedef enum {
-  /* Old (long) names.  TODO(haberman): remove */
-  UPB_DESCRIPTOR_TYPE_DOUBLE   = 1,
-  UPB_DESCRIPTOR_TYPE_FLOAT    = 2,
-  UPB_DESCRIPTOR_TYPE_INT64    = 3,
-  UPB_DESCRIPTOR_TYPE_UINT64   = 4,
-  UPB_DESCRIPTOR_TYPE_INT32    = 5,
-  UPB_DESCRIPTOR_TYPE_FIXED64  = 6,
-  UPB_DESCRIPTOR_TYPE_FIXED32  = 7,
-  UPB_DESCRIPTOR_TYPE_BOOL     = 8,
-  UPB_DESCRIPTOR_TYPE_STRING   = 9,
-  UPB_DESCRIPTOR_TYPE_GROUP    = 10,
-  UPB_DESCRIPTOR_TYPE_MESSAGE  = 11,
-  UPB_DESCRIPTOR_TYPE_BYTES    = 12,
-  UPB_DESCRIPTOR_TYPE_UINT32   = 13,
-  UPB_DESCRIPTOR_TYPE_ENUM     = 14,
-  UPB_DESCRIPTOR_TYPE_SFIXED32 = 15,
-  UPB_DESCRIPTOR_TYPE_SFIXED64 = 16,
-  UPB_DESCRIPTOR_TYPE_SINT32   = 17,
-  UPB_DESCRIPTOR_TYPE_SINT64   = 18,
-
-  UPB_DTYPE_DOUBLE   = 1,
-  UPB_DTYPE_FLOAT    = 2,
-  UPB_DTYPE_INT64    = 3,
-  UPB_DTYPE_UINT64   = 4,
-  UPB_DTYPE_INT32    = 5,
-  UPB_DTYPE_FIXED64  = 6,
-  UPB_DTYPE_FIXED32  = 7,
-  UPB_DTYPE_BOOL     = 8,
-  UPB_DTYPE_STRING   = 9,
-  UPB_DTYPE_GROUP    = 10,
-  UPB_DTYPE_MESSAGE  = 11,
-  UPB_DTYPE_BYTES    = 12,
-  UPB_DTYPE_UINT32   = 13,
-  UPB_DTYPE_ENUM     = 14,
-  UPB_DTYPE_SFIXED32 = 15,
-  UPB_DTYPE_SFIXED64 = 16,
-  UPB_DTYPE_SINT32   = 17,
-  UPB_DTYPE_SINT64   = 18
-} upb_descriptortype_t;
-
-#define UPB_MAP_BEGIN -1
-
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-#endif  /* UPB_H_ */
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* upb_value ******************************************************************/
-
-/* A tagged union (stored untagged inside the table) so that we can check that
- * clients calling table accessors are correctly typed without having to have
- * an explosion of accessors. */
-typedef enum {
-  UPB_CTYPE_INT32    = 1,
-  UPB_CTYPE_INT64    = 2,
-  UPB_CTYPE_UINT32   = 3,
-  UPB_CTYPE_UINT64   = 4,
-  UPB_CTYPE_BOOL     = 5,
-  UPB_CTYPE_CSTR     = 6,
-  UPB_CTYPE_PTR      = 7,
-  UPB_CTYPE_CONSTPTR = 8,
-  UPB_CTYPE_FPTR     = 9,
-  UPB_CTYPE_FLOAT    = 10,
-  UPB_CTYPE_DOUBLE   = 11
-} upb_ctype_t;
-
-typedef struct {
-  uint64_t val;
-} upb_value;
-
-/* Like strdup(), which isn't always available since it's not ANSI C. */
-char *upb_strdup(const char *s, upb_alloc *a);
-/* Variant that works with a length-delimited rather than NULL-delimited string,
- * as supported by strtable. */
-char *upb_strdup2(const char *s, size_t len, upb_alloc *a);
-
-UPB_INLINE char *upb_gstrdup(const char *s) {
-  return upb_strdup(s, &upb_alloc_global);
-}
-
-UPB_INLINE void _upb_value_setval(upb_value *v, uint64_t val) {
-  v->val = val;
-}
-
-UPB_INLINE upb_value _upb_value_val(uint64_t val) {
-  upb_value ret;
-  _upb_value_setval(&ret, val);
-  return ret;
-}
-
-/* For each value ctype, define the following set of functions:
- *
- * // Get/set an int32 from a upb_value.
- * int32_t upb_value_getint32(upb_value val);
- * void upb_value_setint32(upb_value *val, int32_t cval);
- *
- * // Construct a new upb_value from an int32.
- * upb_value upb_value_int32(int32_t val); */
-#define FUNCS(name, membername, type_t, converter, proto_type) \
-  UPB_INLINE void upb_value_set ## name(upb_value *val, type_t cval) { \
-    val->val = (converter)cval; \
-  } \
-  UPB_INLINE upb_value upb_value_ ## name(type_t val) { \
-    upb_value ret; \
-    upb_value_set ## name(&ret, val); \
-    return ret; \
-  } \
-  UPB_INLINE type_t upb_value_get ## name(upb_value val) { \
-    return (type_t)(converter)val.val; \
-  }
-
-FUNCS(int32,    int32,        int32_t,      int32_t,    UPB_CTYPE_INT32)
-FUNCS(int64,    int64,        int64_t,      int64_t,    UPB_CTYPE_INT64)
-FUNCS(uint32,   uint32,       uint32_t,     uint32_t,   UPB_CTYPE_UINT32)
-FUNCS(uint64,   uint64,       uint64_t,     uint64_t,   UPB_CTYPE_UINT64)
-FUNCS(bool,     _bool,        bool,         bool,       UPB_CTYPE_BOOL)
-FUNCS(cstr,     cstr,         char*,        uintptr_t,  UPB_CTYPE_CSTR)
-FUNCS(ptr,      ptr,          void*,        uintptr_t,  UPB_CTYPE_PTR)
-FUNCS(constptr, constptr,     const void*,  uintptr_t,  UPB_CTYPE_CONSTPTR)
-FUNCS(fptr,     fptr,         upb_func*,    uintptr_t,  UPB_CTYPE_FPTR)
-
-#undef FUNCS
-
-UPB_INLINE void upb_value_setfloat(upb_value *val, float cval) {
-  memcpy(&val->val, &cval, sizeof(cval));
-}
-
-UPB_INLINE void upb_value_setdouble(upb_value *val, double cval) {
-  memcpy(&val->val, &cval, sizeof(cval));
-}
-
-UPB_INLINE upb_value upb_value_float(float cval) {
-  upb_value ret;
-  upb_value_setfloat(&ret, cval);
-  return ret;
-}
-
-UPB_INLINE upb_value upb_value_double(double cval) {
-  upb_value ret;
-  upb_value_setdouble(&ret, cval);
-  return ret;
-}
-
-#undef SET_TYPE
-
-
-/* upb_tabkey *****************************************************************/
-
-/* Either:
- *   1. an actual integer key, or
- *   2. a pointer to a string prefixed by its uint32_t length, owned by us.
- *
- * ...depending on whether this is a string table or an int table.  We would
- * make this a union of those two types, but C89 doesn't support statically
- * initializing a non-first union member. */
-typedef uintptr_t upb_tabkey;
-
-UPB_INLINE char *upb_tabstr(upb_tabkey key, uint32_t *len) {
-  char* mem = (char*)key;
-  if (len) memcpy(len, mem, sizeof(*len));
-  return mem + sizeof(*len);
-}
-
-
-/* upb_tabval *****************************************************************/
-
-typedef struct {
-  uint64_t val;
-} upb_tabval;
-
-#define UPB_TABVALUE_EMPTY_INIT  {-1}
-
-/* upb_table ******************************************************************/
-
-typedef struct _upb_tabent {
-  upb_tabkey key;
-  upb_tabval val;
-
-  /* Internal chaining.  This is const so we can create static initializers for
-   * tables.  We cast away const sometimes, but *only* when the containing
-   * upb_table is known to be non-const.  This requires a bit of care, but
-   * the subtlety is confined to table.c. */
-  const struct _upb_tabent *next;
-} upb_tabent;
-
-typedef struct {
-  size_t count;          /* Number of entries in the hash part. */
-  size_t mask;           /* Mask to turn hash value -> bucket. */
-  uint8_t size_lg2;      /* Size of the hashtable part is 2^size_lg2 entries. */
-
-  /* Hash table entries.
-   * Making this const isn't entirely accurate; what we really want is for it to
-   * have the same const-ness as the table it's inside.  But there's no way to
-   * declare that in C.  So we have to make it const so that we can statically
-   * initialize const hash tables.  Then we cast away const when we have to.
-   */
-  const upb_tabent *entries;
-} upb_table;
-
-typedef struct {
-  upb_table t;
-} upb_strtable;
-
-typedef struct {
-  upb_table t;              /* For entries that don't fit in the array part. */
-  const upb_tabval *array;  /* Array part of the table. See const note above. */
-  size_t array_size;        /* Array part size. */
-  size_t array_count;       /* Array part number of elements. */
-} upb_inttable;
-
-#define UPB_ARRAY_EMPTYENT -1
-
-UPB_INLINE size_t upb_table_size(const upb_table *t) {
-  if (t->size_lg2 == 0)
-    return 0;
-  else
-    return 1 << t->size_lg2;
-}
-
-/* Internal-only functions, in .h file only out of necessity. */
-UPB_INLINE bool upb_tabent_isempty(const upb_tabent *e) {
-  return e->key == 0;
-}
-
-/* Used by some of the unit tests for generic hashing functionality. */
-uint32_t upb_murmur_hash2(const void * key, size_t len, uint32_t seed);
-
-UPB_INLINE uintptr_t upb_intkey(uintptr_t key) {
-  return key;
-}
-
-UPB_INLINE uint32_t upb_inthash(uintptr_t key) {
-  return (uint32_t)key;
-}
-
-static const upb_tabent *upb_getentry(const upb_table *t, uint32_t hash) {
-  return t->entries + (hash & t->mask);
-}
-
-UPB_INLINE bool upb_arrhas(upb_tabval key) {
-  return key.val != (uint64_t)-1;
-}
-
-/* Initialize and uninitialize a table, respectively.  If memory allocation
- * failed, false is returned that the table is uninitialized. */
-bool upb_inttable_init2(upb_inttable *table, upb_ctype_t ctype, upb_alloc *a);
-bool upb_strtable_init2(upb_strtable *table, upb_ctype_t ctype, upb_alloc *a);
-void upb_inttable_uninit2(upb_inttable *table, upb_alloc *a);
-void upb_strtable_uninit2(upb_strtable *table, upb_alloc *a);
-
-UPB_INLINE bool upb_inttable_init(upb_inttable *table, upb_ctype_t ctype) {
-  return upb_inttable_init2(table, ctype, &upb_alloc_global);
-}
-
-UPB_INLINE bool upb_strtable_init(upb_strtable *table, upb_ctype_t ctype) {
-  return upb_strtable_init2(table, ctype, &upb_alloc_global);
-}
-
-UPB_INLINE void upb_inttable_uninit(upb_inttable *table) {
-  upb_inttable_uninit2(table, &upb_alloc_global);
-}
-
-UPB_INLINE void upb_strtable_uninit(upb_strtable *table) {
-  upb_strtable_uninit2(table, &upb_alloc_global);
-}
-
-/* Returns the number of values in the table. */
-size_t upb_inttable_count(const upb_inttable *t);
-UPB_INLINE size_t upb_strtable_count(const upb_strtable *t) {
-  return t->t.count;
-}
-
-void upb_inttable_packedsize(const upb_inttable *t, size_t *size);
-void upb_strtable_packedsize(const upb_strtable *t, size_t *size);
-upb_inttable *upb_inttable_pack(const upb_inttable *t, void *p, size_t *ofs,
-                                size_t size);
-upb_strtable *upb_strtable_pack(const upb_strtable *t, void *p, size_t *ofs,
-                                size_t size);
-void upb_strtable_clear(upb_strtable *t);
-
-/* Inserts the given key into the hashtable with the given value.  The key must
- * not already exist in the hash table.  For string tables, the key must be
- * NULL-terminated, and the table will make an internal copy of the key.
- * Inttables must not insert a value of UINTPTR_MAX.
- *
- * If a table resize was required but memory allocation failed, false is
- * returned and the table is unchanged. */
-bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val,
-                          upb_alloc *a);
-bool upb_strtable_insert3(upb_strtable *t, const char *key, size_t len,
-                          upb_value val, upb_alloc *a);
-
-UPB_INLINE bool upb_inttable_insert(upb_inttable *t, uintptr_t key,
-                                    upb_value val) {
-  return upb_inttable_insert2(t, key, val, &upb_alloc_global);
-}
-
-UPB_INLINE bool upb_strtable_insert2(upb_strtable *t, const char *key,
-                                     size_t len, upb_value val) {
-  return upb_strtable_insert3(t, key, len, val, &upb_alloc_global);
-}
-
-/* For NULL-terminated strings. */
-UPB_INLINE bool upb_strtable_insert(upb_strtable *t, const char *key,
-                                    upb_value val) {
-  return upb_strtable_insert2(t, key, strlen(key), val);
-}
-
-/* Looks up key in this table, returning "true" if the key was found.
- * If v is non-NULL, copies the value for this key into *v. */
-bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v);
-bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
-                          upb_value *v);
-
-/* For NULL-terminated strings. */
-UPB_INLINE bool upb_strtable_lookup(const upb_strtable *t, const char *key,
-                                    upb_value *v) {
-  return upb_strtable_lookup2(t, key, strlen(key), v);
-}
-
-/* Removes an item from the table.  Returns true if the remove was successful,
- * and stores the removed item in *val if non-NULL. */
-bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val);
-bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len,
-                          upb_value *val, upb_alloc *alloc);
-
-UPB_INLINE bool upb_strtable_remove2(upb_strtable *t, const char *key,
-                                     size_t len, upb_value *val) {
-  return upb_strtable_remove3(t, key, len, val, &upb_alloc_global);
-}
-
-/* For NULL-terminated strings. */
-UPB_INLINE bool upb_strtable_remove(upb_strtable *t, const char *key,
-                                    upb_value *v) {
-  return upb_strtable_remove2(t, key, strlen(key), v);
-}
-
-/* Updates an existing entry in an inttable.  If the entry does not exist,
- * returns false and does nothing.  Unlike insert/remove, this does not
- * invalidate iterators. */
-bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val);
-
-/* Handy routines for treating an inttable like a stack.  May not be mixed with
- * other insert/remove calls. */
-bool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a);
-upb_value upb_inttable_pop(upb_inttable *t);
-
-UPB_INLINE bool upb_inttable_push(upb_inttable *t, upb_value val) {
-  return upb_inttable_push2(t, val, &upb_alloc_global);
-}
-
-/* Convenience routines for inttables with pointer keys. */
-bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val,
-                             upb_alloc *a);
-bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val);
-bool upb_inttable_lookupptr(
-    const upb_inttable *t, const void *key, upb_value *val);
-
-UPB_INLINE bool upb_inttable_insertptr(upb_inttable *t, const void *key,
-                                       upb_value val) {
-  return upb_inttable_insertptr2(t, key, val, &upb_alloc_global);
-}
-
-/* Optimizes the table for the current set of entries, for both memory use and
- * lookup time.  Client should call this after all entries have been inserted;
- * inserting more entries is legal, but will likely require a table resize. */
-void upb_inttable_compact2(upb_inttable *t, upb_alloc *a);
-
-UPB_INLINE void upb_inttable_compact(upb_inttable *t) {
-  upb_inttable_compact2(t, &upb_alloc_global);
-}
-
-/* A special-case inlinable version of the lookup routine for 32-bit
- * integers. */
-UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key,
-                                      upb_value *v) {
-  *v = upb_value_int32(0);  /* Silence compiler warnings. */
-  if (key < t->array_size) {
-    upb_tabval arrval = t->array[key];
-    if (upb_arrhas(arrval)) {
-      _upb_value_setval(v, arrval.val);
-      return true;
-    } else {
-      return false;
-    }
-  } else {
-    const upb_tabent *e;
-    if (t->t.entries == NULL) return false;
-    for (e = upb_getentry(&t->t, upb_inthash(key)); true; e = e->next) {
-      if ((uint32_t)e->key == key) {
-        _upb_value_setval(v, e->val.val);
-        return true;
-      }
-      if (e->next == NULL) return false;
-    }
-  }
-}
-
-/* Exposed for testing only. */
-bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a);
-
-/* Iterators ******************************************************************/
-
-/* Iterators for int and string tables.  We are subject to some kind of unusual
- * design constraints:
- *
- * For high-level languages:
- *  - we must be able to guarantee that we don't crash or corrupt memory even if
- *    the program accesses an invalidated iterator.
- *
- * For C++11 range-based for:
- *  - iterators must be copyable
- *  - iterators must be comparable
- *  - it must be possible to construct an "end" value.
- *
- * Iteration order is undefined.
- *
- * Modifying the table invalidates iterators.  upb_{str,int}table_done() is
- * guaranteed to work even on an invalidated iterator, as long as the table it
- * is iterating over has not been freed.  Calling next() or accessing data from
- * an invalidated iterator yields unspecified elements from the table, but it is
- * guaranteed not to crash and to return real table elements (except when done()
- * is true). */
-
-
-/* upb_strtable_iter **********************************************************/
-
-/*   upb_strtable_iter i;
- *   upb_strtable_begin(&i, t);
- *   for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
- *     const char *key = upb_strtable_iter_key(&i);
- *     const upb_value val = upb_strtable_iter_value(&i);
- *     // ...
- *   }
- */
-
-typedef struct {
-  const upb_strtable *t;
-  size_t index;
-} upb_strtable_iter;
-
-void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t);
-void upb_strtable_next(upb_strtable_iter *i);
-bool upb_strtable_done(const upb_strtable_iter *i);
-upb_strview upb_strtable_iter_key(const upb_strtable_iter *i);
-upb_value upb_strtable_iter_value(const upb_strtable_iter *i);
-void upb_strtable_iter_setdone(upb_strtable_iter *i);
-bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
-                               const upb_strtable_iter *i2);
-
-
-/* upb_inttable_iter **********************************************************/
-
-/*   upb_inttable_iter i;
- *   upb_inttable_begin(&i, t);
- *   for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
- *     uintptr_t key = upb_inttable_iter_key(&i);
- *     upb_value val = upb_inttable_iter_value(&i);
- *     // ...
- *   }
- */
-
-typedef struct {
-  const upb_inttable *t;
-  size_t index;
-  bool array_part;
-} upb_inttable_iter;
-
-UPB_INLINE const upb_tabent *str_tabent(const upb_strtable_iter *i) {
-  return &i->t->t.entries[i->index];
-}
-
-void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t);
-void upb_inttable_next(upb_inttable_iter *i);
-bool upb_inttable_done(const upb_inttable_iter *i);
-uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i);
-upb_value upb_inttable_iter_value(const upb_inttable_iter *i);
-void upb_inttable_iter_setdone(upb_inttable_iter *i);
-bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
-                               const upb_inttable_iter *i2);
-
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-
-#endif  /* UPB_TABLE_H_ */
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define PTR_AT(msg, ofs, type) (type*)((const char*)msg + ofs)
-
-typedef void upb_msg;
-
-/** upb_msglayout *************************************************************/
-
-/* upb_msglayout represents the memory layout of a given upb_msgdef.  The
- * members are public so generated code can initialize them, but users MUST NOT
- * read or write any of its members. */
-
-/* These aren't real labels according to descriptor.proto, but in the table we
- * use these for map/packed fields instead of UPB_LABEL_REPEATED. */
-enum {
-  _UPB_LABEL_MAP = 4,
-  _UPB_LABEL_PACKED = 7  /* Low 3 bits are common with UPB_LABEL_REPEATED. */
-};
-
-typedef struct {
-  uint32_t number;
-  uint16_t offset;
-  int16_t presence;      /* If >0, hasbit_index.  If <0, -oneof_index. */
-  uint16_t submsg_index;  /* undefined if descriptortype != MESSAGE or GROUP. */
-  uint8_t descriptortype;
-  uint8_t label;
-} upb_msglayout_field;
-
-typedef struct upb_msglayout {
-  const struct upb_msglayout *const* submsgs;
-  const upb_msglayout_field *fields;
-  /* Must be aligned to sizeof(void*).  Doesn't include internal members like
-   * unknown fields, extension dict, pointer to msglayout, etc. */
-  uint16_t size;
-  uint16_t field_count;
-  bool extendable;
-} upb_msglayout;
-
-/** upb_msg *******************************************************************/
-
-/* Internal members of a upb_msg.  We can change this without breaking binary
- * compatibility.  We put these before the user's data.  The user's upb_msg*
- * points after the upb_msg_internal. */
-
-/* Used when a message is not extendable. */
-typedef struct {
-  char *unknown;
-  size_t unknown_len;
-  size_t unknown_size;
-} upb_msg_internal;
-
-/* Used when a message is extendable. */
-typedef struct {
-  upb_inttable *extdict;
-  upb_msg_internal base;
-} upb_msg_internal_withext;
-
-/* Maps upb_fieldtype_t -> memory size. */
-extern char _upb_fieldtype_to_size[12];
-
-/* Creates a new messages with the given layout on the given arena. */
-upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a);
-
-/* Adds unknown data (serialized protobuf data) to the given message.  The data
- * is copied into the message instance. */
-bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
-                         upb_arena *arena);
-
-/* Returns a reference to the message's unknown data. */
-const char *upb_msg_getunknown(const upb_msg *msg, size_t *len);
-
-UPB_INLINE bool _upb_has_field(const void *msg, size_t idx) {
-  return (*PTR_AT(msg, idx / 8, const char) & (1 << (idx % 8))) != 0;
-}
-
-UPB_INLINE bool _upb_sethas(const void *msg, size_t idx) {
-  return (*PTR_AT(msg, idx / 8, char)) |= (char)(1 << (idx % 8));
-}
-
-UPB_INLINE bool _upb_clearhas(const void *msg, size_t idx) {
-  return (*PTR_AT(msg, idx / 8, char)) &= (char)(~(1 << (idx % 8)));
-}
-
-UPB_INLINE bool _upb_has_oneof_field(const void *msg, size_t case_ofs, int32_t num) {
-  return *PTR_AT(msg, case_ofs, int32_t) == num;
-}
-
-UPB_INLINE bool _upb_has_submsg_nohasbit(const void *msg, size_t ofs) {
-  return *PTR_AT(msg, ofs, const void*) != NULL;
-}
-
-UPB_INLINE bool _upb_isrepeated(const upb_msglayout_field *field) {
-  return (field->label & 3) == UPB_LABEL_REPEATED;
-}
-
-/** upb_array *****************************************************************/
-
-/* Our internal representation for repeated fields.  */
-typedef struct {
-  uintptr_t data;   /* Tagged ptr: low 3 bits of ptr are lg2(elem size). */
-  size_t len;   /* Measured in elements. */
-  size_t size;  /* Measured in elements. */
-} upb_array;
-
-UPB_INLINE const void *_upb_array_constptr(const upb_array *arr) {
-  return (void*)(arr->data & ~(uintptr_t)7);
-}
-
-UPB_INLINE void *_upb_array_ptr(upb_array *arr) {
-  return (void*)_upb_array_constptr(arr);
-}
-
-/* Creates a new array on the given arena. */
-upb_array *_upb_array_new(upb_arena *a, upb_fieldtype_t type);
-
-/* Resizes the capacity of the array to be at least min_size. */
-bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena);
-
-/* Fallback functions for when the accessors require a resize. */
-void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size,
-                                 upb_fieldtype_t type, upb_arena *arena);
-bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value,
-                                upb_fieldtype_t type, upb_arena *arena);
-
-UPB_INLINE const void *_upb_array_accessor(const void *msg, size_t ofs,
-                                           size_t *size) {
-  const upb_array *arr = *PTR_AT(msg, ofs, const upb_array*);
-  if (arr) {
-    if (size) *size = arr->len;
-    return _upb_array_constptr(arr);
-  } else {
-    if (size) *size = 0;
-    return NULL;
-  }
-}
-
-UPB_INLINE void *_upb_array_mutable_accessor(void *msg, size_t ofs,
-                                             size_t *size) {
-  upb_array *arr = *PTR_AT(msg, ofs, upb_array*);
-  if (arr) {
-    if (size) *size = arr->len;
-    return _upb_array_ptr(arr);
-  } else {
-    if (size) *size = 0;
-    return NULL;
-  }
-}
-
-UPB_INLINE void *_upb_array_resize_accessor(void *msg, size_t ofs, size_t size,
-                                            upb_fieldtype_t type,
-                                            upb_arena *arena) {
-  upb_array **arr_ptr = PTR_AT(msg, ofs, upb_array*);
-  upb_array *arr = *arr_ptr;
-  if (!arr || arr->size < size) {
-    return _upb_array_resize_fallback(arr_ptr, size, type, arena);
-  }
-  arr->len = size;
-  return _upb_array_ptr(arr);
-}
-
-
-UPB_INLINE bool _upb_array_append_accessor(void *msg, size_t ofs,
-                                           size_t elem_size,
-                                           upb_fieldtype_t type,
-                                           const void *value,
-                                           upb_arena *arena) {
-  upb_array **arr_ptr = PTR_AT(msg, ofs, upb_array*);
-  upb_array *arr = *arr_ptr;
-  void* ptr;
-  if (!arr || arr->len == arr->size) {
-    return _upb_array_append_fallback(arr_ptr, value, type, arena);
-  }
-  ptr = _upb_array_ptr(arr);
-  memcpy(PTR_AT(ptr, arr->len * elem_size, char), value, elem_size);
-  arr->len++;
-  return true;
-}
-
-/** upb_map *******************************************************************/
-
-/* Right now we use strmaps for everything.  We'll likely want to use
- * integer-specific maps for integer-keyed maps.*/
-typedef struct {
-  /* Size of key and val, based on the map type.  Strings are represented as '0'
-   * because they must be handled specially. */
-  char key_size;
-  char val_size;
-
-  upb_strtable table;
-} upb_map;
-
-/* Map entries aren't actually stored, they are only used during parsing.  For
- * parsing, it helps a lot if all map entry messages have the same layout.
- * The compiler and def.c must ensure that all map entries have this layout. */
-typedef struct {
-  upb_msg_internal internal;
-  union {
-    upb_strview str;  /* For str/bytes. */
-    upb_value val;    /* For all other types. */
-  } k;
-  union {
-    upb_strview str;  /* For str/bytes. */
-    upb_value val;    /* For all other types. */
-  } v;
-} upb_map_entry;
-
-/* Creates a new map on the given arena with this key/value type. */
-upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size);
-
-/* Converting between internal table representation and user values.
- *
- * _upb_map_tokey() and _upb_map_fromkey() are inverses.
- * _upb_map_tovalue() and _upb_map_fromvalue() are inverses.
- *
- * These functions account for the fact that strings are treated differently
- * from other types when stored in a map.
- */
-
-UPB_INLINE upb_strview _upb_map_tokey(const void *key, size_t size) {
-  if (size == UPB_MAPTYPE_STRING) {
-    return *(upb_strview*)key;
-  } else {
-    return upb_strview_make((const char*)key, size);
-  }
-}
-
-UPB_INLINE void _upb_map_fromkey(upb_strview key, void* out, size_t size) {
-  if (size == UPB_MAPTYPE_STRING) {
-    memcpy(out, &key, sizeof(key));
-  } else {
-    memcpy(out, key.data, size);
-  }
-}
-
-UPB_INLINE upb_value _upb_map_tovalue(const void *val, size_t size,
-                                      upb_arena *a) {
-  upb_value ret = {0};
-  if (size == UPB_MAPTYPE_STRING) {
-    upb_strview *strp = (upb_strview*)upb_arena_malloc(a, sizeof(*strp));
-    *strp = *(upb_strview*)val;
-    memcpy(&ret, &strp, sizeof(strp));
-  } else {
-    memcpy(&ret, val, size);
-  }
-  return ret;
-}
-
-UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) {
-  if (size == UPB_MAPTYPE_STRING) {
-    const upb_strview *strp = (const upb_strview*)upb_value_getptr(val);
-    memcpy(out, strp, sizeof(upb_strview));
-  } else {
-    memcpy(out, &val, size);
-  }
-}
-
-/* Map operations, shared by reflection and generated code. */
-
-UPB_INLINE size_t _upb_map_size(const upb_map *map) {
-  return map->table.t.count;
-}
-
-UPB_INLINE bool _upb_map_get(const upb_map *map, const void *key,
-                             size_t key_size, void *val, size_t val_size) {
-  upb_value tabval;
-  upb_strview k = _upb_map_tokey(key, key_size);
-  bool ret = upb_strtable_lookup2(&map->table, k.data, k.size, &tabval);
-  if (ret) {
-    _upb_map_fromvalue(tabval, val, val_size);
-  }
-  return ret;
-}
-
-UPB_INLINE void* _upb_map_next(const upb_map *map, size_t *iter) {
-  upb_strtable_iter it;
-  it.t = &map->table;
-  it.index = *iter;
-  upb_strtable_next(&it);
-  if (upb_strtable_done(&it)) return NULL;
-  *iter = it.index;
-  return (void*)str_tabent(&it);
-}
-
-UPB_INLINE bool _upb_map_set(upb_map *map, const void *key, size_t key_size,
-                             void *val, size_t val_size, upb_arena *arena) {
-  upb_strview strkey = _upb_map_tokey(key, key_size);
-  upb_value tabval = _upb_map_tovalue(val, val_size, arena);
-  upb_alloc *a = upb_arena_alloc(arena);
-
-  /* TODO(haberman): add overwrite operation to minimize number of lookups. */
-  upb_strtable_remove3(&map->table, strkey.data, strkey.size, NULL, a);
-  return upb_strtable_insert3(&map->table, strkey.data, strkey.size, tabval, a);
-}
-
-UPB_INLINE bool _upb_map_delete(upb_map *map, const void *key, size_t key_size) {
-  upb_strview k = _upb_map_tokey(key, key_size);
-  return upb_strtable_remove3(&map->table, k.data, k.size, NULL, NULL);
-}
-
-UPB_INLINE void _upb_map_clear(upb_map *map) {
-  upb_strtable_clear(&map->table);
-}
-
-/* Message map operations, these get the map from the message first. */
-
-UPB_INLINE size_t _upb_msg_map_size(const upb_msg *msg, size_t ofs) {
-  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
-  return map ? _upb_map_size(map) : 0;
-}
-
-UPB_INLINE bool _upb_msg_map_get(const upb_msg *msg, size_t ofs,
-                                 const void *key, size_t key_size, void *val,
-                                 size_t val_size) {
-  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
-  if (!map) return false;
-  return _upb_map_get(map, key, key_size, val, val_size);
-}
-
-UPB_INLINE void *_upb_msg_map_next(const upb_msg *msg, size_t ofs,
-                                   size_t *iter) {
-  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
-  if (!map) return NULL;
-  return _upb_map_next(map, iter);
-}
-
-UPB_INLINE bool _upb_msg_map_set(upb_msg *msg, size_t ofs, const void *key,
-                                 size_t key_size, void *val, size_t val_size,
-                                 upb_arena *arena) {
-  upb_map **map = PTR_AT(msg, ofs, upb_map *);
-  if (!*map) {
-    *map = _upb_map_new(arena, key_size, val_size);
-  }
-  return _upb_map_set(*map, key, key_size, val, val_size, arena);
-}
-
-UPB_INLINE bool _upb_msg_map_delete(upb_msg *msg, size_t ofs, const void *key,
-                                    size_t key_size) {
-  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
-  if (!map) return false;
-  return _upb_map_delete(map, key, key_size);
-}
-
-UPB_INLINE void _upb_msg_map_clear(upb_msg *msg, size_t ofs) {
-  upb_map *map = *UPB_PTR_AT(msg, ofs, upb_map *);
-  if (!map) return;
-  _upb_map_clear(map);
-}
-
-/* Accessing map key/value from a pointer, used by generated code only. */
-
-UPB_INLINE void _upb_msg_map_key(const void* msg, void* key, size_t size) {
-  const upb_tabent *ent = (const upb_tabent*)msg;
-  uint32_t u32len;
-  upb_strview k;
-  k.data = upb_tabstr(ent->key, &u32len);
-  k.size = u32len;
-  _upb_map_fromkey(k, key, size);
-}
-
-UPB_INLINE void _upb_msg_map_value(const void* msg, void* val, size_t size) {
-  const upb_tabent *ent = (const upb_tabent*)msg;
-  upb_value v;
-  _upb_value_setval(&v, ent->val.val);
-  _upb_map_fromvalue(v, val, size);
-}
-
-UPB_INLINE void _upb_msg_map_set_value(void* msg, const void* val, size_t size) {
-  upb_tabent *ent = (upb_tabent*)msg;
-  /* This is like _upb_map_tovalue() except the entry already exists so we can
-   * reuse the allocated upb_strview for string fields. */
-  if (size == UPB_MAPTYPE_STRING) {
-    upb_strview *strp = (upb_strview*)ent->val.val;
-    memcpy(strp, val, sizeof(*strp));
-  } else {
-    memcpy(&ent->val.val, val, size);
-  }
-}
-
-#undef PTR_AT
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-
-#endif /* UPB_MSG_H_ */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-bool upb_decode(const char *buf, size_t size, upb_msg *msg,
-                const upb_msglayout *l, upb_arena *arena);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-#endif  /* UPB_DECODE_H_ */
-/*
-** upb_encode: parsing into a upb_msg using a upb_msglayout.
-*/
-
-#ifndef UPB_ENCODE_H_
-#define UPB_ENCODE_H_
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-char *upb_encode(const void *msg, const upb_msglayout *l, upb_arena *arena,
-                 size_t *size);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-#endif  /* UPB_ENCODE_H_ */
-/* This file was generated by upbc (the upb compiler) from the input
- * file:
- *
- *     google/protobuf/descriptor.proto
- *
- * Do not edit -- your changes will be discarded when the file is
- * regenerated. */
-
-#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_
-#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_
-
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct google_protobuf_FileDescriptorSet;
-struct google_protobuf_FileDescriptorProto;
-struct google_protobuf_DescriptorProto;
-struct google_protobuf_DescriptorProto_ExtensionRange;
-struct google_protobuf_DescriptorProto_ReservedRange;
-struct google_protobuf_ExtensionRangeOptions;
-struct google_protobuf_FieldDescriptorProto;
-struct google_protobuf_OneofDescriptorProto;
-struct google_protobuf_EnumDescriptorProto;
-struct google_protobuf_EnumDescriptorProto_EnumReservedRange;
-struct google_protobuf_EnumValueDescriptorProto;
-struct google_protobuf_ServiceDescriptorProto;
-struct google_protobuf_MethodDescriptorProto;
-struct google_protobuf_FileOptions;
-struct google_protobuf_MessageOptions;
-struct google_protobuf_FieldOptions;
-struct google_protobuf_OneofOptions;
-struct google_protobuf_EnumOptions;
-struct google_protobuf_EnumValueOptions;
-struct google_protobuf_ServiceOptions;
-struct google_protobuf_MethodOptions;
-struct google_protobuf_UninterpretedOption;
-struct google_protobuf_UninterpretedOption_NamePart;
-struct google_protobuf_SourceCodeInfo;
-struct google_protobuf_SourceCodeInfo_Location;
-struct google_protobuf_GeneratedCodeInfo;
-struct google_protobuf_GeneratedCodeInfo_Annotation;
-typedef struct google_protobuf_FileDescriptorSet google_protobuf_FileDescriptorSet;
-typedef struct google_protobuf_FileDescriptorProto google_protobuf_FileDescriptorProto;
-typedef struct google_protobuf_DescriptorProto google_protobuf_DescriptorProto;
-typedef struct google_protobuf_DescriptorProto_ExtensionRange google_protobuf_DescriptorProto_ExtensionRange;
-typedef struct google_protobuf_DescriptorProto_ReservedRange google_protobuf_DescriptorProto_ReservedRange;
-typedef struct google_protobuf_ExtensionRangeOptions google_protobuf_ExtensionRangeOptions;
-typedef struct google_protobuf_FieldDescriptorProto google_protobuf_FieldDescriptorProto;
-typedef struct google_protobuf_OneofDescriptorProto google_protobuf_OneofDescriptorProto;
-typedef struct google_protobuf_EnumDescriptorProto google_protobuf_EnumDescriptorProto;
-typedef struct google_protobuf_EnumDescriptorProto_EnumReservedRange google_protobuf_EnumDescriptorProto_EnumReservedRange;
-typedef struct google_protobuf_EnumValueDescriptorProto google_protobuf_EnumValueDescriptorProto;
-typedef struct google_protobuf_ServiceDescriptorProto google_protobuf_ServiceDescriptorProto;
-typedef struct google_protobuf_MethodDescriptorProto google_protobuf_MethodDescriptorProto;
-typedef struct google_protobuf_FileOptions google_protobuf_FileOptions;
-typedef struct google_protobuf_MessageOptions google_protobuf_MessageOptions;
-typedef struct google_protobuf_FieldOptions google_protobuf_FieldOptions;
-typedef struct google_protobuf_OneofOptions google_protobuf_OneofOptions;
-typedef struct google_protobuf_EnumOptions google_protobuf_EnumOptions;
-typedef struct google_protobuf_EnumValueOptions google_protobuf_EnumValueOptions;
-typedef struct google_protobuf_ServiceOptions google_protobuf_ServiceOptions;
-typedef struct google_protobuf_MethodOptions google_protobuf_MethodOptions;
-typedef struct google_protobuf_UninterpretedOption google_protobuf_UninterpretedOption;
-typedef struct google_protobuf_UninterpretedOption_NamePart google_protobuf_UninterpretedOption_NamePart;
-typedef struct google_protobuf_SourceCodeInfo google_protobuf_SourceCodeInfo;
-typedef struct google_protobuf_SourceCodeInfo_Location google_protobuf_SourceCodeInfo_Location;
-typedef struct google_protobuf_GeneratedCodeInfo google_protobuf_GeneratedCodeInfo;
-typedef struct google_protobuf_GeneratedCodeInfo_Annotation google_protobuf_GeneratedCodeInfo_Annotation;
-extern const upb_msglayout google_protobuf_FileDescriptorSet_msginit;
-extern const upb_msglayout google_protobuf_FileDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_DescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit;
-extern const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit;
-extern const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit;
-extern const upb_msglayout google_protobuf_FieldDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_OneofDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_EnumDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit;
-extern const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_MethodDescriptorProto_msginit;
-extern const upb_msglayout google_protobuf_FileOptions_msginit;
-extern const upb_msglayout google_protobuf_MessageOptions_msginit;
-extern const upb_msglayout google_protobuf_FieldOptions_msginit;
-extern const upb_msglayout google_protobuf_OneofOptions_msginit;
-extern const upb_msglayout google_protobuf_EnumOptions_msginit;
-extern const upb_msglayout google_protobuf_EnumValueOptions_msginit;
-extern const upb_msglayout google_protobuf_ServiceOptions_msginit;
-extern const upb_msglayout google_protobuf_MethodOptions_msginit;
-extern const upb_msglayout google_protobuf_UninterpretedOption_msginit;
-extern const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit;
-extern const upb_msglayout google_protobuf_SourceCodeInfo_msginit;
-extern const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit;
-extern const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit;
-extern const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit;
-
-typedef enum {
-  google_protobuf_FieldDescriptorProto_LABEL_OPTIONAL = 1,
-  google_protobuf_FieldDescriptorProto_LABEL_REQUIRED = 2,
-  google_protobuf_FieldDescriptorProto_LABEL_REPEATED = 3
-} google_protobuf_FieldDescriptorProto_Label;
-
-typedef enum {
-  google_protobuf_FieldDescriptorProto_TYPE_DOUBLE = 1,
-  google_protobuf_FieldDescriptorProto_TYPE_FLOAT = 2,
-  google_protobuf_FieldDescriptorProto_TYPE_INT64 = 3,
-  google_protobuf_FieldDescriptorProto_TYPE_UINT64 = 4,
-  google_protobuf_FieldDescriptorProto_TYPE_INT32 = 5,
-  google_protobuf_FieldDescriptorProto_TYPE_FIXED64 = 6,
-  google_protobuf_FieldDescriptorProto_TYPE_FIXED32 = 7,
-  google_protobuf_FieldDescriptorProto_TYPE_BOOL = 8,
-  google_protobuf_FieldDescriptorProto_TYPE_STRING = 9,
-  google_protobuf_FieldDescriptorProto_TYPE_GROUP = 10,
-  google_protobuf_FieldDescriptorProto_TYPE_MESSAGE = 11,
-  google_protobuf_FieldDescriptorProto_TYPE_BYTES = 12,
-  google_protobuf_FieldDescriptorProto_TYPE_UINT32 = 13,
-  google_protobuf_FieldDescriptorProto_TYPE_ENUM = 14,
-  google_protobuf_FieldDescriptorProto_TYPE_SFIXED32 = 15,
-  google_protobuf_FieldDescriptorProto_TYPE_SFIXED64 = 16,
-  google_protobuf_FieldDescriptorProto_TYPE_SINT32 = 17,
-  google_protobuf_FieldDescriptorProto_TYPE_SINT64 = 18
-} google_protobuf_FieldDescriptorProto_Type;
-
-typedef enum {
-  google_protobuf_FieldOptions_STRING = 0,
-  google_protobuf_FieldOptions_CORD = 1,
-  google_protobuf_FieldOptions_STRING_PIECE = 2
-} google_protobuf_FieldOptions_CType;
-
-typedef enum {
-  google_protobuf_FieldOptions_JS_NORMAL = 0,
-  google_protobuf_FieldOptions_JS_STRING = 1,
-  google_protobuf_FieldOptions_JS_NUMBER = 2
-} google_protobuf_FieldOptions_JSType;
-
-typedef enum {
-  google_protobuf_FileOptions_SPEED = 1,
-  google_protobuf_FileOptions_CODE_SIZE = 2,
-  google_protobuf_FileOptions_LITE_RUNTIME = 3
-} google_protobuf_FileOptions_OptimizeMode;
-
-typedef enum {
-  google_protobuf_MethodOptions_IDEMPOTENCY_UNKNOWN = 0,
-  google_protobuf_MethodOptions_NO_SIDE_EFFECTS = 1,
-  google_protobuf_MethodOptions_IDEMPOTENT = 2
-} google_protobuf_MethodOptions_IdempotencyLevel;
-
-
-/* google.protobuf.FileDescriptorSet */
-
-UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_new(upb_arena *arena) {
-  return (google_protobuf_FileDescriptorSet *)_upb_msg_new(&google_protobuf_FileDescriptorSet_msginit, arena);
-}
-UPB_INLINE google_protobuf_FileDescriptorSet *google_protobuf_FileDescriptorSet_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_FileDescriptorSet *ret = google_protobuf_FileDescriptorSet_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_FileDescriptorSet_serialize(const google_protobuf_FileDescriptorSet *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_FileDescriptorSet_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_FileDescriptorSet_has_file(const google_protobuf_FileDescriptorSet *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
-UPB_INLINE const google_protobuf_FileDescriptorProto* const* google_protobuf_FileDescriptorSet_file(const google_protobuf_FileDescriptorSet *msg, size_t *len) { return (const google_protobuf_FileDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
-
-UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_mutable_file(google_protobuf_FileDescriptorSet *msg, size_t *len) {
-  return (google_protobuf_FileDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
-}
-UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_resize_file(google_protobuf_FileDescriptorSet *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_FileDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorSet_add_file(google_protobuf_FileDescriptorSet *msg, upb_arena *arena) {
-  struct google_protobuf_FileDescriptorProto* sub = (struct google_protobuf_FileDescriptorProto*)_upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.FileDescriptorProto */
-
-UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_FileDescriptorProto *)_upb_msg_new(&google_protobuf_FileDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_FileDescriptorProto *google_protobuf_FileDescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_FileDescriptorProto *ret = google_protobuf_FileDescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_FileDescriptorProto_serialize(const google_protobuf_FileDescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_FileDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_name(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_name(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_package(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_package(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); }
-UPB_INLINE upb_strview const* google_protobuf_FileDescriptorProto_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_message_type(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(40, 80)); }
-UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_FileDescriptorProto_message_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_enum_type(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(44, 88)); }
-UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_FileDescriptorProto_enum_type(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_service(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(48, 96)); }
-UPB_INLINE const google_protobuf_ServiceDescriptorProto* const* google_protobuf_FileDescriptorProto_service(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_ServiceDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(48, 96), len); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_extension(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(52, 104)); }
-UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_FileDescriptorProto_extension(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(52, 104), len); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_options(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE const google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_options(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_FileOptions*); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE const google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 64), const google_protobuf_SourceCodeInfo*); }
-UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_public_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(56, 112), len); }
-UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_weak_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(60, 120), len); }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_syntax(const google_protobuf_FileDescriptorProto *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE upb_strview google_protobuf_FileDescriptorProto_syntax(const google_protobuf_FileDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); }
-
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_name(google_protobuf_FileDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_package(google_protobuf_FileDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value;
-}
-UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_mutable_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len);
-}
-UPB_INLINE upb_strview* google_protobuf_FileDescriptorProto_resize_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(36, 72), len, UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool google_protobuf_FileDescriptorProto_add_dependency(google_protobuf_FileDescriptorProto *msg, upb_strview val, upb_arena *arena) {
-  return _upb_array_append_accessor(msg, UPB_SIZE(36, 72), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val,
-      arena);
-}
-UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_mutable_message_type(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len);
-}
-UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_resize_message_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(40, 80), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_FileDescriptorProto_add_message_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(40, 80), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_mutable_enum_type(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len);
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_resize_enum_type(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(44, 88), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_FileDescriptorProto_add_enum_type(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(44, 88), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_mutable_service(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (google_protobuf_ServiceDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(48, 96), len);
-}
-UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_resize_service(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_ServiceDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(48, 96), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_ServiceDescriptorProto* google_protobuf_FileDescriptorProto_add_service(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_ServiceDescriptorProto* sub = (struct google_protobuf_ServiceDescriptorProto*)_upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(48, 96), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_mutable_extension(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(52, 104), len);
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_resize_extension(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(52, 104), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_FileDescriptorProto_add_extension(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(52, 104), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_options(google_protobuf_FileDescriptorProto *msg, google_protobuf_FileOptions* value) {
-  _upb_sethas(msg, 4);
-  *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_FileOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_mutable_options(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_FileOptions* sub = (struct google_protobuf_FileOptions*)google_protobuf_FileDescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_FileOptions*)_upb_msg_new(&google_protobuf_FileOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_FileDescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_source_code_info(google_protobuf_FileDescriptorProto *msg, google_protobuf_SourceCodeInfo* value) {
-  _upb_sethas(msg, 5);
-  *UPB_PTR_AT(msg, UPB_SIZE(32, 64), google_protobuf_SourceCodeInfo*) = value;
-}
-UPB_INLINE struct google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_mutable_source_code_info(google_protobuf_FileDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_SourceCodeInfo* sub = (struct google_protobuf_SourceCodeInfo*)google_protobuf_FileDescriptorProto_source_code_info(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_SourceCodeInfo*)_upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_FileDescriptorProto_set_source_code_info(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_public_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 112), len);
-}
-UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_public_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(56, 112), len, UPB_TYPE_INT32, arena);
-}
-UPB_INLINE bool google_protobuf_FileDescriptorProto_add_public_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) {
-  return _upb_array_append_accessor(msg, UPB_SIZE(56, 112), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val,
-      arena);
-}
-UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(60, 120), len);
-}
-UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_weak_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(60, 120), len, UPB_TYPE_INT32, arena);
-}
-UPB_INLINE bool google_protobuf_FileDescriptorProto_add_weak_dependency(google_protobuf_FileDescriptorProto *msg, int32_t val, upb_arena *arena) {
-  return _upb_array_append_accessor(msg, UPB_SIZE(60, 120), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val,
-      arena);
-}
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_syntax(google_protobuf_FileDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value;
-}
-
-/* google.protobuf.DescriptorProto */
-
-UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_DescriptorProto *)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_DescriptorProto *google_protobuf_DescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_DescriptorProto *ret = google_protobuf_DescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_DescriptorProto_serialize(const google_protobuf_DescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_DescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_DescriptorProto_has_name(const google_protobuf_DescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_DescriptorProto_name(const google_protobuf_DescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_field(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); }
-UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_field(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_nested_type(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 40)); }
-UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_DescriptorProto_nested_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_enum_type(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(24, 48)); }
-UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_DescriptorProto_enum_type(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_extension_range(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(28, 56)); }
-UPB_INLINE const google_protobuf_DescriptorProto_ExtensionRange* const* google_protobuf_DescriptorProto_extension_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ExtensionRange* const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_extension(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(32, 64)); }
-UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_extension(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(32, 64), len); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_options(const google_protobuf_DescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE const google_protobuf_MessageOptions* google_protobuf_DescriptorProto_options(const google_protobuf_DescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_MessageOptions*); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_oneof_decl(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(36, 72)); }
-UPB_INLINE const google_protobuf_OneofDescriptorProto* const* google_protobuf_DescriptorProto_oneof_decl(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_OneofDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len); }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_reserved_range(const google_protobuf_DescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(40, 80)); }
-UPB_INLINE const google_protobuf_DescriptorProto_ReservedRange* const* google_protobuf_DescriptorProto_reserved_range(const google_protobuf_DescriptorProto *msg, size_t *len) { return (const google_protobuf_DescriptorProto_ReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(40, 80), len); }
-UPB_INLINE upb_strview const* google_protobuf_DescriptorProto_reserved_name(const google_protobuf_DescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); }
-
-UPB_INLINE void google_protobuf_DescriptorProto_set_name(google_protobuf_DescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_field(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len);
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_field(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_field(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(16, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_mutable_nested_type(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
-}
-UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_resize_nested_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_DescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_add_nested_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_msg_new(&google_protobuf_DescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(20, 40), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_mutable_enum_type(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_resize_enum_type(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_EnumDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_DescriptorProto_add_enum_type(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(24, 48), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_mutable_extension_range(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len);
-}
-UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_resize_extension_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_resize_accessor(msg, UPB_SIZE(28, 56), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_DescriptorProto_ExtensionRange* google_protobuf_DescriptorProto_add_extension_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_DescriptorProto_ExtensionRange* sub = (struct google_protobuf_DescriptorProto_ExtensionRange*)_upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(28, 56), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_extension(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 64), len);
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_extension(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_FieldDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(32, 64), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_extension(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(32, 64), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE void google_protobuf_DescriptorProto_set_options(google_protobuf_DescriptorProto *msg, google_protobuf_MessageOptions* value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_MessageOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_MessageOptions* google_protobuf_DescriptorProto_mutable_options(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_MessageOptions* sub = (struct google_protobuf_MessageOptions*)google_protobuf_DescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_MessageOptions*)_upb_msg_new(&google_protobuf_MessageOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_DescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_mutable_oneof_decl(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (google_protobuf_OneofDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len);
-}
-UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_resize_oneof_decl(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_OneofDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(36, 72), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_OneofDescriptorProto* google_protobuf_DescriptorProto_add_oneof_decl(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_OneofDescriptorProto* sub = (struct google_protobuf_OneofDescriptorProto*)_upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(36, 72), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_mutable_reserved_range(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(40, 80), len);
-}
-UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_resize_reserved_range(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_resize_accessor(msg, UPB_SIZE(40, 80), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_add_reserved_range(google_protobuf_DescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_DescriptorProto_ReservedRange* sub = (struct google_protobuf_DescriptorProto_ReservedRange*)_upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(40, 80), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE upb_strview* google_protobuf_DescriptorProto_mutable_reserved_name(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len);
-}
-UPB_INLINE upb_strview* google_protobuf_DescriptorProto_resize_reserved_name(google_protobuf_DescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(44, 88), len, UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool google_protobuf_DescriptorProto_add_reserved_name(google_protobuf_DescriptorProto *msg, upb_strview val, upb_arena *arena) {
-  return _upb_array_append_accessor(msg, UPB_SIZE(44, 88), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val,
-      arena);
-}
-
-/* google.protobuf.DescriptorProto.ExtensionRange */
-
-UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_new(upb_arena *arena) {
-  return (google_protobuf_DescriptorProto_ExtensionRange *)_upb_msg_new(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena);
-}
-UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange *google_protobuf_DescriptorProto_ExtensionRange_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_DescriptorProto_ExtensionRange *ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_DescriptorProto_ExtensionRange_serialize(const google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_DescriptorProto_ExtensionRange_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
-UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE const google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), const google_protobuf_ExtensionRangeOptions*); }
-
-UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_start(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_end(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_options(google_protobuf_DescriptorProto_ExtensionRange *msg, google_protobuf_ExtensionRangeOptions* value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 16), google_protobuf_ExtensionRangeOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_mutable_options(google_protobuf_DescriptorProto_ExtensionRange *msg, upb_arena *arena) {
-  struct google_protobuf_ExtensionRangeOptions* sub = (struct google_protobuf_ExtensionRangeOptions*)google_protobuf_DescriptorProto_ExtensionRange_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_ExtensionRangeOptions*)_upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_DescriptorProto_ExtensionRange_set_options(msg, sub);
-  }
-  return sub;
-}
-
-/* google.protobuf.DescriptorProto.ReservedRange */
-
-UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_new(upb_arena *arena) {
-  return (google_protobuf_DescriptorProto_ReservedRange *)_upb_msg_new(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena);
-}
-UPB_INLINE google_protobuf_DescriptorProto_ReservedRange *google_protobuf_DescriptorProto_ReservedRange_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_DescriptorProto_ReservedRange *ret = google_protobuf_DescriptorProto_ReservedRange_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_DescriptorProto_ReservedRange_serialize(const google_protobuf_DescriptorProto_ReservedRange *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_DescriptorProto_ReservedRange_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
-UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-
-UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_start(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_end(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-
-/* google.protobuf.ExtensionRangeOptions */
-
-UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_new(upb_arena *arena) {
-  return (google_protobuf_ExtensionRangeOptions *)_upb_msg_new(&google_protobuf_ExtensionRangeOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_ExtensionRangeOptions *google_protobuf_ExtensionRangeOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_ExtensionRangeOptions *ret = google_protobuf_ExtensionRangeOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_ExtensionRangeOptions_serialize(const google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_ExtensionRangeOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_ExtensionRangeOptions_has_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ExtensionRangeOptions_uninterpreted_option(const google_protobuf_ExtensionRangeOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
-
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_mutable_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_resize_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ExtensionRangeOptions_add_uninterpreted_option(google_protobuf_ExtensionRangeOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.FieldDescriptorProto */
-
-UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_FieldDescriptorProto *)_upb_msg_new(&google_protobuf_FieldDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_FieldDescriptorProto *google_protobuf_FieldDescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_FieldDescriptorProto *ret = google_protobuf_FieldDescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_FieldDescriptorProto_serialize(const google_protobuf_FieldDescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_FieldDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 6); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(36, 40), upb_strview); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 7); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(44, 56), upb_strview); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_number(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_number(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), int32_t); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_label(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_label(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_type(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 8); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(52, 72), upb_strview); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 9); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(60, 88), upb_strview); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 11); }
-UPB_INLINE const google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_options(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(76, 120), const google_protobuf_FieldOptions*); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 28), int32_t); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 10); }
-UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(68, 104), upb_strview); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 32), bool); }
-
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 6);
-  *UPB_PTR_AT(msg, UPB_SIZE(36, 40), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_extendee(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 7);
-  *UPB_PTR_AT(msg, UPB_SIZE(44, 56), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_number(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(24, 24), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_label(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 8);
-  *UPB_PTR_AT(msg, UPB_SIZE(52, 72), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 9);
-  *UPB_PTR_AT(msg, UPB_SIZE(60, 88), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_options(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldOptions* value) {
-  _upb_sethas(msg, 11);
-  *UPB_PTR_AT(msg, UPB_SIZE(76, 120), google_protobuf_FieldOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_mutable_options(google_protobuf_FieldDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_FieldOptions* sub = (struct google_protobuf_FieldOptions*)google_protobuf_FieldDescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_FieldOptions*)_upb_msg_new(&google_protobuf_FieldOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_FieldDescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_oneof_index(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
-  _upb_sethas(msg, 4);
-  *UPB_PTR_AT(msg, UPB_SIZE(28, 28), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 10);
-  *UPB_PTR_AT(msg, UPB_SIZE(68, 104), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_proto3_optional(google_protobuf_FieldDescriptorProto *msg, bool value) {
-  _upb_sethas(msg, 5);
-  *UPB_PTR_AT(msg, UPB_SIZE(32, 32), bool) = value;
-}
-
-/* google.protobuf.OneofDescriptorProto */
-
-UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_OneofDescriptorProto *)_upb_msg_new(&google_protobuf_OneofDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_OneofDescriptorProto *google_protobuf_OneofDescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_OneofDescriptorProto *ret = google_protobuf_OneofDescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_OneofDescriptorProto_serialize(const google_protobuf_OneofDescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_OneofDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_name(const google_protobuf_OneofDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_OneofDescriptorProto_name(const google_protobuf_OneofDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_options(const google_protobuf_OneofDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE const google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_options(const google_protobuf_OneofDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_OneofOptions*); }
-
-UPB_INLINE void google_protobuf_OneofDescriptorProto_set_name(google_protobuf_OneofDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_OneofDescriptorProto_set_options(google_protobuf_OneofDescriptorProto *msg, google_protobuf_OneofOptions* value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_OneofOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_mutable_options(google_protobuf_OneofDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_OneofOptions* sub = (struct google_protobuf_OneofOptions*)google_protobuf_OneofDescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_OneofOptions*)_upb_msg_new(&google_protobuf_OneofOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_OneofDescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-
-/* google.protobuf.EnumDescriptorProto */
-
-UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_EnumDescriptorProto *)_upb_msg_new(&google_protobuf_EnumDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto *google_protobuf_EnumDescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_EnumDescriptorProto *ret = google_protobuf_EnumDescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_EnumDescriptorProto_serialize(const google_protobuf_EnumDescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_EnumDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_name(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_EnumDescriptorProto_name(const google_protobuf_EnumDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_value(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); }
-UPB_INLINE const google_protobuf_EnumValueDescriptorProto* const* google_protobuf_EnumDescriptorProto_value(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumValueDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_options(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE const google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_options(const google_protobuf_EnumDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_EnumOptions*); }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_reserved_range(const google_protobuf_EnumDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 40)); }
-UPB_INLINE const google_protobuf_EnumDescriptorProto_EnumReservedRange* const* google_protobuf_EnumDescriptorProto_reserved_range(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (const google_protobuf_EnumDescriptorProto_EnumReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
-UPB_INLINE upb_strview const* google_protobuf_EnumDescriptorProto_reserved_name(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
-
-UPB_INLINE void google_protobuf_EnumDescriptorProto_set_name(google_protobuf_EnumDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_mutable_value(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
-  return (google_protobuf_EnumValueDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len);
-}
-UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_resize_value(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_EnumValueDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_EnumValueDescriptorProto* google_protobuf_EnumDescriptorProto_add_value(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_EnumValueDescriptorProto* sub = (struct google_protobuf_EnumValueDescriptorProto*)_upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(16, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE void google_protobuf_EnumDescriptorProto_set_options(google_protobuf_EnumDescriptorProto *msg, google_protobuf_EnumOptions* value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_EnumOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_mutable_options(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_EnumOptions* sub = (struct google_protobuf_EnumOptions*)google_protobuf_EnumDescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_EnumOptions*)_upb_msg_new(&google_protobuf_EnumOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_EnumDescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_mutable_reserved_range(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
-  return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_resize_reserved_range(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_EnumDescriptorProto_EnumReservedRange* google_protobuf_EnumDescriptorProto_add_reserved_range(google_protobuf_EnumDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_EnumDescriptorProto_EnumReservedRange* sub = (struct google_protobuf_EnumDescriptorProto_EnumReservedRange*)_upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(20, 40), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_mutable_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
-}
-UPB_INLINE upb_strview* google_protobuf_EnumDescriptorProto_resize_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_add_reserved_name(google_protobuf_EnumDescriptorProto *msg, upb_strview val, upb_arena *arena) {
-  return _upb_array_append_accessor(msg, UPB_SIZE(24, 48), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val,
-      arena);
-}
-
-/* google.protobuf.EnumDescriptorProto.EnumReservedRange */
-
-UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_new(upb_arena *arena) {
-  return (google_protobuf_EnumDescriptorProto_EnumReservedRange *)_upb_msg_new(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena);
-}
-UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange *google_protobuf_EnumDescriptorProto_EnumReservedRange_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_EnumDescriptorProto_EnumReservedRange *ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_EnumDescriptorProto_EnumReservedRange_serialize(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-
-UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_start(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_end(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-
-/* google.protobuf.EnumValueDescriptorProto */
-
-UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_EnumValueDescriptorProto *)_upb_msg_new(&google_protobuf_EnumValueDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_EnumValueDescriptorProto *google_protobuf_EnumValueDescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_EnumValueDescriptorProto *ret = google_protobuf_EnumValueDescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_EnumValueDescriptorProto_serialize(const google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_EnumValueDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_name(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE upb_strview google_protobuf_EnumValueDescriptorProto_name(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_number(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_EnumValueDescriptorProto_number(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
-UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_options(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE const google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_options(const google_protobuf_EnumValueDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), const google_protobuf_EnumValueOptions*); }
-
-UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_name(google_protobuf_EnumValueDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_number(google_protobuf_EnumValueDescriptorProto *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_options(google_protobuf_EnumValueDescriptorProto *msg, google_protobuf_EnumValueOptions* value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(16, 24), google_protobuf_EnumValueOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_mutable_options(google_protobuf_EnumValueDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_EnumValueOptions* sub = (struct google_protobuf_EnumValueOptions*)google_protobuf_EnumValueDescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_EnumValueOptions*)_upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_EnumValueDescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-
-/* google.protobuf.ServiceDescriptorProto */
-
-UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_ServiceDescriptorProto *)_upb_msg_new(&google_protobuf_ServiceDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_ServiceDescriptorProto *google_protobuf_ServiceDescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_ServiceDescriptorProto *ret = google_protobuf_ServiceDescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_ServiceDescriptorProto_serialize(const google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_ServiceDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_name(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_ServiceDescriptorProto_name(const google_protobuf_ServiceDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_method(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); }
-UPB_INLINE const google_protobuf_MethodDescriptorProto* const* google_protobuf_ServiceDescriptorProto_method(const google_protobuf_ServiceDescriptorProto *msg, size_t *len) { return (const google_protobuf_MethodDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); }
-UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_options(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE const google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_options(const google_protobuf_ServiceDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const google_protobuf_ServiceOptions*); }
-
-UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_name(google_protobuf_ServiceDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_mutable_method(google_protobuf_ServiceDescriptorProto *msg, size_t *len) {
-  return (google_protobuf_MethodDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len);
-}
-UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_resize_method(google_protobuf_ServiceDescriptorProto *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_MethodDescriptorProto**)_upb_array_resize_accessor(msg, UPB_SIZE(16, 32), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_MethodDescriptorProto* google_protobuf_ServiceDescriptorProto_add_method(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_MethodDescriptorProto* sub = (struct google_protobuf_MethodDescriptorProto*)_upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(16, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_options(google_protobuf_ServiceDescriptorProto *msg, google_protobuf_ServiceOptions* value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), google_protobuf_ServiceOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_mutable_options(google_protobuf_ServiceDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_ServiceOptions* sub = (struct google_protobuf_ServiceOptions*)google_protobuf_ServiceDescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_ServiceOptions*)_upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_ServiceDescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-
-/* google.protobuf.MethodDescriptorProto */
-
-UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_new(upb_arena *arena) {
-  return (google_protobuf_MethodDescriptorProto *)_upb_msg_new(&google_protobuf_MethodDescriptorProto_msginit, arena);
-}
-UPB_INLINE google_protobuf_MethodDescriptorProto *google_protobuf_MethodDescriptorProto_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_MethodDescriptorProto *ret = google_protobuf_MethodDescriptorProto_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_MethodDescriptorProto_serialize(const google_protobuf_MethodDescriptorProto *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_MethodDescriptorProto_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_name(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_name(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_input_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_input_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_output_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE upb_strview google_protobuf_MethodDescriptorProto_output_type(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_options(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 6); }
-UPB_INLINE const google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_options(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const google_protobuf_MethodOptions*); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_client_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_server_streaming(const google_protobuf_MethodDescriptorProto *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); }
-
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_name(google_protobuf_MethodDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_input_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 4);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_output_type(google_protobuf_MethodDescriptorProto *msg, upb_strview value) {
-  _upb_sethas(msg, 5);
-  *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_options(google_protobuf_MethodDescriptorProto *msg, google_protobuf_MethodOptions* value) {
-  _upb_sethas(msg, 6);
-  *UPB_PTR_AT(msg, UPB_SIZE(28, 56), google_protobuf_MethodOptions*) = value;
-}
-UPB_INLINE struct google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_mutable_options(google_protobuf_MethodDescriptorProto *msg, upb_arena *arena) {
-  struct google_protobuf_MethodOptions* sub = (struct google_protobuf_MethodOptions*)google_protobuf_MethodDescriptorProto_options(msg);
-  if (sub == NULL) {
-    sub = (struct google_protobuf_MethodOptions*)_upb_msg_new(&google_protobuf_MethodOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_MethodDescriptorProto_set_options(msg, sub);
-  }
-  return sub;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_client_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_server_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value;
-}
-
-/* google.protobuf.FileOptions */
-
-UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_new(upb_arena *arena) {
-  return (google_protobuf_FileOptions *)_upb_msg_new(&google_protobuf_FileOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_FileOptions *google_protobuf_FileOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_FileOptions *ret = google_protobuf_FileOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_FileOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_FileOptions_serialize(const google_protobuf_FileOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_FileOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_FileOptions_has_java_package(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 11); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_java_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 32), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_outer_classname(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 12); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_java_outer_classname(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(36, 48), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_optimize_for(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_FileOptions_optimize_for(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_multiple_files(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE bool google_protobuf_FileOptions_java_multiple_files(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_go_package(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 13); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_go_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(44, 64), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_cc_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE bool google_protobuf_FileOptions_cc_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(17, 17), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE bool google_protobuf_FileOptions_java_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(18, 18), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_py_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE bool google_protobuf_FileOptions_py_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(19, 19), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 6); }
-UPB_INLINE bool google_protobuf_FileOptions_java_generate_equals_and_hash(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_deprecated(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 7); }
-UPB_INLINE bool google_protobuf_FileOptions_deprecated(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(21, 21), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 8); }
-UPB_INLINE bool google_protobuf_FileOptions_java_string_check_utf8(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(22, 22), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 9); }
-UPB_INLINE bool google_protobuf_FileOptions_cc_enable_arenas(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(23, 23), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_objc_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 14); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_objc_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(52, 80), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_csharp_namespace(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 15); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_csharp_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(60, 96), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_swift_prefix(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 16); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_swift_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(68, 112), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 17); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_php_class_prefix(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(76, 128), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_namespace(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 18); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_php_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(84, 144), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_generic_services(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 10); }
-UPB_INLINE bool google_protobuf_FileOptions_php_generic_services(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), bool); }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 19); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(92, 160), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_ruby_package(const google_protobuf_FileOptions *msg) { return _upb_has_field(msg, 20); }
-UPB_INLINE upb_strview google_protobuf_FileOptions_ruby_package(const google_protobuf_FileOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(100, 176), upb_strview); }
-UPB_INLINE bool google_protobuf_FileOptions_has_uninterpreted_option(const google_protobuf_FileOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(108, 192)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FileOptions_uninterpreted_option(const google_protobuf_FileOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(108, 192), len); }
-
-UPB_INLINE void google_protobuf_FileOptions_set_java_package(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 11);
-  *UPB_PTR_AT(msg, UPB_SIZE(28, 32), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_java_outer_classname(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 12);
-  *UPB_PTR_AT(msg, UPB_SIZE(36, 48), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_optimize_for(google_protobuf_FileOptions *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_java_multiple_files(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_go_package(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 13);
-  *UPB_PTR_AT(msg, UPB_SIZE(44, 64), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_cc_generic_services(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(17, 17), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_java_generic_services(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 4);
-  *UPB_PTR_AT(msg, UPB_SIZE(18, 18), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_py_generic_services(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 5);
-  *UPB_PTR_AT(msg, UPB_SIZE(19, 19), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_java_generate_equals_and_hash(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 6);
-  *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_deprecated(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 7);
-  *UPB_PTR_AT(msg, UPB_SIZE(21, 21), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_java_string_check_utf8(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 8);
-  *UPB_PTR_AT(msg, UPB_SIZE(22, 22), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_cc_enable_arenas(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 9);
-  *UPB_PTR_AT(msg, UPB_SIZE(23, 23), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_objc_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 14);
-  *UPB_PTR_AT(msg, UPB_SIZE(52, 80), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_csharp_namespace(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 15);
-  *UPB_PTR_AT(msg, UPB_SIZE(60, 96), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_swift_prefix(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 16);
-  *UPB_PTR_AT(msg, UPB_SIZE(68, 112), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_php_class_prefix(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 17);
-  *UPB_PTR_AT(msg, UPB_SIZE(76, 128), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_php_namespace(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 18);
-  *UPB_PTR_AT(msg, UPB_SIZE(84, 144), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_php_generic_services(google_protobuf_FileOptions *msg, bool value) {
-  _upb_sethas(msg, 10);
-  *UPB_PTR_AT(msg, UPB_SIZE(24, 24), bool) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_php_metadata_namespace(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 19);
-  *UPB_PTR_AT(msg, UPB_SIZE(92, 160), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_ruby_package(google_protobuf_FileOptions *msg, upb_strview value) {
-  _upb_sethas(msg, 20);
-  *UPB_PTR_AT(msg, UPB_SIZE(100, 176), upb_strview) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_mutable_uninterpreted_option(google_protobuf_FileOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(108, 192), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_resize_uninterpreted_option(google_protobuf_FileOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(108, 192), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FileOptions_add_uninterpreted_option(google_protobuf_FileOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(108, 192), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.MessageOptions */
-
-UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_new(upb_arena *arena) {
-  return (google_protobuf_MessageOptions *)_upb_msg_new(&google_protobuf_MessageOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_MessageOptions *google_protobuf_MessageOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_MessageOptions *ret = google_protobuf_MessageOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_MessageOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_MessageOptions_serialize(const google_protobuf_MessageOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_MessageOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_MessageOptions_has_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_MessageOptions_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
-UPB_INLINE bool google_protobuf_MessageOptions_has_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE bool google_protobuf_MessageOptions_no_standard_descriptor_accessor(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); }
-UPB_INLINE bool google_protobuf_MessageOptions_has_deprecated(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE bool google_protobuf_MessageOptions_deprecated(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool); }
-UPB_INLINE bool google_protobuf_MessageOptions_has_map_entry(const google_protobuf_MessageOptions *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE bool google_protobuf_MessageOptions_map_entry(const google_protobuf_MessageOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool); }
-UPB_INLINE bool google_protobuf_MessageOptions_has_uninterpreted_option(const google_protobuf_MessageOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 8)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MessageOptions_uninterpreted_option(const google_protobuf_MessageOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(8, 8), len); }
-
-UPB_INLINE void google_protobuf_MessageOptions_set_message_set_wire_format(google_protobuf_MessageOptions *msg, bool value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
-}
-UPB_INLINE void google_protobuf_MessageOptions_set_no_standard_descriptor_accessor(google_protobuf_MessageOptions *msg, bool value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value;
-}
-UPB_INLINE void google_protobuf_MessageOptions_set_deprecated(google_protobuf_MessageOptions *msg, bool value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool) = value;
-}
-UPB_INLINE void google_protobuf_MessageOptions_set_map_entry(google_protobuf_MessageOptions *msg, bool value) {
-  _upb_sethas(msg, 4);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_mutable_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 8), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_resize_uninterpreted_option(google_protobuf_MessageOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(8, 8), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MessageOptions_add_uninterpreted_option(google_protobuf_MessageOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(8, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.FieldOptions */
-
-UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_new(upb_arena *arena) {
-  return (google_protobuf_FieldOptions *)_upb_msg_new(&google_protobuf_FieldOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_FieldOptions *google_protobuf_FieldOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_FieldOptions *ret = google_protobuf_FieldOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_FieldOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_FieldOptions_serialize(const google_protobuf_FieldOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_FieldOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_FieldOptions_has_ctype(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_FieldOptions_ctype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_packed(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE bool google_protobuf_FieldOptions_packed(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), bool); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_deprecated(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE bool google_protobuf_FieldOptions_deprecated(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(25, 25), bool); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_lazy(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE bool google_protobuf_FieldOptions_lazy(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(26, 26), bool); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_jstype(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_FieldOptions_jstype(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_weak(const google_protobuf_FieldOptions *msg) { return _upb_has_field(msg, 6); }
-UPB_INLINE bool google_protobuf_FieldOptions_weak(const google_protobuf_FieldOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(27, 27), bool); }
-UPB_INLINE bool google_protobuf_FieldOptions_has_uninterpreted_option(const google_protobuf_FieldOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(28, 32)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FieldOptions_uninterpreted_option(const google_protobuf_FieldOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(28, 32), len); }
-
-UPB_INLINE void google_protobuf_FieldOptions_set_ctype(google_protobuf_FieldOptions *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_FieldOptions_set_packed(google_protobuf_FieldOptions *msg, bool value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(24, 24), bool) = value;
-}
-UPB_INLINE void google_protobuf_FieldOptions_set_deprecated(google_protobuf_FieldOptions *msg, bool value) {
-  _upb_sethas(msg, 4);
-  *UPB_PTR_AT(msg, UPB_SIZE(25, 25), bool) = value;
-}
-UPB_INLINE void google_protobuf_FieldOptions_set_lazy(google_protobuf_FieldOptions *msg, bool value) {
-  _upb_sethas(msg, 5);
-  *UPB_PTR_AT(msg, UPB_SIZE(26, 26), bool) = value;
-}
-UPB_INLINE void google_protobuf_FieldOptions_set_jstype(google_protobuf_FieldOptions *msg, int32_t value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_FieldOptions_set_weak(google_protobuf_FieldOptions *msg, bool value) {
-  _upb_sethas(msg, 6);
-  *UPB_PTR_AT(msg, UPB_SIZE(27, 27), bool) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_mutable_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 32), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_resize_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(28, 32), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FieldOptions_add_uninterpreted_option(google_protobuf_FieldOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(28, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.OneofOptions */
-
-UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_new(upb_arena *arena) {
-  return (google_protobuf_OneofOptions *)_upb_msg_new(&google_protobuf_OneofOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_OneofOptions *google_protobuf_OneofOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_OneofOptions *ret = google_protobuf_OneofOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_OneofOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_OneofOptions_serialize(const google_protobuf_OneofOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_OneofOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_OneofOptions_has_uninterpreted_option(const google_protobuf_OneofOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_OneofOptions_uninterpreted_option(const google_protobuf_OneofOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
-
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_mutable_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_resize_uninterpreted_option(google_protobuf_OneofOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_OneofOptions_add_uninterpreted_option(google_protobuf_OneofOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.EnumOptions */
-
-UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_new(upb_arena *arena) {
-  return (google_protobuf_EnumOptions *)_upb_msg_new(&google_protobuf_EnumOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_EnumOptions *google_protobuf_EnumOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_EnumOptions *ret = google_protobuf_EnumOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_EnumOptions_serialize(const google_protobuf_EnumOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_EnumOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_EnumOptions_has_allow_alias(const google_protobuf_EnumOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_EnumOptions_allow_alias(const google_protobuf_EnumOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
-UPB_INLINE bool google_protobuf_EnumOptions_has_deprecated(const google_protobuf_EnumOptions *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE bool google_protobuf_EnumOptions_deprecated(const google_protobuf_EnumOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); }
-UPB_INLINE bool google_protobuf_EnumOptions_has_uninterpreted_option(const google_protobuf_EnumOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumOptions_uninterpreted_option(const google_protobuf_EnumOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
-
-UPB_INLINE void google_protobuf_EnumOptions_set_allow_alias(google_protobuf_EnumOptions *msg, bool value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
-}
-UPB_INLINE void google_protobuf_EnumOptions_set_deprecated(google_protobuf_EnumOptions *msg, bool value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_mutable_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_resize_uninterpreted_option(google_protobuf_EnumOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumOptions_add_uninterpreted_option(google_protobuf_EnumOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.EnumValueOptions */
-
-UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_new(upb_arena *arena) {
-  return (google_protobuf_EnumValueOptions *)_upb_msg_new(&google_protobuf_EnumValueOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_EnumValueOptions *google_protobuf_EnumValueOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_EnumValueOptions *ret = google_protobuf_EnumValueOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_EnumValueOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_EnumValueOptions_serialize(const google_protobuf_EnumValueOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_EnumValueOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_EnumValueOptions_has_deprecated(const google_protobuf_EnumValueOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_EnumValueOptions_deprecated(const google_protobuf_EnumValueOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
-UPB_INLINE bool google_protobuf_EnumValueOptions_has_uninterpreted_option(const google_protobuf_EnumValueOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumValueOptions_uninterpreted_option(const google_protobuf_EnumValueOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
-
-UPB_INLINE void google_protobuf_EnumValueOptions_set_deprecated(google_protobuf_EnumValueOptions *msg, bool value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_mutable_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_resize_uninterpreted_option(google_protobuf_EnumValueOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumValueOptions_add_uninterpreted_option(google_protobuf_EnumValueOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.ServiceOptions */
-
-UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_new(upb_arena *arena) {
-  return (google_protobuf_ServiceOptions *)_upb_msg_new(&google_protobuf_ServiceOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_ServiceOptions *google_protobuf_ServiceOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_ServiceOptions *ret = google_protobuf_ServiceOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_ServiceOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_ServiceOptions_serialize(const google_protobuf_ServiceOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_ServiceOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_ServiceOptions_has_deprecated(const google_protobuf_ServiceOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_ServiceOptions_deprecated(const google_protobuf_ServiceOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
-UPB_INLINE bool google_protobuf_ServiceOptions_has_uninterpreted_option(const google_protobuf_ServiceOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ServiceOptions_uninterpreted_option(const google_protobuf_ServiceOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); }
-
-UPB_INLINE void google_protobuf_ServiceOptions_set_deprecated(google_protobuf_ServiceOptions *msg, bool value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_mutable_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_resize_uninterpreted_option(google_protobuf_ServiceOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ServiceOptions_add_uninterpreted_option(google_protobuf_ServiceOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.MethodOptions */
-
-UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_new(upb_arena *arena) {
-  return (google_protobuf_MethodOptions *)_upb_msg_new(&google_protobuf_MethodOptions_msginit, arena);
-}
-UPB_INLINE google_protobuf_MethodOptions *google_protobuf_MethodOptions_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_MethodOptions *ret = google_protobuf_MethodOptions_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_MethodOptions_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_MethodOptions_serialize(const google_protobuf_MethodOptions *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_MethodOptions_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_MethodOptions_has_deprecated(const google_protobuf_MethodOptions *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE bool google_protobuf_MethodOptions_deprecated(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool); }
-UPB_INLINE bool google_protobuf_MethodOptions_has_idempotency_level(const google_protobuf_MethodOptions *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_MethodOptions_idempotency_level(const google_protobuf_MethodOptions *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-UPB_INLINE bool google_protobuf_MethodOptions_has_uninterpreted_option(const google_protobuf_MethodOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 24)); }
-UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MethodOptions_uninterpreted_option(const google_protobuf_MethodOptions *msg, size_t *len) { return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(20, 24), len); }
-
-UPB_INLINE void google_protobuf_MethodOptions_set_deprecated(google_protobuf_MethodOptions *msg, bool value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool) = value;
-}
-UPB_INLINE void google_protobuf_MethodOptions_set_idempotency_level(google_protobuf_MethodOptions *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_mutable_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 24), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_resize_uninterpreted_option(google_protobuf_MethodOptions *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 24), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MethodOptions_add_uninterpreted_option(google_protobuf_MethodOptions *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(20, 24), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.UninterpretedOption */
-
-UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_new(upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption *)_upb_msg_new(&google_protobuf_UninterpretedOption_msginit, arena);
-}
-UPB_INLINE google_protobuf_UninterpretedOption *google_protobuf_UninterpretedOption_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_UninterpretedOption *ret = google_protobuf_UninterpretedOption_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_UninterpretedOption_serialize(const google_protobuf_UninterpretedOption *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_UninterpretedOption_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_name(const google_protobuf_UninterpretedOption *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(56, 80)); }
-UPB_INLINE const google_protobuf_UninterpretedOption_NamePart* const* google_protobuf_UninterpretedOption_name(const google_protobuf_UninterpretedOption *msg, size_t *len) { return (const google_protobuf_UninterpretedOption_NamePart* const*)_upb_array_accessor(msg, UPB_SIZE(56, 80), len); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_identifier_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 4); }
-UPB_INLINE upb_strview google_protobuf_UninterpretedOption_identifier_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE uint64_t google_protobuf_UninterpretedOption_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int64_t google_protobuf_UninterpretedOption_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_double_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE double google_protobuf_UninterpretedOption_double_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_string_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 5); }
-UPB_INLINE upb_strview google_protobuf_UninterpretedOption_string_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_strview); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return _upb_has_field(msg, 6); }
-UPB_INLINE upb_strview google_protobuf_UninterpretedOption_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_strview); }
-
-UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_mutable_name(google_protobuf_UninterpretedOption *msg, size_t *len) {
-  return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_mutable_accessor(msg, UPB_SIZE(56, 80), len);
-}
-UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_resize_name(google_protobuf_UninterpretedOption *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_resize_accessor(msg, UPB_SIZE(56, 80), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_UninterpretedOption_NamePart* google_protobuf_UninterpretedOption_add_name(google_protobuf_UninterpretedOption *msg, upb_arena *arena) {
-  struct google_protobuf_UninterpretedOption_NamePart* sub = (struct google_protobuf_UninterpretedOption_NamePart*)_upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(56, 80), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_identifier_value(google_protobuf_UninterpretedOption *msg, upb_strview value) {
-  _upb_sethas(msg, 4);
-  *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_positive_int_value(google_protobuf_UninterpretedOption *msg, uint64_t value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), uint64_t) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_negative_int_value(google_protobuf_UninterpretedOption *msg, int64_t value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), int64_t) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_double_value(google_protobuf_UninterpretedOption *msg, double value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_string_value(google_protobuf_UninterpretedOption *msg, upb_strview value) {
-  _upb_sethas(msg, 5);
-  *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_aggregate_value(google_protobuf_UninterpretedOption *msg, upb_strview value) {
-  _upb_sethas(msg, 6);
-  *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_strview) = value;
-}
-
-/* google.protobuf.UninterpretedOption.NamePart */
-
-UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_new(upb_arena *arena) {
-  return (google_protobuf_UninterpretedOption_NamePart *)_upb_msg_new(&google_protobuf_UninterpretedOption_NamePart_msginit, arena);
-}
-UPB_INLINE google_protobuf_UninterpretedOption_NamePart *google_protobuf_UninterpretedOption_NamePart_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_UninterpretedOption_NamePart *ret = google_protobuf_UninterpretedOption_NamePart_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_UninterpretedOption_NamePart_serialize(const google_protobuf_UninterpretedOption_NamePart *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_UninterpretedOption_NamePart_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE upb_strview google_protobuf_UninterpretedOption_NamePart_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_is_extension(const google_protobuf_UninterpretedOption_NamePart *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool); }
-
-UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_name_part(google_protobuf_UninterpretedOption_NamePart *msg, upb_strview value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_is_extension(google_protobuf_UninterpretedOption_NamePart *msg, bool value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool) = value;
-}
-
-/* google.protobuf.SourceCodeInfo */
-
-UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_new(upb_arena *arena) {
-  return (google_protobuf_SourceCodeInfo *)_upb_msg_new(&google_protobuf_SourceCodeInfo_msginit, arena);
-}
-UPB_INLINE google_protobuf_SourceCodeInfo *google_protobuf_SourceCodeInfo_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_SourceCodeInfo *ret = google_protobuf_SourceCodeInfo_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_SourceCodeInfo_serialize(const google_protobuf_SourceCodeInfo *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_SourceCodeInfo_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_SourceCodeInfo_has_location(const google_protobuf_SourceCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
-UPB_INLINE const google_protobuf_SourceCodeInfo_Location* const* google_protobuf_SourceCodeInfo_location(const google_protobuf_SourceCodeInfo *msg, size_t *len) { return (const google_protobuf_SourceCodeInfo_Location* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
-
-UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_mutable_location(google_protobuf_SourceCodeInfo *msg, size_t *len) {
-  return (google_protobuf_SourceCodeInfo_Location**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
-}
-UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_resize_location(google_protobuf_SourceCodeInfo *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_SourceCodeInfo_Location**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_add_location(google_protobuf_SourceCodeInfo *msg, upb_arena *arena) {
-  struct google_protobuf_SourceCodeInfo_Location* sub = (struct google_protobuf_SourceCodeInfo_Location*)_upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.SourceCodeInfo.Location */
-
-UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_new(upb_arena *arena) {
-  return (google_protobuf_SourceCodeInfo_Location *)_upb_msg_new(&google_protobuf_SourceCodeInfo_Location_msginit, arena);
-}
-UPB_INLINE google_protobuf_SourceCodeInfo_Location *google_protobuf_SourceCodeInfo_Location_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_SourceCodeInfo_Location *ret = google_protobuf_SourceCodeInfo_Location_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_SourceCodeInfo_Location_serialize(const google_protobuf_SourceCodeInfo_Location *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_SourceCodeInfo_Location_msginit, arena, len);
-}
-
-UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_path(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 40), len); }
-UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_span(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_leading_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); }
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE upb_strview google_protobuf_SourceCodeInfo_Location_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); }
-UPB_INLINE upb_strview const* google_protobuf_SourceCodeInfo_Location_leading_detached_comments(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); }
-
-UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_path(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
-  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 40), len);
-}
-UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_path(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) {
-  return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(20, 40), len, UPB_TYPE_INT32, arena);
-}
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_path(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) {
-  return _upb_array_append_accessor(msg, UPB_SIZE(20, 40), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val,
-      arena);
-}
-UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_span(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
-  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
-}
-UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_span(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) {
-  return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(24, 48), len, UPB_TYPE_INT32, arena);
-}
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_span(google_protobuf_SourceCodeInfo_Location *msg, int32_t val, upb_arena *arena) {
-  return _upb_array_append_accessor(msg, UPB_SIZE(24, 48), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val,
-      arena);
-}
-UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_leading_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_trailing_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value;
-}
-UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_mutable_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
-  return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len);
-}
-UPB_INLINE upb_strview* google_protobuf_SourceCodeInfo_Location_resize_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_arena *arena) {
-  return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(28, 56), len, UPB_TYPE_STRING, arena);
-}
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_strview val, upb_arena *arena) {
-  return _upb_array_append_accessor(msg, UPB_SIZE(28, 56), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val,
-      arena);
-}
-
-/* google.protobuf.GeneratedCodeInfo */
-
-UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_new(upb_arena *arena) {
-  return (google_protobuf_GeneratedCodeInfo *)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_msginit, arena);
-}
-UPB_INLINE google_protobuf_GeneratedCodeInfo *google_protobuf_GeneratedCodeInfo_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_GeneratedCodeInfo *ret = google_protobuf_GeneratedCodeInfo_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_GeneratedCodeInfo_serialize(const google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_msginit, arena, len);
-}
-
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_has_annotation(const google_protobuf_GeneratedCodeInfo *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); }
-UPB_INLINE const google_protobuf_GeneratedCodeInfo_Annotation* const* google_protobuf_GeneratedCodeInfo_annotation(const google_protobuf_GeneratedCodeInfo *msg, size_t *len) { return (const google_protobuf_GeneratedCodeInfo_Annotation* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); }
-
-UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_mutable_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t *len) {
-  return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len);
-}
-UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_resize_annotation(google_protobuf_GeneratedCodeInfo *msg, size_t len, upb_arena *arena) {
-  return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_resize_accessor(msg, UPB_SIZE(0, 0), len, UPB_TYPE_MESSAGE, arena);
-}
-UPB_INLINE struct google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_add_annotation(google_protobuf_GeneratedCodeInfo *msg, upb_arena *arena) {
-  struct google_protobuf_GeneratedCodeInfo_Annotation* sub = (struct google_protobuf_GeneratedCodeInfo_Annotation*)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena);
-  bool ok = _upb_array_append_accessor(
-      msg, UPB_SIZE(0, 0), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena);
-  if (!ok) return NULL;
-  return sub;
-}
-
-/* google.protobuf.GeneratedCodeInfo.Annotation */
-
-UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_new(upb_arena *arena) {
-  return (google_protobuf_GeneratedCodeInfo_Annotation *)_upb_msg_new(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena);
-}
-UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation *google_protobuf_GeneratedCodeInfo_Annotation_parse(const char *buf, size_t size,
-                        upb_arena *arena) {
-  google_protobuf_GeneratedCodeInfo_Annotation *ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena);
-  return (ret && upb_decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena)) ? ret : NULL;
-}
-UPB_INLINE char *google_protobuf_GeneratedCodeInfo_Annotation_serialize(const google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_arena *arena, size_t *len) {
-  return upb_encode(msg, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena, len);
-}
-
-UPB_INLINE int32_t const* google_protobuf_GeneratedCodeInfo_Annotation_path(const google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) { return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(20, 32), len); }
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_has_field(msg, 3); }
-UPB_INLINE upb_strview google_protobuf_GeneratedCodeInfo_Annotation_source_file(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview); }
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_has_field(msg, 1); }
-UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); }
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_has_field(msg, 2); }
-UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t); }
-
-UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_mutable_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t *len) {
-  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 32), len);
-}
-UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_resize_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, size_t len, upb_arena *arena) {
-  return (int32_t*)_upb_array_resize_accessor(msg, UPB_SIZE(20, 32), len, UPB_TYPE_INT32, arena);
-}
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_add_path(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t val, upb_arena *arena) {
-  return _upb_array_append_accessor(msg, UPB_SIZE(20, 32), UPB_SIZE(4, 4), UPB_TYPE_INT32, &val,
-      arena);
-}
-UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_source_file(google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_strview value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_strview) = value;
-}
-UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_begin(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value;
-}
-UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_end(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) = value;
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-
-#endif  /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ */
-/*
-** Defs are upb's internal representation of the constructs that can appear
-** in a .proto file:
-**
-** - upb_msgdef: describes a "message" construct.
-** - upb_fielddef: describes a message field.
-** - upb_filedef: describes a .proto file and its defs.
-** - upb_enumdef: describes an enum.
-** - upb_oneofdef: describes a oneof.
-**
-** TODO: definitions of services.
-*/
-
-#ifndef UPB_DEF_H_
-#define UPB_DEF_H_
-
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif  /* __cplusplus */
-
-struct upb_enumdef;
-typedef struct upb_enumdef upb_enumdef;
-struct upb_fielddef;
-typedef struct upb_fielddef upb_fielddef;
-struct upb_filedef;
-typedef struct upb_filedef upb_filedef;
-struct upb_msgdef;
-typedef struct upb_msgdef upb_msgdef;
-struct upb_oneofdef;
-typedef struct upb_oneofdef upb_oneofdef;
-struct upb_symtab;
-typedef struct upb_symtab upb_symtab;
-
-typedef enum {
-  UPB_SYNTAX_PROTO2 = 2,
-  UPB_SYNTAX_PROTO3 = 3
-} upb_syntax_t;
-
-/* All the different kind of well known type messages. For simplicity of check,
- * number wrappers and string wrappers are grouped together. Make sure the
- * order and merber of these groups are not changed.
- */
-typedef enum {
-  UPB_WELLKNOWN_UNSPECIFIED,
-  UPB_WELLKNOWN_ANY,
-  UPB_WELLKNOWN_FIELDMASK,
-  UPB_WELLKNOWN_DURATION,
-  UPB_WELLKNOWN_TIMESTAMP,
-  /* number wrappers */
-  UPB_WELLKNOWN_DOUBLEVALUE,
-  UPB_WELLKNOWN_FLOATVALUE,
-  UPB_WELLKNOWN_INT64VALUE,
-  UPB_WELLKNOWN_UINT64VALUE,
-  UPB_WELLKNOWN_INT32VALUE,
-  UPB_WELLKNOWN_UINT32VALUE,
-  /* string wrappers */
-  UPB_WELLKNOWN_STRINGVALUE,
-  UPB_WELLKNOWN_BYTESVALUE,
-  UPB_WELLKNOWN_BOOLVALUE,
-  UPB_WELLKNOWN_VALUE,
-  UPB_WELLKNOWN_LISTVALUE,
-  UPB_WELLKNOWN_STRUCT
-} upb_wellknowntype_t;
-
-/* upb_fielddef ***************************************************************/
-
-/* Maximum field number allowed for FieldDefs.  This is an inherent limit of the
- * protobuf wire format. */
-#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1)
-
-const char *upb_fielddef_fullname(const upb_fielddef *f);
-upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f);
-upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f);
-upb_label_t upb_fielddef_label(const upb_fielddef *f);
-uint32_t upb_fielddef_number(const upb_fielddef *f);
-const char *upb_fielddef_name(const upb_fielddef *f);
-const char *upb_fielddef_jsonname(const upb_fielddef *f);
-bool upb_fielddef_isextension(const upb_fielddef *f);
-bool upb_fielddef_lazy(const upb_fielddef *f);
-bool upb_fielddef_packed(const upb_fielddef *f);
-const upb_filedef *upb_fielddef_file(const upb_fielddef *f);
-const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f);
-const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f);
-const upb_oneofdef *upb_fielddef_realcontainingoneof(const upb_fielddef *f);
-uint32_t upb_fielddef_index(const upb_fielddef *f);
-bool upb_fielddef_issubmsg(const upb_fielddef *f);
-bool upb_fielddef_isstring(const upb_fielddef *f);
-bool upb_fielddef_isseq(const upb_fielddef *f);
-bool upb_fielddef_isprimitive(const upb_fielddef *f);
-bool upb_fielddef_ismap(const upb_fielddef *f);
-int64_t upb_fielddef_defaultint64(const upb_fielddef *f);
-int32_t upb_fielddef_defaultint32(const upb_fielddef *f);
-uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f);
-uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f);
-bool upb_fielddef_defaultbool(const upb_fielddef *f);
-float upb_fielddef_defaultfloat(const upb_fielddef *f);
-double upb_fielddef_defaultdouble(const upb_fielddef *f);
-const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len);
-bool upb_fielddef_hassubdef(const upb_fielddef *f);
-bool upb_fielddef_haspresence(const upb_fielddef *f);
-const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f);
-const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f);
-const upb_msglayout_field *upb_fielddef_layout(const upb_fielddef *f);
-
-/* Internal only. */
-uint32_t upb_fielddef_selectorbase(const upb_fielddef *f);
-
-/* upb_oneofdef ***************************************************************/
-
-typedef upb_inttable_iter upb_oneof_iter;
-
-const char *upb_oneofdef_name(const upb_oneofdef *o);
-const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o);
-int upb_oneofdef_numfields(const upb_oneofdef *o);
-uint32_t upb_oneofdef_index(const upb_oneofdef *o);
-bool upb_oneofdef_issynthetic(const upb_oneofdef *o);
-
-/* Oneof lookups:
- * - ntof:  look up a field by name.
- * - ntofz: look up a field by name (as a null-terminated string).
- * - itof:  look up a field by number. */
-const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
-                                      const char *name, size_t length);
-UPB_INLINE const upb_fielddef *upb_oneofdef_ntofz(const upb_oneofdef *o,
-                                                  const char *name) {
-  return upb_oneofdef_ntof(o, name, strlen(name));
-}
-const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num);
-
-/*  upb_oneof_iter i;
- *  for(upb_oneof_begin(&i, e); !upb_oneof_done(&i); upb_oneof_next(&i)) {
- *    // ...
- *  }
- */
-void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o);
-void upb_oneof_next(upb_oneof_iter *iter);
-bool upb_oneof_done(upb_oneof_iter *iter);
-upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter);
-void upb_oneof_iter_setdone(upb_oneof_iter *iter);
-bool upb_oneof_iter_isequal(const upb_oneof_iter *iter1,
-                            const upb_oneof_iter *iter2);
-
-/* upb_msgdef *****************************************************************/
-
-typedef upb_inttable_iter upb_msg_field_iter;
-typedef upb_strtable_iter upb_msg_oneof_iter;
-
-/* Well-known field tag numbers for map-entry messages. */
-#define UPB_MAPENTRY_KEY   1
-#define UPB_MAPENTRY_VALUE 2
-
-/* Well-known field tag numbers for Any messages. */
-#define UPB_ANY_TYPE 1
-#define UPB_ANY_VALUE 2
-
-/* Well-known field tag numbers for timestamp messages. */
-#define UPB_DURATION_SECONDS 1
-#define UPB_DURATION_NANOS 2
-
-/* Well-known field tag numbers for duration messages. */
-#define UPB_TIMESTAMP_SECONDS 1
-#define UPB_TIMESTAMP_NANOS 2
-
-const char *upb_msgdef_fullname(const upb_msgdef *m);
-const upb_filedef *upb_msgdef_file(const upb_msgdef *m);
-const char *upb_msgdef_name(const upb_msgdef *m);
-int upb_msgdef_numfields(const upb_msgdef *m);
-int upb_msgdef_numoneofs(const upb_msgdef *m);
-int upb_msgdef_numrealoneofs(const upb_msgdef *m);
-upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m);
-bool upb_msgdef_mapentry(const upb_msgdef *m);
-upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m);
-bool upb_msgdef_isnumberwrapper(const upb_msgdef *m);
-const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i);
-const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
-                                    size_t len);
-const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
-                                    size_t len);
-const upb_msglayout *upb_msgdef_layout(const upb_msgdef *m);
-const upb_fielddef *_upb_msgdef_field(const upb_msgdef *m, int i);
-
-UPB_INLINE const upb_oneofdef *upb_msgdef_ntooz(const upb_msgdef *m,
-                                               const char *name) {
-  return upb_msgdef_ntoo(m, name, strlen(name));
-}
-
-UPB_INLINE const upb_fielddef *upb_msgdef_ntofz(const upb_msgdef *m,
-                                                const char *name) {
-  return upb_msgdef_ntof(m, name, strlen(name));
-}
-
-/* Internal-only. */
-size_t upb_msgdef_selectorcount(const upb_msgdef *m);
-uint32_t upb_msgdef_submsgfieldcount(const upb_msgdef *m);
-
-/* Lookup of either field or oneof by name.  Returns whether either was found.
- * If the return is true, then the found def will be set, and the non-found
- * one set to NULL. */
-bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
-                           const upb_fielddef **f, const upb_oneofdef **o);
-
-UPB_INLINE bool upb_msgdef_lookupnamez(const upb_msgdef *m, const char *name,
-                                       const upb_fielddef **f,
-                                       const upb_oneofdef **o) {
-  return upb_msgdef_lookupname(m, name, strlen(name), f, o);
-}
-
-/* Returns a field by either JSON name or regular proto name. */
-const upb_fielddef *upb_msgdef_lookupjsonname(const upb_msgdef *m,
-                                              const char *name, size_t len);
-
-/* Iteration over fields and oneofs.  For example:
- *
- * upb_msg_field_iter i;
- * for(upb_msg_field_begin(&i, m);
- *     !upb_msg_field_done(&i);
- *     upb_msg_field_next(&i)) {
- *   upb_fielddef *f = upb_msg_iter_field(&i);
- *   // ...
- * }
- *
- * For C we don't have separate iterators for const and non-const.
- * It is the caller's responsibility to cast the upb_fielddef* to
- * const if the upb_msgdef* is const. */
-void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m);
-void upb_msg_field_next(upb_msg_field_iter *iter);
-bool upb_msg_field_done(const upb_msg_field_iter *iter);
-upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter);
-void upb_msg_field_iter_setdone(upb_msg_field_iter *iter);
-bool upb_msg_field_iter_isequal(const upb_msg_field_iter * iter1,
-                                const upb_msg_field_iter * iter2);
-
-/* Similar to above, we also support iterating through the oneofs in a
- * msgdef. */
-void upb_msg_oneof_begin(upb_msg_oneof_iter * iter, const upb_msgdef *m);
-void upb_msg_oneof_next(upb_msg_oneof_iter * iter);
-bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter);
-const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter);
-void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter * iter);
-bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1,
-                                const upb_msg_oneof_iter *iter2);
-
-/* upb_enumdef ****************************************************************/
-
-typedef upb_strtable_iter upb_enum_iter;
-
-const char *upb_enumdef_fullname(const upb_enumdef *e);
-const char *upb_enumdef_name(const upb_enumdef *e);
-const upb_filedef *upb_enumdef_file(const upb_enumdef *e);
-int32_t upb_enumdef_default(const upb_enumdef *e);
-int upb_enumdef_numvals(const upb_enumdef *e);
-
-/* Enum lookups:
- * - ntoi:  look up a name with specified length.
- * - ntoiz: look up a name provided as a null-terminated string.
- * - iton:  look up an integer, returning the name as a null-terminated
- *          string. */
-bool upb_enumdef_ntoi(const upb_enumdef *e, const char *name, size_t len,
-                      int32_t *num);
-UPB_INLINE bool upb_enumdef_ntoiz(const upb_enumdef *e,
-                                  const char *name, int32_t *num) {
-  return upb_enumdef_ntoi(e, name, strlen(name), num);
-}
-const char *upb_enumdef_iton(const upb_enumdef *e, int32_t num);
-
-/*  upb_enum_iter i;
- *  for(upb_enum_begin(&i, e); !upb_enum_done(&i); upb_enum_next(&i)) {
- *    // ...
- *  }
- */
-void upb_enum_begin(upb_enum_iter *iter, const upb_enumdef *e);
-void upb_enum_next(upb_enum_iter *iter);
-bool upb_enum_done(upb_enum_iter *iter);
-const char *upb_enum_iter_name(upb_enum_iter *iter);
-int32_t upb_enum_iter_number(upb_enum_iter *iter);
-
-/* upb_filedef ****************************************************************/
-
-const char *upb_filedef_name(const upb_filedef *f);
-const char *upb_filedef_package(const upb_filedef *f);
-const char *upb_filedef_phpprefix(const upb_filedef *f);
-const char *upb_filedef_phpnamespace(const upb_filedef *f);
-upb_syntax_t upb_filedef_syntax(const upb_filedef *f);
-int upb_filedef_depcount(const upb_filedef *f);
-int upb_filedef_msgcount(const upb_filedef *f);
-int upb_filedef_enumcount(const upb_filedef *f);
-const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i);
-const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i);
-const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i);
-
-/* upb_symtab *****************************************************************/
-
-upb_symtab *upb_symtab_new(void);
-void upb_symtab_free(upb_symtab* s);
-const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym);
-const upb_msgdef *upb_symtab_lookupmsg2(
-    const upb_symtab *s, const char *sym, size_t len);
-const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym);
-const upb_filedef *upb_symtab_lookupfile(const upb_symtab *s, const char *name);
-int upb_symtab_filecount(const upb_symtab *s);
-const upb_filedef *upb_symtab_addfile(
-    upb_symtab *s, const google_protobuf_FileDescriptorProto *file,
-    upb_status *status);
-
-/* For generated code only: loads a generated descriptor. */
-typedef struct upb_def_init {
-  struct upb_def_init **deps;     /* Dependencies of this file. */
-  const upb_msglayout **layouts;  /* Pre-order layouts of all messages. */
-  const char *filename;
-  upb_strview descriptor;         /* Serialized descriptor. */
-} upb_def_init;
-
-bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init);
-
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif  /* __cplusplus */
-
-#endif /* UPB_DEF_H_ */
-
-#ifndef UPB_REFLECTION_H_
-#define UPB_REFLECTION_H_
-
-
-
-typedef union {
-  bool bool_val;
-  float float_val;
-  double double_val;
-  int32_t int32_val;
-  int64_t int64_val;
-  uint32_t uint32_val;
-  uint64_t uint64_val;
-  const upb_map* map_val;
-  const upb_msg* msg_val;
-  const upb_array* array_val;
-  upb_strview str_val;
-} upb_msgval;
-
-typedef union {
-  upb_map* map;
-  upb_msg* msg;
-  upb_array* array;
-} upb_mutmsgval;
-
-/** upb_msg *******************************************************************/
-
-/* Creates a new message of the given type in the given arena. */
-upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a);
-
-/* Returns the value associated with this field. */
-upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f);
-
-/* Returns a mutable pointer to a map, array, or submessage value.  If the given
- * arena is non-NULL this will construct a new object if it was not previously
- * present.  May not be called for primitive fields. */
-upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f, upb_arena *a);
-
-/* May only be called for fields where upb_fielddef_haspresence(f) == true. */
-bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f);
-
-/* Returns whether any field is set in the oneof. */
-bool upb_msg_hasoneof(const upb_msg *msg, const upb_oneofdef *o);
-
-/* Sets the given field to the given value.  For a msg/array/map/string, the
- * value must be in the same arena.  */
-void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val,
-                 upb_arena *a);
-
-/* Clears any field presence and sets the value back to its default. */
-void upb_msg_clearfield(upb_msg *msg, const upb_fielddef *f);
-
-/* Iterate over present fields.
- *
- * size_t iter = UPB_MSG_BEGIN;
- * const upb_fielddef *f;
- * upb_msgval val;
- * while (upb_msg_next(msg, m, ext_pool, &f, &val, &iter)) {
- *   process_field(f, val);
- * }
- *
- * If ext_pool is NULL, no extensions will be returned.  If the given symtab
- * returns extensions that don't match what is in this message, those extensions
- * will be skipped.
- */
-
-#define UPB_MSG_BEGIN -1
-bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m,
-                  const upb_symtab *ext_pool, const upb_fielddef **f,
-                  upb_msgval *val, size_t *iter);
-
-/* Adds unknown data (serialized protobuf data) to the given message.  The data
- * is copied into the message instance. */
-void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
-                        upb_arena *arena);
-
-/* Returns a reference to the message's unknown data. */
-const char *upb_msg_getunknown(const upb_msg *msg, size_t *len);
-
-/** upb_array *****************************************************************/
-
-/* Creates a new array on the given arena that holds elements of this type. */
-upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type);
-
-/* Returns the size of the array. */
-size_t upb_array_size(const upb_array *arr);
-
-/* Returns the given element, which must be within the array's current size. */
-upb_msgval upb_array_get(const upb_array *arr, size_t i);
-
-/* Sets the given element, which must be within the array's current size. */
-void upb_array_set(upb_array *arr, size_t i, upb_msgval val);
-
-/* Appends an element to the array.  Returns false on allocation failure. */
-bool upb_array_append(upb_array *array, upb_msgval val, upb_arena *arena);
-
-/* Changes the size of a vector.  New elements are initialized to empty/0.
- * Returns false on allocation failure. */
-bool upb_array_resize(upb_array *array, size_t size, upb_arena *arena);
-
-/** upb_map *******************************************************************/
-
-/* Creates a new map on the given arena with the given key/value size. */
-upb_map *upb_map_new(upb_arena *a, upb_fieldtype_t key_type,
-                     upb_fieldtype_t value_type);
-
-/* Returns the number of entries in the map. */
-size_t upb_map_size(const upb_map *map);
-
-/* Stores a value for the given key into |*val| (or the zero value if the key is
- * not present).  Returns whether the key was present.  The |val| pointer may be
- * NULL, in which case the function tests whether the given key is present.  */
-bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val);
-
-/* Removes all entries in the map. */
-void upb_map_clear(upb_map *map);
-
-/* Sets the given key to the given value.  Returns true if this was a new key in
- * the map, or false if an existing key was replaced. */
-bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val,
-                 upb_arena *arena);
-
-/* Deletes this key from the table.  Returns true if the key was present. */
-bool upb_map_delete(upb_map *map, upb_msgval key);
-
-/* Map iteration:
- *
- * size_t iter = UPB_MAP_BEGIN;
- * while (upb_mapiter_next(map, &iter)) {
- *   upb_msgval key = upb_mapiter_key(map, iter);
- *   upb_msgval val = upb_mapiter_value(map, iter);
- *
- *   // If mutating is desired.
- *   upb_mapiter_setvalue(map, iter, value2);
- * }
- */
-
-/* Advances to the next entry.  Returns false if no more entries are present. */
-bool upb_mapiter_next(const upb_map *map, size_t *iter);
-
-/* Returns the key and value for this entry of the map. */
-upb_msgval upb_mapiter_key(const upb_map *map, size_t iter);
-upb_msgval upb_mapiter_value(const upb_map *map, size_t iter);
-
-/* Sets the value for this entry.  The iterator must not be done, and the
- * iterator must not have been initialized const. */
-void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value);
-
-
-#endif /* UPB_REFLECTION_H_ */
-/*
-** upb::Handlers (upb_handlers)
-**
-** A upb_handlers is like a virtual table for a upb_msgdef.  Each field of the
-** message can have associated functions that will be called when we are
-** parsing or visiting a stream of data.  This is similar to how handlers work
-** in SAX (the Simple API for XML).
-**
-** The handlers have no idea where the data is coming from, so a single set of
-** handlers could be used with two completely different data sources (for
-** example, a parser and a visitor over in-memory objects).  This decoupling is
-** the most important feature of upb, because it allows parsers and serializers
-** to be highly reusable.
-**
-** This is a mixed C/C++ interface that offers a full API to both languages.
-** See the top-level README for more information.
-*/
-
-#ifndef UPB_HANDLERS_H
-#define UPB_HANDLERS_H
-
-
-
-#ifdef __cplusplus
-namespace upb {
-class HandlersPtr;
-class HandlerCache;
-template <class T> class Handler;
-template <class T> struct CanonicalType;
-}  /* namespace upb */
-#endif
-
-
-/* The maximum depth that the handler graph can have.  This is a resource limit
- * for the C stack since we sometimes need to recursively traverse the graph.
- * Cycles are ok; the traversal will stop when it detects a cycle, but we must
- * hit the cycle before the maximum depth is reached.
- *
- * If having a single static limit is too inflexible, we can add another variant
- * of Handlers::Freeze that allows specifying this as a parameter. */
-#define UPB_MAX_HANDLER_DEPTH 64
-
-/* All the different types of handlers that can be registered.
- * Only needed for the advanced functions in upb::Handlers. */
-typedef enum {
-  UPB_HANDLER_INT32,
-  UPB_HANDLER_INT64,
-  UPB_HANDLER_UINT32,
-  UPB_HANDLER_UINT64,
-  UPB_HANDLER_FLOAT,
-  UPB_HANDLER_DOUBLE,
-  UPB_HANDLER_BOOL,
-  UPB_HANDLER_STARTSTR,
-  UPB_HANDLER_STRING,
-  UPB_HANDLER_ENDSTR,
-  UPB_HANDLER_STARTSUBMSG,
-  UPB_HANDLER_ENDSUBMSG,
-  UPB_HANDLER_STARTSEQ,
-  UPB_HANDLER_ENDSEQ
-} upb_handlertype_t;
-
-#define UPB_HANDLER_MAX (UPB_HANDLER_ENDSEQ+1)
-
-#define UPB_BREAK NULL
-
-/* A convenient definition for when no closure is needed. */
-extern char _upb_noclosure;
-#define UPB_NO_CLOSURE &_upb_noclosure
-
-/* A selector refers to a specific field handler in the Handlers object
- * (for example: the STARTSUBMSG handler for field "field15"). */
-typedef int32_t upb_selector_t;
-
-/* Static selectors for upb::Handlers. */
-#define UPB_STARTMSG_SELECTOR 0
-#define UPB_ENDMSG_SELECTOR 1
-#define UPB_UNKNOWN_SELECTOR 2
-#define UPB_STATIC_SELECTOR_COUNT 3  /* Warning: also in upb/def.c. */
-
-/* Static selectors for upb::BytesHandler. */
-#define UPB_STARTSTR_SELECTOR 0
-#define UPB_STRING_SELECTOR 1
-#define UPB_ENDSTR_SELECTOR 2
-
-#ifdef __cplusplus
-template<class T> const void *UniquePtrForType() {
-  static const char ch = 0;
-  return &ch;
-}
-#endif
-
-/* upb_handlers ************************************************************/
-
-/* Handler attributes, to be registered with the handler itself. */
-typedef struct {
-  const void *handler_data;
-  const void *closure_type;
-  const void *return_closure_type;
-  bool alwaysok;
-} upb_handlerattr;
-
-#define UPB_HANDLERATTR_INIT {NULL, NULL, NULL, false}
-
-/* Bufhandle, data passed along with a buffer to indicate its provenance. */
-typedef struct {
-  /* The beginning of the buffer.  This may be different than the pointer
-   * passed to a StringBuf handler because the handler may receive data
-   * that is from the middle or end of a larger buffer. */
-  const char *buf;
-
-  /* The offset within the attached object where this buffer begins.  Only
-   * meaningful if there is an attached object. */
-  size_t objofs;
-
-  /* The attached object (if any) and a pointer representing its type. */
-  const void *obj;
-  const void *objtype;
-
-#ifdef __cplusplus
-  template <class T>
-  void SetAttachedObject(const T* _obj) {
-    obj = _obj;
-    objtype = UniquePtrForType<T>();
-  }
-
-  template <class T>
-  const T *GetAttachedObject() const {
-    return objtype == UniquePtrForType<T>() ? static_cast<const T *>(obj)
-                                            : NULL;
-  }
-#endif
-} upb_bufhandle;
-
-#define UPB_BUFHANDLE_INIT {NULL, 0, NULL, NULL}
-
-/* Handler function typedefs. */
-typedef void upb_handlerfree(void *d);
-typedef bool upb_unknown_handlerfunc(void *c, const void *hd, const char *buf,
-                                     size_t n);
-typedef bool upb_startmsg_handlerfunc(void *c, const void*);
-typedef bool upb_endmsg_handlerfunc(void *c, const void *, upb_status *status);
-typedef void* upb_startfield_handlerfunc(void *c, const void *hd);
-typedef bool upb_endfield_handlerfunc(void *c, const void *hd);
-typedef bool upb_int32_handlerfunc(void *c, const void *hd, int32_t val);
-typedef bool upb_int64_handlerfunc(void *c, const void *hd, int64_t val);
-typedef bool upb_uint32_handlerfunc(void *c, const void *hd, uint32_t val);
-typedef bool upb_uint64_handlerfunc(void *c, const void *hd, uint64_t val);
-typedef bool upb_float_handlerfunc(void *c, const void *hd, float val);
-typedef bool upb_double_handlerfunc(void *c, const void *hd, double val);
-typedef bool upb_bool_handlerfunc(void *c, const void *hd, bool val);
-typedef void *upb_startstr_handlerfunc(void *c, const void *hd,
-                                       size_t size_hint);
-typedef size_t upb_string_handlerfunc(void *c, const void *hd, const char *buf,
-                                      size_t n, const upb_bufhandle* handle);
-
-struct upb_handlers;
-typedef struct upb_handlers upb_handlers;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Mutating accessors. */
-const upb_status *upb_handlers_status(upb_handlers *h);
-void upb_handlers_clearerr(upb_handlers *h);
-const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h);
-bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *hfree);
-bool upb_handlers_setunknown(upb_handlers *h, upb_unknown_handlerfunc *func,
-                             const upb_handlerattr *attr);
-bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func,
-                              const upb_handlerattr *attr);
-bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func,
-                            const upb_handlerattr *attr);
-bool upb_handlers_setint32(upb_handlers *h, const upb_fielddef *f,
-                           upb_int32_handlerfunc *func,
-                           const upb_handlerattr *attr);
-bool upb_handlers_setint64(upb_handlers *h, const upb_fielddef *f,
-                           upb_int64_handlerfunc *func,
-                           const upb_handlerattr *attr);
-bool upb_handlers_setuint32(upb_handlers *h, const upb_fielddef *f,
-                            upb_uint32_handlerfunc *func,
-                            const upb_handlerattr *attr);
-bool upb_handlers_setuint64(upb_handlers *h, const upb_fielddef *f,
-                            upb_uint64_handlerfunc *func,
-                            const upb_handlerattr *attr);
-bool upb_handlers_setfloat(upb_handlers *h, const upb_fielddef *f,
-                           upb_float_handlerfunc *func,
-                           const upb_handlerattr *attr);
-bool upb_handlers_setdouble(upb_handlers *h, const upb_fielddef *f,
-                            upb_double_handlerfunc *func,
-                            const upb_handlerattr *attr);
-bool upb_handlers_setbool(upb_handlers *h, const upb_fielddef *f,
-                          upb_bool_handlerfunc *func,
-                          const upb_handlerattr *attr);
-bool upb_handlers_setstartstr(upb_handlers *h, const upb_fielddef *f,
-                              upb_startstr_handlerfunc *func,
-                              const upb_handlerattr *attr);
-bool upb_handlers_setstring(upb_handlers *h, const upb_fielddef *f,
-                            upb_string_handlerfunc *func,
-                            const upb_handlerattr *attr);
-bool upb_handlers_setendstr(upb_handlers *h, const upb_fielddef *f,
-                            upb_endfield_handlerfunc *func,
-                            const upb_handlerattr *attr);
-bool upb_handlers_setstartseq(upb_handlers *h, const upb_fielddef *f,
-                              upb_startfield_handlerfunc *func,
-                              const upb_handlerattr *attr);
-bool upb_handlers_setstartsubmsg(upb_handlers *h, const upb_fielddef *f,
-                                 upb_startfield_handlerfunc *func,
-                                 const upb_handlerattr *attr);
-bool upb_handlers_setendsubmsg(upb_handlers *h, const upb_fielddef *f,
-                               upb_endfield_handlerfunc *func,
-                               const upb_handlerattr *attr);
-bool upb_handlers_setendseq(upb_handlers *h, const upb_fielddef *f,
-                            upb_endfield_handlerfunc *func,
-                            const upb_handlerattr *attr);
-
-/* Read-only accessors. */
-const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h,
-                                                const upb_fielddef *f);
-const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h,
-                                                    upb_selector_t sel);
-upb_func *upb_handlers_gethandler(const upb_handlers *h, upb_selector_t s,
-                                  const void **handler_data);
-bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t s,
-                          upb_handlerattr *attr);
-
-/* "Static" methods */
-upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f);
-bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
-                              upb_selector_t *s);
-UPB_INLINE upb_selector_t upb_handlers_getendselector(upb_selector_t start) {
-  return start + 1;
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-namespace upb {
-typedef upb_handlers Handlers;
-}
-
-/* Convenience macros for creating a Handler object that is wrapped with a
- * type-safe wrapper function that converts the "void*" parameters/returns
- * of the underlying C API into nice C++ function.
- *
- * Sample usage:
- *   void OnValue1(MyClosure* c, const MyHandlerData* d, int32_t val) {
- *     // do stuff ...
- *   }
- *
- *   // Handler that doesn't need any data bound to it.
- *   void OnValue2(MyClosure* c, int32_t val) {
- *     // do stuff ...
- *   }
- *
- *   // Handler that returns bool so it can return failure if necessary.
- *   bool OnValue3(MyClosure* c, int32_t val) {
- *     // do stuff ...
- *     return ok;
- *   }
- *
- *   // Member function handler.
- *   class MyClosure {
- *    public:
- *     void OnValue(int32_t val) {
- *       // do stuff ...
- *     }
- *   };
- *
- *   // Takes ownership of the MyHandlerData.
- *   handlers->SetInt32Handler(f1, UpbBind(OnValue1, new MyHandlerData(...)));
- *   handlers->SetInt32Handler(f2, UpbMakeHandler(OnValue2));
- *   handlers->SetInt32Handler(f1, UpbMakeHandler(OnValue3));
- *   handlers->SetInt32Handler(f2, UpbMakeHandler(&MyClosure::OnValue));
- */
-
-/* In C++11, the "template" disambiguator can appear even outside templates,
- * so all calls can safely use this pair of macros. */
-
-#define UpbMakeHandler(f) upb::MatchFunc(f).template GetFunc<f>()
-
-/* We have to be careful to only evaluate "d" once. */
-#define UpbBind(f, d) upb::MatchFunc(f).template GetFunc<f>((d))
-
-/* Handler: a struct that contains the (handler, data, deleter) tuple that is
- * used to register all handlers.  Users can Make() these directly but it's
- * more convenient to use the UpbMakeHandler/UpbBind macros above. */
-template <class T> class upb::Handler {
- public:
-  /* The underlying, handler function signature that upb uses internally. */
-  typedef T FuncPtr;
-
-  /* Intentionally implicit. */
-  template <class F> Handler(F func);
-  ~Handler() { UPB_ASSERT(registered_); }
-
-  void AddCleanup(upb_handlers* h) const;
-  FuncPtr handler() const { return handler_; }
-  const upb_handlerattr& attr() const { return attr_; }
-
- private:
-  Handler(const Handler&) = delete;
-  Handler& operator=(const Handler&) = delete;
-
-  FuncPtr handler_;
-  mutable upb_handlerattr attr_;
-  mutable bool registered_;
-  void *cleanup_data_;
-  upb_handlerfree *cleanup_func_;
-};
-
-/* A upb::Handlers object represents the set of handlers associated with a
- * message in the graph of messages.  You can think of it as a big virtual
- * table with functions corresponding to all the events that can fire while
- * parsing or visiting a message of a specific type.
- *
- * Any handlers that are not set behave as if they had successfully consumed
- * the value.  Any unset Start* handlers will propagate their closure to the
- * inner frame.
- *
- * The easiest way to create the *Handler objects needed by the Set* methods is
- * with the UpbBind() and UpbMakeHandler() macros; see below. */
-class upb::HandlersPtr {
- public:
-  HandlersPtr(upb_handlers* ptr) : ptr_(ptr) {}
-
-  upb_handlers* ptr() const { return ptr_; }
-
-  typedef upb_selector_t Selector;
-  typedef upb_handlertype_t Type;
-
-  typedef Handler<void *(*)(void *, const void *)> StartFieldHandler;
-  typedef Handler<bool (*)(void *, const void *)> EndFieldHandler;
-  typedef Handler<bool (*)(void *, const void *)> StartMessageHandler;
-  typedef Handler<bool (*)(void *, const void *, upb_status *)>
-      EndMessageHandler;
-  typedef Handler<void *(*)(void *, const void *, size_t)> StartStringHandler;
-  typedef Handler<size_t (*)(void *, const void *, const char *, size_t,
-                             const upb_bufhandle *)>
-      StringHandler;
-
-  template <class T> struct ValueHandler {
-    typedef Handler<bool(*)(void *, const void *, T)> H;
-  };
-
-  typedef ValueHandler<int32_t>::H     Int32Handler;
-  typedef ValueHandler<int64_t>::H     Int64Handler;
-  typedef ValueHandler<uint32_t>::H    UInt32Handler;
-  typedef ValueHandler<uint64_t>::H    UInt64Handler;
-  typedef ValueHandler<float>::H       FloatHandler;
-  typedef ValueHandler<double>::H      DoubleHandler;
-  typedef ValueHandler<bool>::H        BoolHandler;
-
-  /* Any function pointer can be converted to this and converted back to its
-   * correct type. */
-  typedef void GenericFunction();
-
-  typedef void HandlersCallback(const void *closure, upb_handlers *h);
-
-  /* Returns the msgdef associated with this handlers object. */
-  MessageDefPtr message_def() const {
-    return MessageDefPtr(upb_handlers_msgdef(ptr()));
-  }
-
-  /* Adds the given pointer and function to the list of cleanup functions that
-   * will be run when these handlers are freed.  If this pointer has previously
-   * been registered, the function returns false and does nothing. */
-  bool AddCleanup(void *ptr, upb_handlerfree *cleanup) {
-    return upb_handlers_addcleanup(ptr_, ptr, cleanup);
-  }
-
-  /* Sets the startmsg handler for the message, which is defined as follows:
-   *
-   *   bool startmsg(MyType* closure) {
-   *     // Called when the message begins.  Returns true if processing should
-   *     // continue.
-   *     return true;
-   *   }
-   */
-  bool SetStartMessageHandler(const StartMessageHandler &h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setstartmsg(ptr(), h.handler(), &h.attr());
-  }
-
-  /* Sets the endmsg handler for the message, which is defined as follows:
-   *
-   *   bool endmsg(MyType* closure, upb_status *status) {
-   *     // Called when processing of this message ends, whether in success or
-   *     // failure.  "status" indicates the final status of processing, and
-   *     // can also be modified in-place to update the final status.
-   *   }
-   */
-  bool SetEndMessageHandler(const EndMessageHandler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setendmsg(ptr(), h.handler(), &h.attr());
-  }
-
-  /* Sets the value handler for the given field, which is defined as follows
-   * (this is for an int32 field; other field types will pass their native
-   * C/C++ type for "val"):
-   *
-   *   bool OnValue(MyClosure* c, const MyHandlerData* d, int32_t val) {
-   *     // Called when the field's value is encountered.  "d" contains
-   *     // whatever data was bound to this field when it was registered.
-   *     // Returns true if processing should continue.
-   *     return true;
-   *   }
-   *
-   *   handers->SetInt32Handler(f, UpbBind(OnValue, new MyHandlerData(...)));
-   *
-   * The value type must exactly match f->type().
-   * For example, a handler that takes an int32_t parameter may only be used for
-   * fields of type UPB_TYPE_INT32 and UPB_TYPE_ENUM.
-   *
-   * Returns false if the handler failed to register; in this case the cleanup
-   * handler (if any) will be called immediately.
-   */
-  bool SetInt32Handler(FieldDefPtr f, const Int32Handler &h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setint32(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetInt64Handler (FieldDefPtr f,  const Int64Handler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setint64(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetUInt32Handler(FieldDefPtr f, const UInt32Handler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setuint32(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetUInt64Handler(FieldDefPtr f, const UInt64Handler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setuint64(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetFloatHandler (FieldDefPtr f,  const FloatHandler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setfloat(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetDoubleHandler(FieldDefPtr f, const DoubleHandler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setdouble(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetBoolHandler(FieldDefPtr f, const BoolHandler &h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setbool(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  /* Like the previous, but templated on the type on the value (ie. int32).
-   * This is mostly useful to call from other templates.  To call this you must
-   * specify the template parameter explicitly, ie:
-   *   h->SetValueHandler<T>(f, UpbBind(MyHandler<T>, MyData)); */
-  template <class T>
-  bool SetValueHandler(
-      FieldDefPtr f,
-      const typename ValueHandler<typename CanonicalType<T>::Type>::H &handler);
-
-  /* Sets handlers for a string field, which are defined as follows:
-   *
-   *   MySubClosure* startstr(MyClosure* c, const MyHandlerData* d,
-   *                          size_t size_hint) {
-   *     // Called when a string value begins.  The return value indicates the
-   *     // closure for the string.  "size_hint" indicates the size of the
-   *     // string if it is known, however if the string is length-delimited
-   *     // and the end-of-string is not available size_hint will be zero.
-   *     // This case is indistinguishable from the case where the size is
-   *     // known to be zero.
-   *     //
-   *     // TODO(haberman): is it important to distinguish these cases?
-   *     // If we had ssize_t as a type we could make -1 "unknown", but
-   *     // ssize_t is POSIX (not ANSI) and therefore less portable.
-   *     // In practice I suspect it won't be important to distinguish.
-   *     return closure;
-   *   }
-   *
-   *   size_t str(MyClosure* closure, const MyHandlerData* d,
-   *              const char *str, size_t len) {
-   *     // Called for each buffer of string data; the multiple physical buffers
-   *     // are all part of the same logical string.  The return value indicates
-   *     // how many bytes were consumed.  If this number is less than "len",
-   *     // this will also indicate that processing should be halted for now,
-   *     // like returning false or UPB_BREAK from any other callback.  If
-   *     // number is greater than "len", the excess bytes will be skipped over
-   *     // and not passed to the callback.
-   *     return len;
-   *   }
-   *
-   *   bool endstr(MyClosure* c, const MyHandlerData* d) {
-   *     // Called when a string value ends.  Return value indicates whether
-   *     // processing should continue.
-   *     return true;
-   *   }
-   */
-  bool SetStartStringHandler(FieldDefPtr f, const StartStringHandler &h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setstartstr(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetStringHandler(FieldDefPtr f, const StringHandler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setstring(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  bool SetEndStringHandler(FieldDefPtr f, const EndFieldHandler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setendstr(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  /* Sets the startseq handler, which is defined as follows:
-   *
-   *   MySubClosure *startseq(MyClosure* c, const MyHandlerData* d) {
-   *     // Called when a sequence (repeated field) begins.  The returned
-   *     // pointer indicates the closure for the sequence (or UPB_BREAK
-   *     // to interrupt processing).
-   *     return closure;
-   *   }
-   *
-   *   h->SetStartSequenceHandler(f, UpbBind(startseq, new MyHandlerData(...)));
-   *
-   * Returns "false" if "f" does not belong to this message or is not a
-   * repeated field.
-   */
-  bool SetStartSequenceHandler(FieldDefPtr f, const StartFieldHandler &h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setstartseq(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  /* Sets the startsubmsg handler for the given field, which is defined as
-   * follows:
-   *
-   *   MySubClosure* startsubmsg(MyClosure* c, const MyHandlerData* d) {
-   *     // Called when a submessage begins.  The returned pointer indicates the
-   *     // closure for the sequence (or UPB_BREAK to interrupt processing).
-   *     return closure;
-   *   }
-   *
-   *   h->SetStartSubMessageHandler(f, UpbBind(startsubmsg,
-   *                                           new MyHandlerData(...)));
-   *
-   * Returns "false" if "f" does not belong to this message or is not a
-   * submessage/group field.
-   */
-  bool SetStartSubMessageHandler(FieldDefPtr f, const StartFieldHandler& h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setstartsubmsg(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  /* Sets the endsubmsg handler for the given field, which is defined as
-   * follows:
-   *
-   *   bool endsubmsg(MyClosure* c, const MyHandlerData* d) {
-   *     // Called when a submessage ends.  Returns true to continue processing.
-   *     return true;
-   *   }
-   *
-   * Returns "false" if "f" does not belong to this message or is not a
-   * submessage/group field.
-   */
-  bool SetEndSubMessageHandler(FieldDefPtr f, const EndFieldHandler &h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setendsubmsg(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
-  /* Starts the endsubseq handler for the given field, which is defined as
-   * follows:
-   *
-   *   bool endseq(MyClosure* c, const MyHandlerData* d) {
-   *     // Called when a sequence ends.  Returns true continue processing.
-   *     return true;
-   *   }
-   *
-   * Returns "false" if "f" does not belong to this message or is not a
-   * repeated field.
-   */
-  bool SetEndSequenceHandler(FieldDefPtr f, const EndFieldHandler &h) {
-    h.AddCleanup(ptr());
-    return upb_handlers_setendseq(ptr(), f.ptr(), h.handler(), &h.attr());
-  }
-
- private:
-  upb_handlers* ptr_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_handlercache ***********************************************************/
-
-/* A upb_handlercache lazily builds and caches upb_handlers.  You pass it a
- * function (with optional closure) that can build handlers for a given
- * message on-demand, and the cache maintains a map of msgdef->handlers. */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct upb_handlercache;
-typedef struct upb_handlercache upb_handlercache;
-
-typedef void upb_handlers_callback(const void *closure, upb_handlers *h);
-
-upb_handlercache *upb_handlercache_new(upb_handlers_callback *callback,
-                                       const void *closure);
-void upb_handlercache_free(upb_handlercache *cache);
-const upb_handlers *upb_handlercache_get(upb_handlercache *cache,
-                                         const upb_msgdef *md);
-bool upb_handlercache_addcleanup(upb_handlercache *h, void *p,
-                                 upb_handlerfree *hfree);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-class upb::HandlerCache {
- public:
-  HandlerCache(upb_handlers_callback *callback, const void *closure)
-      : ptr_(upb_handlercache_new(callback, closure), upb_handlercache_free) {}
-  HandlerCache(HandlerCache&&) = default;
-  HandlerCache& operator=(HandlerCache&&) = default;
-  HandlerCache(upb_handlercache* c) : ptr_(c, upb_handlercache_free) {}
-
-  upb_handlercache* ptr() { return ptr_.get(); }
-
-  const upb_handlers *Get(MessageDefPtr md) {
-    return upb_handlercache_get(ptr_.get(), md.ptr());
-  }
-
- private:
-  std::unique_ptr<upb_handlercache, decltype(&upb_handlercache_free)> ptr_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_byteshandler ***********************************************************/
-
-typedef struct {
-  upb_func *func;
-
-  /* It is wasteful to include the entire attributes here:
-   *
-   * * Some of the information is redundant (like storing the closure type
-   *   separately for each handler that must match).
-   * * Some of the info is only needed prior to freeze() (like closure types).
-   * * alignment padding wastes a lot of space for alwaysok_.
-   *
-   * If/when the size and locality of handlers is an issue, we can optimize this
-   * not to store the entire attr like this.  We do not expose the table's
-   * layout to allow this optimization in the future. */
-  upb_handlerattr attr;
-} upb_handlers_tabent;
-
-#define UPB_TABENT_INIT {NULL, UPB_HANDLERATTR_INIT}
-
-typedef struct {
-  upb_handlers_tabent table[3];
-} upb_byteshandler;
-
-#define UPB_BYTESHANDLER_INIT                             \
-  {                                                       \
-    { UPB_TABENT_INIT, UPB_TABENT_INIT, UPB_TABENT_INIT } \
-  }
-
-UPB_INLINE void upb_byteshandler_init(upb_byteshandler *handler) {
-  upb_byteshandler init = UPB_BYTESHANDLER_INIT;
-  *handler = init;
-}
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Caller must ensure that "d" outlives the handlers. */
-bool upb_byteshandler_setstartstr(upb_byteshandler *h,
-                                  upb_startstr_handlerfunc *func, void *d);
-bool upb_byteshandler_setstring(upb_byteshandler *h,
-                                upb_string_handlerfunc *func, void *d);
-bool upb_byteshandler_setendstr(upb_byteshandler *h,
-                                upb_endfield_handlerfunc *func, void *d);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-namespace upb {
-typedef upb_byteshandler BytesHandler;
-}
-#endif
-
-/** Message handlers ******************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* These are the handlers used internally by upb_msgfactory_getmergehandlers().
- * They write scalar data to a known offset from the message pointer.
- *
- * These would be trivial for anyone to implement themselves, but it's better
- * to use these because some JITs will recognize and specialize these instead
- * of actually calling the function. */
-
-/* Sets a handler for the given primitive field that will write the data at the
- * given offset.  If hasbit > 0, also sets a hasbit at the given bit offset
- * (addressing each byte low to high). */
-bool upb_msg_setscalarhandler(upb_handlers *h,
-                              const upb_fielddef *f,
-                              size_t offset,
-                              int32_t hasbit);
-
-/* If the given handler is a msghandlers_primitive field, returns true and sets
- * *type, *offset and *hasbit.  Otherwise returns false. */
-bool upb_msg_getscalarhandlerdata(const upb_handlers *h,
-                                  upb_selector_t s,
-                                  upb_fieldtype_t *type,
-                                  size_t *offset,
-                                  int32_t *hasbit);
-
-
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-
-/*
-** Inline definitions for handlers.h, which are particularly long and a bit
-** tricky.
-*/
-
-#ifndef UPB_HANDLERS_INL_H_
-#define UPB_HANDLERS_INL_H_
-
-#include <limits.h>
-#include <stddef.h>
-
-
-#ifdef __cplusplus
-
-/* Type detection and typedefs for integer types.
- * For platforms where there are multiple 32-bit or 64-bit types, we need to be
- * able to enumerate them so we can properly create overloads for all variants.
- *
- * If any platform existed where there were three integer types with the same
- * size, this would have to become more complicated.  For example, short, int,
- * and long could all be 32-bits.  Even more diabolically, short, int, long,
- * and long long could all be 64 bits and still be standard-compliant.
- * However, few platforms are this strange, and it's unlikely that upb will be
- * used on the strangest ones. */
-
-/* Can't count on stdint.h limits like INT32_MAX, because in C++ these are
- * only defined when __STDC_LIMIT_MACROS are defined before the *first* include
- * of stdint.h.  We can't guarantee that someone else didn't include these first
- * without defining __STDC_LIMIT_MACROS. */
-#define UPB_INT32_MAX 0x7fffffffLL
-#define UPB_INT32_MIN (-UPB_INT32_MAX - 1)
-#define UPB_INT64_MAX 0x7fffffffffffffffLL
-#define UPB_INT64_MIN (-UPB_INT64_MAX - 1)
-
-#if INT_MAX == UPB_INT32_MAX && INT_MIN == UPB_INT32_MIN
-#define UPB_INT_IS_32BITS 1
-#endif
-
-#if LONG_MAX == UPB_INT32_MAX && LONG_MIN == UPB_INT32_MIN
-#define UPB_LONG_IS_32BITS 1
-#endif
-
-#if LONG_MAX == UPB_INT64_MAX && LONG_MIN == UPB_INT64_MIN
-#define UPB_LONG_IS_64BITS 1
-#endif
-
-#if LLONG_MAX == UPB_INT64_MAX && LLONG_MIN == UPB_INT64_MIN
-#define UPB_LLONG_IS_64BITS 1
-#endif
-
-/* We use macros instead of typedefs so we can undefine them later and avoid
- * leaking them outside this header file. */
-#if UPB_INT_IS_32BITS
-#define UPB_INT32_T int
-#define UPB_UINT32_T unsigned int
-
-#if UPB_LONG_IS_32BITS
-#define UPB_TWO_32BIT_TYPES 1
-#define UPB_INT32ALT_T long
-#define UPB_UINT32ALT_T unsigned long
-#endif  /* UPB_LONG_IS_32BITS */
-
-#elif UPB_LONG_IS_32BITS  /* && !UPB_INT_IS_32BITS */
-#define UPB_INT32_T long
-#define UPB_UINT32_T unsigned long
-#endif  /* UPB_INT_IS_32BITS */
-
-
-#if UPB_LONG_IS_64BITS
-#define UPB_INT64_T long
-#define UPB_UINT64_T unsigned long
-
-#if UPB_LLONG_IS_64BITS
-#define UPB_TWO_64BIT_TYPES 1
-#define UPB_INT64ALT_T long long
-#define UPB_UINT64ALT_T unsigned long long
-#endif  /* UPB_LLONG_IS_64BITS */
-
-#elif UPB_LLONG_IS_64BITS  /* && !UPB_LONG_IS_64BITS */
-#define UPB_INT64_T long long
-#define UPB_UINT64_T unsigned long long
-#endif  /* UPB_LONG_IS_64BITS */
-
-#undef UPB_INT32_MAX
-#undef UPB_INT32_MIN
-#undef UPB_INT64_MAX
-#undef UPB_INT64_MIN
-#undef UPB_INT_IS_32BITS
-#undef UPB_LONG_IS_32BITS
-#undef UPB_LONG_IS_64BITS
-#undef UPB_LLONG_IS_64BITS
-
-
-namespace upb {
-
-typedef void CleanupFunc(void *ptr);
-
-/* Template to remove "const" from "const T*" and just return "T*".
- *
- * We define a nonsense default because otherwise it will fail to instantiate as
- * a function parameter type even in cases where we don't expect any caller to
- * actually match the overload. */
-class CouldntRemoveConst {};
-template <class T> struct remove_constptr { typedef CouldntRemoveConst type; };
-template <class T> struct remove_constptr<const T *> { typedef T *type; };
-
-/* Template that we use below to remove a template specialization from
- * consideration if it matches a specific type. */
-template <class T, class U> struct disable_if_same { typedef void Type; };
-template <class T> struct disable_if_same<T, T> {};
-
-template <class T> void DeletePointer(void *p) { delete static_cast<T>(p); }
-
-template <class T1, class T2>
-struct FirstUnlessVoidOrBool {
-  typedef T1 value;
-};
-
-template <class T2>
-struct FirstUnlessVoidOrBool<void, T2> {
-  typedef T2 value;
-};
-
-template <class T2>
-struct FirstUnlessVoidOrBool<bool, T2> {
-  typedef T2 value;
-};
-
-template<class T, class U>
-struct is_same {
-  static bool value;
-};
-
-template<class T>
-struct is_same<T, T> {
-  static bool value;
-};
-
-template<class T, class U>
-bool is_same<T, U>::value = false;
-
-template<class T>
-bool is_same<T, T>::value = true;
-
-/* FuncInfo *******************************************************************/
-
-/* Info about the user's original, pre-wrapped function. */
-template <class C, class R = void>
-struct FuncInfo {
-  /* The type of the closure that the function takes (its first param). */
-  typedef C Closure;
-
-  /* The return type. */
-  typedef R Return;
-};
-
-/* Func ***********************************************************************/
-
-/* Func1, Func2, Func3: Template classes representing a function and its
- * signature.
- *
- * Since the function is a template parameter, calling the function can be
- * inlined at compile-time and does not require a function pointer at runtime.
- * These functions are not bound to a handler data so have no data or cleanup
- * handler. */
-struct UnboundFunc {
-  CleanupFunc *GetCleanup() { return nullptr; }
-  void *GetData() { return nullptr; }
-};
-
-template <class R, class P1, R F(P1), class I>
-struct Func1 : public UnboundFunc {
-  typedef R Return;
-  typedef I FuncInfo;
-  static R Call(P1 p1) { return F(p1); }
-};
-
-template <class R, class P1, class P2, R F(P1, P2), class I>
-struct Func2 : public UnboundFunc {
-  typedef R Return;
-  typedef I FuncInfo;
-  static R Call(P1 p1, P2 p2) { return F(p1, p2); }
-};
-
-template <class R, class P1, class P2, class P3, R F(P1, P2, P3), class I>
-struct Func3 : public UnboundFunc {
-  typedef R Return;
-  typedef I FuncInfo;
-  static R Call(P1 p1, P2 p2, P3 p3) { return F(p1, p2, p3); }
-};
-
-template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4),
-          class I>
-struct Func4 : public UnboundFunc {
-  typedef R Return;
-  typedef I FuncInfo;
-  static R Call(P1 p1, P2 p2, P3 p3, P4 p4) { return F(p1, p2, p3, p4); }
-};
-
-template <class R, class P1, class P2, class P3, class P4, class P5,
-          R F(P1, P2, P3, P4, P5), class I>
-struct Func5 : public UnboundFunc {
-  typedef R Return;
-  typedef I FuncInfo;
-  static R Call(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
-    return F(p1, p2, p3, p4, p5);
-  }
-};
-
-/* BoundFunc ******************************************************************/
-
-/* BoundFunc2, BoundFunc3: Like Func2/Func3 except also contains a value that
- * shall be bound to the function's second parameter.
- * 
- * Note that the second parameter is a const pointer, but our stored bound value
- * is non-const so we can free it when the handlers are destroyed. */
-template <class T>
-struct BoundFunc {
-  typedef typename remove_constptr<T>::type MutableP2;
-  explicit BoundFunc(MutableP2 data_) : data(data_) {}
-  CleanupFunc *GetCleanup() { return &DeletePointer<MutableP2>; }
-  MutableP2 GetData() { return data; }
-  MutableP2 data;
-};
-
-template <class R, class P1, class P2, R F(P1, P2), class I>
-struct BoundFunc2 : public BoundFunc<P2> {
-  typedef BoundFunc<P2> Base;
-  typedef I FuncInfo;
-  explicit BoundFunc2(typename Base::MutableP2 arg) : Base(arg) {}
-};
-
-template <class R, class P1, class P2, class P3, R F(P1, P2, P3), class I>
-struct BoundFunc3 : public BoundFunc<P2> {
-  typedef BoundFunc<P2> Base;
-  typedef I FuncInfo;
-  explicit BoundFunc3(typename Base::MutableP2 arg) : Base(arg) {}
-};
-
-template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4),
-          class I>
-struct BoundFunc4 : public BoundFunc<P2> {
-  typedef BoundFunc<P2> Base;
-  typedef I FuncInfo;
-  explicit BoundFunc4(typename Base::MutableP2 arg) : Base(arg) {}
-};
-
-template <class R, class P1, class P2, class P3, class P4, class P5,
-          R F(P1, P2, P3, P4, P5), class I>
-struct BoundFunc5 : public BoundFunc<P2> {
-  typedef BoundFunc<P2> Base;
-  typedef I FuncInfo;
-  explicit BoundFunc5(typename Base::MutableP2 arg) : Base(arg) {}
-};
-
-/* FuncSig ********************************************************************/
-
-/* FuncSig1, FuncSig2, FuncSig3: template classes reflecting a function
- * *signature*, but without a specific function attached.
- *
- * These classes contain member functions that can be invoked with a
- * specific function to return a Func/BoundFunc class. */
-template <class R, class P1>
-struct FuncSig1 {
-  template <R F(P1)>
-  Func1<R, P1, F, FuncInfo<P1, R> > GetFunc() {
-    return Func1<R, P1, F, FuncInfo<P1, R> >();
-  }
-};
-
-template <class R, class P1, class P2>
-struct FuncSig2 {
-  template <R F(P1, P2)>
-  Func2<R, P1, P2, F, FuncInfo<P1, R> > GetFunc() {
-    return Func2<R, P1, P2, F, FuncInfo<P1, R> >();
-  }
-
-  template <R F(P1, P2)>
-  BoundFunc2<R, P1, P2, F, FuncInfo<P1, R> > GetFunc(
-      typename remove_constptr<P2>::type param2) {
-    return BoundFunc2<R, P1, P2, F, FuncInfo<P1, R> >(param2);
-  }
-};
-
-template <class R, class P1, class P2, class P3>
-struct FuncSig3 {
-  template <R F(P1, P2, P3)>
-  Func3<R, P1, P2, P3, F, FuncInfo<P1, R> > GetFunc() {
-    return Func3<R, P1, P2, P3, F, FuncInfo<P1, R> >();
-  }
-
-  template <R F(P1, P2, P3)>
-  BoundFunc3<R, P1, P2, P3, F, FuncInfo<P1, R> > GetFunc(
-      typename remove_constptr<P2>::type param2) {
-    return BoundFunc3<R, P1, P2, P3, F, FuncInfo<P1, R> >(param2);
-  }
-};
-
-template <class R, class P1, class P2, class P3, class P4>
-struct FuncSig4 {
-  template <R F(P1, P2, P3, P4)>
-  Func4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> > GetFunc() {
-    return Func4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> >();
-  }
-
-  template <R F(P1, P2, P3, P4)>
-  BoundFunc4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> > GetFunc(
-      typename remove_constptr<P2>::type param2) {
-    return BoundFunc4<R, P1, P2, P3, P4, F, FuncInfo<P1, R> >(param2);
-  }
-};
-
-template <class R, class P1, class P2, class P3, class P4, class P5>
-struct FuncSig5 {
-  template <R F(P1, P2, P3, P4, P5)>
-  Func5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> > GetFunc() {
-    return Func5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> >();
-  }
-
-  template <R F(P1, P2, P3, P4, P5)>
-  BoundFunc5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> > GetFunc(
-      typename remove_constptr<P2>::type param2) {
-    return BoundFunc5<R, P1, P2, P3, P4, P5, F, FuncInfo<P1, R> >(param2);
-  }
-};
-
-/* Overloaded template function that can construct the appropriate FuncSig*
- * class given a function pointer by deducing the template parameters. */
-template <class R, class P1>
-inline FuncSig1<R, P1> MatchFunc(R (*f)(P1)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return FuncSig1<R, P1>();
-}
-
-template <class R, class P1, class P2>
-inline FuncSig2<R, P1, P2> MatchFunc(R (*f)(P1, P2)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return FuncSig2<R, P1, P2>();
-}
-
-template <class R, class P1, class P2, class P3>
-inline FuncSig3<R, P1, P2, P3> MatchFunc(R (*f)(P1, P2, P3)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return FuncSig3<R, P1, P2, P3>();
-}
-
-template <class R, class P1, class P2, class P3, class P4>
-inline FuncSig4<R, P1, P2, P3, P4> MatchFunc(R (*f)(P1, P2, P3, P4)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return FuncSig4<R, P1, P2, P3, P4>();
-}
-
-template <class R, class P1, class P2, class P3, class P4, class P5>
-inline FuncSig5<R, P1, P2, P3, P4, P5> MatchFunc(R (*f)(P1, P2, P3, P4, P5)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return FuncSig5<R, P1, P2, P3, P4, P5>();
-}
-
-/* MethodSig ******************************************************************/
-
-/* CallMethod*: a function template that calls a given method. */
-template <class R, class C, R (C::*F)()>
-R CallMethod0(C *obj) {
-  return ((*obj).*F)();
-}
-
-template <class R, class C, class P1, R (C::*F)(P1)>
-R CallMethod1(C *obj, P1 arg1) {
-  return ((*obj).*F)(arg1);
-}
-
-template <class R, class C, class P1, class P2, R (C::*F)(P1, P2)>
-R CallMethod2(C *obj, P1 arg1, P2 arg2) {
-  return ((*obj).*F)(arg1, arg2);
-}
-
-template <class R, class C, class P1, class P2, class P3, R (C::*F)(P1, P2, P3)>
-R CallMethod3(C *obj, P1 arg1, P2 arg2, P3 arg3) {
-  return ((*obj).*F)(arg1, arg2, arg3);
-}
-
-template <class R, class C, class P1, class P2, class P3, class P4,
-          R (C::*F)(P1, P2, P3, P4)>
-R CallMethod4(C *obj, P1 arg1, P2 arg2, P3 arg3, P4 arg4) {
-  return ((*obj).*F)(arg1, arg2, arg3, arg4);
-}
-
-/* MethodSig: like FuncSig, but for member functions.
- *
- * GetFunc() returns a normal FuncN object, so after calling GetFunc() no
- * more logic is required to special-case methods. */
-template <class R, class C>
-struct MethodSig0 {
-  template <R (C::*F)()>
-  Func1<R, C *, CallMethod0<R, C, F>, FuncInfo<C *, R> > GetFunc() {
-    return Func1<R, C *, CallMethod0<R, C, F>, FuncInfo<C *, R> >();
-  }
-};
-
-template <class R, class C, class P1>
-struct MethodSig1 {
-  template <R (C::*F)(P1)>
-  Func2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> > GetFunc() {
-    return Func2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> >();
-  }
-
-  template <R (C::*F)(P1)>
-  BoundFunc2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> > GetFunc(
-      typename remove_constptr<P1>::type param1) {
-    return BoundFunc2<R, C *, P1, CallMethod1<R, C, P1, F>, FuncInfo<C *, R> >(
-        param1);
-  }
-};
-
-template <class R, class C, class P1, class P2>
-struct MethodSig2 {
-  template <R (C::*F)(P1, P2)>
-  Func3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>, FuncInfo<C *, R> >
-  GetFunc() {
-    return Func3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>,
-                 FuncInfo<C *, R> >();
-  }
-
-  template <R (C::*F)(P1, P2)>
-  BoundFunc3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>, FuncInfo<C *, R> >
-  GetFunc(typename remove_constptr<P1>::type param1) {
-    return BoundFunc3<R, C *, P1, P2, CallMethod2<R, C, P1, P2, F>,
-                      FuncInfo<C *, R> >(param1);
-  }
-};
-
-template <class R, class C, class P1, class P2, class P3>
-struct MethodSig3 {
-  template <R (C::*F)(P1, P2, P3)>
-  Func4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>, FuncInfo<C *, R> >
-  GetFunc() {
-    return Func4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>,
-                 FuncInfo<C *, R> >();
-  }
-
-  template <R (C::*F)(P1, P2, P3)>
-  BoundFunc4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>,
-             FuncInfo<C *, R> >
-  GetFunc(typename remove_constptr<P1>::type param1) {
-    return BoundFunc4<R, C *, P1, P2, P3, CallMethod3<R, C, P1, P2, P3, F>,
-                      FuncInfo<C *, R> >(param1);
-  }
-};
-
-template <class R, class C, class P1, class P2, class P3, class P4>
-struct MethodSig4 {
-  template <R (C::*F)(P1, P2, P3, P4)>
-  Func5<R, C *, P1, P2, P3, P4, CallMethod4<R, C, P1, P2, P3, P4, F>,
-        FuncInfo<C *, R> >
-  GetFunc() {
-    return Func5<R, C *, P1, P2, P3, P4, CallMethod4<R, C, P1, P2, P3, P4, F>,
-                 FuncInfo<C *, R> >();
-  }
-
-  template <R (C::*F)(P1, P2, P3, P4)>
-  BoundFunc5<R, C *, P1, P2, P3, P4, CallMethod4<R, C, P1, P2, P3, P4, F>,
-             FuncInfo<C *, R> >
-  GetFunc(typename remove_constptr<P1>::type param1) {
-    return BoundFunc5<R, C *, P1, P2, P3, P4,
-                      CallMethod4<R, C, P1, P2, P3, P4, F>, FuncInfo<C *, R> >(
-        param1);
-  }
-};
-
-template <class R, class C>
-inline MethodSig0<R, C> MatchFunc(R (C::*f)()) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return MethodSig0<R, C>();
-}
-
-template <class R, class C, class P1>
-inline MethodSig1<R, C, P1> MatchFunc(R (C::*f)(P1)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return MethodSig1<R, C, P1>();
-}
-
-template <class R, class C, class P1, class P2>
-inline MethodSig2<R, C, P1, P2> MatchFunc(R (C::*f)(P1, P2)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return MethodSig2<R, C, P1, P2>();
-}
-
-template <class R, class C, class P1, class P2, class P3>
-inline MethodSig3<R, C, P1, P2, P3> MatchFunc(R (C::*f)(P1, P2, P3)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return MethodSig3<R, C, P1, P2, P3>();
-}
-
-template <class R, class C, class P1, class P2, class P3, class P4>
-inline MethodSig4<R, C, P1, P2, P3, P4> MatchFunc(R (C::*f)(P1, P2, P3, P4)) {
-  UPB_UNUSED(f);  /* Only used for template parameter deduction. */
-  return MethodSig4<R, C, P1, P2, P3, P4>();
-}
-
-/* MaybeWrapReturn ************************************************************/
-
-/* Template class that attempts to wrap the return value of the function so it
- * matches the expected type.  There are two main adjustments it may make:
- *
- *   1. If the function returns void, make it return the expected type and with
- *      a value that always indicates success.
- *   2. If the function returns bool, make it return the expected type with a
- *      value that indicates success or failure.
- *
- * The "expected type" for return is:
- *   1. void* for start handlers.  If the closure parameter has a different type
- *      we will cast it to void* for the return in the success case.
- *   2. size_t for string buffer handlers.
- *   3. bool for everything else. */
-
-/* Template parameters are FuncN type and desired return type. */
-template <class F, class R, class Enable = void>
-struct MaybeWrapReturn;
-
-/* If the return type matches, return the given function unwrapped. */
-template <class F>
-struct MaybeWrapReturn<F, typename F::Return> {
-  typedef F Func;
-};
-
-/* Function wrapper that munges the return value from void to (bool)true. */
-template <class P1, class P2, void F(P1, P2)>
-bool ReturnTrue2(P1 p1, P2 p2) {
-  F(p1, p2);
-  return true;
-}
-
-template <class P1, class P2, class P3, void F(P1, P2, P3)>
-bool ReturnTrue3(P1 p1, P2 p2, P3 p3) {
-  F(p1, p2, p3);
-  return true;
-}
-
-/* Function wrapper that munges the return value from void to (void*)arg1  */
-template <class P1, class P2, void F(P1, P2)>
-void *ReturnClosure2(P1 p1, P2 p2) {
-  F(p1, p2);
-  return p1;
-}
-
-template <class P1, class P2, class P3, void F(P1, P2, P3)>
-void *ReturnClosure3(P1 p1, P2 p2, P3 p3) {
-  F(p1, p2, p3);
-  return p1;
-}
-
-/* Function wrapper that munges the return value from R to void*. */
-template <class R, class P1, class P2, R F(P1, P2)>
-void *CastReturnToVoidPtr2(P1 p1, P2 p2) {
-  return F(p1, p2);
-}
-
-template <class R, class P1, class P2, class P3, R F(P1, P2, P3)>
-void *CastReturnToVoidPtr3(P1 p1, P2 p2, P3 p3) {
-  return F(p1, p2, p3);
-}
-
-/* Function wrapper that munges the return value from bool to void*. */
-template <class P1, class P2, bool F(P1, P2)>
-void *ReturnClosureOrBreak2(P1 p1, P2 p2) {
-  return F(p1, p2) ? p1 : UPB_BREAK;
-}
-
-template <class P1, class P2, class P3, bool F(P1, P2, P3)>
-void *ReturnClosureOrBreak3(P1 p1, P2 p2, P3 p3) {
-  return F(p1, p2, p3) ? p1 : UPB_BREAK;
-}
-
-/* For the string callback, which takes five params, returns the size param. */
-template <class P1, class P2,
-          void F(P1, P2, const char *, size_t, const upb_bufhandle *)>
-size_t ReturnStringLen(P1 p1, P2 p2, const char *p3, size_t p4,
-                       const upb_bufhandle *p5) {
-  F(p1, p2, p3, p4, p5);
-  return p4;
-}
-
-/* For the string callback, which takes five params, returns the size param or
- * zero. */
-template <class P1, class P2,
-          bool F(P1, P2, const char *, size_t, const upb_bufhandle *)>
-size_t ReturnNOr0(P1 p1, P2 p2, const char *p3, size_t p4,
-                  const upb_bufhandle *p5) {
-  return F(p1, p2, p3, p4, p5) ? p4 : 0;
-}
-
-/* If we have a function returning void but want a function returning bool, wrap
- * it in a function that returns true. */
-template <class P1, class P2, void F(P1, P2), class I>
-struct MaybeWrapReturn<Func2<void, P1, P2, F, I>, bool> {
-  typedef Func2<bool, P1, P2, ReturnTrue2<P1, P2, F>, I> Func;
-};
-
-template <class P1, class P2, class P3, void F(P1, P2, P3), class I>
-struct MaybeWrapReturn<Func3<void, P1, P2, P3, F, I>, bool> {
-  typedef Func3<bool, P1, P2, P3, ReturnTrue3<P1, P2, P3, F>, I> Func;
-};
-
-/* If our function returns void but we want one returning void*, wrap it in a
- * function that returns the first argument. */
-template <class P1, class P2, void F(P1, P2), class I>
-struct MaybeWrapReturn<Func2<void, P1, P2, F, I>, void *> {
-  typedef Func2<void *, P1, P2, ReturnClosure2<P1, P2, F>, I> Func;
-};
-
-template <class P1, class P2, class P3, void F(P1, P2, P3), class I>
-struct MaybeWrapReturn<Func3<void, P1, P2, P3, F, I>, void *> {
-  typedef Func3<void *, P1, P2, P3, ReturnClosure3<P1, P2, P3, F>, I> Func;
-};
-
-/* If our function returns R* but we want one returning void*, wrap it in a
- * function that casts to void*. */
-template <class R, class P1, class P2, R *F(P1, P2), class I>
-struct MaybeWrapReturn<Func2<R *, P1, P2, F, I>, void *,
-                       typename disable_if_same<R *, void *>::Type> {
-  typedef Func2<void *, P1, P2, CastReturnToVoidPtr2<R *, P1, P2, F>, I> Func;
-};
-
-template <class R, class P1, class P2, class P3, R *F(P1, P2, P3), class I>
-struct MaybeWrapReturn<Func3<R *, P1, P2, P3, F, I>, void *,
-                       typename disable_if_same<R *, void *>::Type> {
-  typedef Func3<void *, P1, P2, P3, CastReturnToVoidPtr3<R *, P1, P2, P3, F>, I>
-      Func;
-};
-
-/* If our function returns bool but we want one returning void*, wrap it in a
- * function that returns either the first param or UPB_BREAK. */
-template <class P1, class P2, bool F(P1, P2), class I>
-struct MaybeWrapReturn<Func2<bool, P1, P2, F, I>, void *> {
-  typedef Func2<void *, P1, P2, ReturnClosureOrBreak2<P1, P2, F>, I> Func;
-};
-
-template <class P1, class P2, class P3, bool F(P1, P2, P3), class I>
-struct MaybeWrapReturn<Func3<bool, P1, P2, P3, F, I>, void *> {
-  typedef Func3<void *, P1, P2, P3, ReturnClosureOrBreak3<P1, P2, P3, F>, I>
-      Func;
-};
-
-/* If our function returns void but we want one returning size_t, wrap it in a
- * function that returns the size argument. */
-template <class P1, class P2,
-          void F(P1, P2, const char *, size_t, const upb_bufhandle *), class I>
-struct MaybeWrapReturn<
-    Func5<void, P1, P2, const char *, size_t, const upb_bufhandle *, F, I>,
-          size_t> {
-  typedef Func5<size_t, P1, P2, const char *, size_t, const upb_bufhandle *,
-                ReturnStringLen<P1, P2, F>, I> Func;
-};
-
-/* If our function returns bool but we want one returning size_t, wrap it in a
- * function that returns either 0 or the buf size. */
-template <class P1, class P2,
-          bool F(P1, P2, const char *, size_t, const upb_bufhandle *), class I>
-struct MaybeWrapReturn<
-    Func5<bool, P1, P2, const char *, size_t, const upb_bufhandle *, F, I>,
-    size_t> {
-  typedef Func5<size_t, P1, P2, const char *, size_t, const upb_bufhandle *,
-                ReturnNOr0<P1, P2, F>, I> Func;
-};
-
-/* ConvertParams **************************************************************/
-
-/* Template class that converts the function parameters if necessary, and
- * ignores the HandlerData parameter if appropriate.
- *
- * Template parameter is the are FuncN function type. */
-template <class F, class T>
-struct ConvertParams;
-
-/* Function that discards the handler data parameter. */
-template <class R, class P1, R F(P1)>
-R IgnoreHandlerData2(void *p1, const void *hd) {
-  UPB_UNUSED(hd);
-  return F(static_cast<P1>(p1));
-}
-
-template <class R, class P1, class P2Wrapper, class P2Wrapped,
-          R F(P1, P2Wrapped)>
-R IgnoreHandlerData3(void *p1, const void *hd, P2Wrapper p2) {
-  UPB_UNUSED(hd);
-  return F(static_cast<P1>(p1), p2);
-}
-
-template <class R, class P1, class P2, class P3, R F(P1, P2, P3)>
-R IgnoreHandlerData4(void *p1, const void *hd, P2 p2, P3 p3) {
-  UPB_UNUSED(hd);
-  return F(static_cast<P1>(p1), p2, p3);
-}
-
-template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4)>
-R IgnoreHandlerData5(void *p1, const void *hd, P2 p2, P3 p3, P4 p4) {
-  UPB_UNUSED(hd);
-  return F(static_cast<P1>(p1), p2, p3, p4);
-}
-
-template <class R, class P1, R F(P1, const char*, size_t)>
-R IgnoreHandlerDataIgnoreHandle(void *p1, const void *hd, const char *p2,
-                                size_t p3, const upb_bufhandle *handle) {
-  UPB_UNUSED(hd);
-  UPB_UNUSED(handle);
-  return F(static_cast<P1>(p1), p2, p3);
-}
-
-/* Function that casts the handler data parameter. */
-template <class R, class P1, class P2, R F(P1, P2)>
-R CastHandlerData2(void *c, const void *hd) {
-  return F(static_cast<P1>(c), static_cast<P2>(hd));
-}
-
-template <class R, class P1, class P2, class P3Wrapper, class P3Wrapped,
-          R F(P1, P2, P3Wrapped)>
-R CastHandlerData3(void *c, const void *hd, P3Wrapper p3) {
-  return F(static_cast<P1>(c), static_cast<P2>(hd), p3);
-}
-
-template <class R, class P1, class P2, class P3, class P4, class P5,
-          R F(P1, P2, P3, P4, P5)>
-R CastHandlerData5(void *c, const void *hd, P3 p3, P4 p4, P5 p5) {
-  return F(static_cast<P1>(c), static_cast<P2>(hd), p3, p4, p5);
-}
-
-template <class R, class P1, class P2, R F(P1, P2, const char *, size_t)>
-R CastHandlerDataIgnoreHandle(void *c, const void *hd, const char *p3,
-                              size_t p4, const upb_bufhandle *handle) {
-  UPB_UNUSED(handle);
-  return F(static_cast<P1>(c), static_cast<P2>(hd), p3, p4);
-}
-
-/* For unbound functions, ignore the handler data. */
-template <class R, class P1, R F(P1), class I, class T>
-struct ConvertParams<Func1<R, P1, F, I>, T> {
-  typedef Func2<R, void *, const void *, IgnoreHandlerData2<R, P1, F>, I> Func;
-};
-
-template <class R, class P1, class P2, R F(P1, P2), class I,
-          class R2, class P1_2, class P2_2, class P3_2>
-struct ConvertParams<Func2<R, P1, P2, F, I>,
-                     R2 (*)(P1_2, P2_2, P3_2)> {
-  typedef Func3<R, void *, const void *, P3_2,
-                IgnoreHandlerData3<R, P1, P3_2, P2, F>, I> Func;
-};
-
-/* For StringBuffer only; this ignores both the handler data and the
- * upb_bufhandle. */
-template <class R, class P1, R F(P1, const char *, size_t), class I, class T>
-struct ConvertParams<Func3<R, P1, const char *, size_t, F, I>, T> {
-  typedef Func5<R, void *, const void *, const char *, size_t,
-                const upb_bufhandle *, IgnoreHandlerDataIgnoreHandle<R, P1, F>,
-                I> Func;
-};
-
-template <class R, class P1, class P2, class P3, class P4, R F(P1, P2, P3, P4),
-          class I, class T>
-struct ConvertParams<Func4<R, P1, P2, P3, P4, F, I>, T> {
-  typedef Func5<R, void *, const void *, P2, P3, P4,
-                IgnoreHandlerData5<R, P1, P2, P3, P4, F>, I> Func;
-};
-
-/* For bound functions, cast the handler data. */
-template <class R, class P1, class P2, R F(P1, P2), class I, class T>
-struct ConvertParams<BoundFunc2<R, P1, P2, F, I>, T> {
-  typedef Func2<R, void *, const void *, CastHandlerData2<R, P1, P2, F>, I>
-      Func;
-};
-
-template <class R, class P1, class P2, class P3, R F(P1, P2, P3), class I,
-          class R2, class P1_2, class P2_2, class P3_2>
-struct ConvertParams<BoundFunc3<R, P1, P2, P3, F, I>,
-                     R2 (*)(P1_2, P2_2, P3_2)> {
-  typedef Func3<R, void *, const void *, P3_2,
-                CastHandlerData3<R, P1, P2, P3_2, P3, F>, I> Func;
-};
-
-/* For StringBuffer only; this ignores the upb_bufhandle. */
-template <class R, class P1, class P2, R F(P1, P2, const char *, size_t),
-          class I, class T>
-struct ConvertParams<BoundFunc4<R, P1, P2, const char *, size_t, F, I>, T> {
-  typedef Func5<R, void *, const void *, const char *, size_t,
-                const upb_bufhandle *,
-                CastHandlerDataIgnoreHandle<R, P1, P2, F>, I>
-      Func;
-};
-
-template <class R, class P1, class P2, class P3, class P4, class P5,
-          R F(P1, P2, P3, P4, P5), class I, class T>
-struct ConvertParams<BoundFunc5<R, P1, P2, P3, P4, P5, F, I>, T> {
-  typedef Func5<R, void *, const void *, P3, P4, P5,
-                CastHandlerData5<R, P1, P2, P3, P4, P5, F>, I> Func;
-};
-
-/* utype/ltype are upper/lower-case, ctype is canonical C type, vtype is
- * variant C type. */
-#define TYPE_METHODS(utype, ltype, ctype, vtype)                      \
-  template <>                                                         \
-  struct CanonicalType<vtype> {                                       \
-    typedef ctype Type;                                               \
-  };                                                                  \
-  template <>                                                         \
-  inline bool HandlersPtr::SetValueHandler<vtype>(                    \
-      FieldDefPtr f, const HandlersPtr::utype##Handler &handler) {    \
-    handler.AddCleanup(ptr());                                        \
-    return upb_handlers_set##ltype(ptr(), f.ptr(), handler.handler(), \
-                                   &handler.attr());                  \
-  }
-
-TYPE_METHODS(Double, double, double,   double)
-TYPE_METHODS(Float,  float,  float,    float)
-TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64_T)
-TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32_T)
-TYPE_METHODS(Int64,  int64,  int64_t,  UPB_INT64_T)
-TYPE_METHODS(Int32,  int32,  int32_t,  UPB_INT32_T)
-TYPE_METHODS(Bool,   bool,   bool,     bool)
-
-#ifdef UPB_TWO_32BIT_TYPES
-TYPE_METHODS(Int32,  int32,  int32_t,  UPB_INT32ALT_T)
-TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32ALT_T)
-#endif
-
-#ifdef UPB_TWO_64BIT_TYPES
-TYPE_METHODS(Int64,  int64,  int64_t,  UPB_INT64ALT_T)
-TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64ALT_T)
-#endif
-#undef TYPE_METHODS
-
-template <> struct CanonicalType<Status*> {
-  typedef Status* Type;
-};
-
-template <class F> struct ReturnOf;
-
-template <class R, class P1, class P2>
-struct ReturnOf<R (*)(P1, P2)> {
-  typedef R Return;
-};
-
-template <class R, class P1, class P2, class P3>
-struct ReturnOf<R (*)(P1, P2, P3)> {
-  typedef R Return;
-};
-
-template <class R, class P1, class P2, class P3, class P4>
-struct ReturnOf<R (*)(P1, P2, P3, P4)> {
-  typedef R Return;
-};
-
-template <class R, class P1, class P2, class P3, class P4, class P5>
-struct ReturnOf<R (*)(P1, P2, P3, P4, P5)> {
-  typedef R Return;
-};
-
-
-template <class T>
-template <class F>
-inline Handler<T>::Handler(F func)
-    : registered_(false),
-      cleanup_data_(func.GetData()),
-      cleanup_func_(func.GetCleanup()) {
-  attr_.handler_data = func.GetData();
-  typedef typename ReturnOf<T>::Return Return;
-  typedef typename ConvertParams<F, T>::Func ConvertedParamsFunc;
-  typedef typename MaybeWrapReturn<ConvertedParamsFunc, Return>::Func
-      ReturnWrappedFunc;
-  handler_ = ReturnWrappedFunc().Call;
-
-  /* Set attributes based on what templates can statically tell us about the
-   * user's function. */
-
-  /* If the original function returns void, then we know that we wrapped it to
-   * always return ok. */
-  bool always_ok = is_same<typename F::FuncInfo::Return, void>::value;
-  attr_.alwaysok = always_ok;
-
-  /* Closure parameter and return type. */
-  attr_.closure_type = UniquePtrForType<typename F::FuncInfo::Closure>();
-
-  /* We use the closure type (from the first parameter) if the return type is
-   * void or bool, since these are the two cases we wrap to return the closure's
-   * type anyway.
-   *
-   * This is all nonsense for non START* handlers, but it doesn't matter because
-   * in that case the value will be ignored. */
-  typedef typename FirstUnlessVoidOrBool<typename F::FuncInfo::Return,
-                                         typename F::FuncInfo::Closure>::value
-      EffectiveReturn;
-  attr_.return_closure_type = UniquePtrForType<EffectiveReturn>();
-}
-
-template <class T>
-inline void Handler<T>::AddCleanup(upb_handlers* h) const {
-  UPB_ASSERT(!registered_);
-  registered_ = true;
-  if (cleanup_func_) {
-    bool ok = upb_handlers_addcleanup(h, cleanup_data_, cleanup_func_);
-    UPB_ASSERT(ok);
-  }
-}
-
-}  /* namespace upb */
-
-#endif  /* __cplusplus */
-
-
-#undef UPB_TWO_32BIT_TYPES
-#undef UPB_TWO_64BIT_TYPES
-#undef UPB_INT32_T
-#undef UPB_UINT32_T
-#undef UPB_INT32ALT_T
-#undef UPB_UINT32ALT_T
-#undef UPB_INT64_T
-#undef UPB_UINT64_T
-#undef UPB_INT64ALT_T
-#undef UPB_UINT64ALT_T
-
-
-#endif  /* UPB_HANDLERS_INL_H_ */
-
-#endif  /* UPB_HANDLERS_H */
-/*
-** upb::Sink (upb_sink)
-** upb::BytesSink (upb_bytessink)
-**
-** A upb_sink is an object that binds a upb_handlers object to some runtime
-** state.  It is the object that can actually receive data via the upb_handlers
-** interface.
-**
-** Unlike upb_def and upb_handlers, upb_sink is never frozen, immutable, or
-** thread-safe.  You can create as many of them as you want, but each one may
-** only be used in a single thread at a time.
-**
-** If we compare with class-based OOP, a you can think of a upb_def as an
-** abstract base class, a upb_handlers as a concrete derived class, and a
-** upb_sink as an object (class instance).
-*/
-
-#ifndef UPB_SINK_H
-#define UPB_SINK_H
-
-
-
-#ifdef __cplusplus
-namespace upb {
-class BytesSink;
-class Sink;
-}
-#endif
-
-/* upb_sink *******************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct {
-  const upb_handlers *handlers;
-  void *closure;
-} upb_sink;
-
-#define PUTVAL(type, ctype)                                           \
-  UPB_INLINE bool upb_sink_put##type(upb_sink s, upb_selector_t sel,  \
-                                     ctype val) {                     \
-    typedef upb_##type##_handlerfunc functype;                        \
-    functype *func;                                                   \
-    const void *hd;                                                   \
-    if (!s.handlers) return true;                                     \
-    func = (functype *)upb_handlers_gethandler(s.handlers, sel, &hd); \
-    if (!func) return true;                                           \
-    return func(s.closure, hd, val);                                  \
-  }
-
-PUTVAL(int32,  int32_t)
-PUTVAL(int64,  int64_t)
-PUTVAL(uint32, uint32_t)
-PUTVAL(uint64, uint64_t)
-PUTVAL(float,  float)
-PUTVAL(double, double)
-PUTVAL(bool,   bool)
-#undef PUTVAL
-
-UPB_INLINE void upb_sink_reset(upb_sink *s, const upb_handlers *h, void *c) {
-  s->handlers = h;
-  s->closure = c;
-}
-
-UPB_INLINE size_t upb_sink_putstring(upb_sink s, upb_selector_t sel,
-                                     const char *buf, size_t n,
-                                     const upb_bufhandle *handle) {
-  typedef upb_string_handlerfunc func;
-  func *handler;
-  const void *hd;
-  if (!s.handlers) return n;
-  handler = (func *)upb_handlers_gethandler(s.handlers, sel, &hd);
-
-  if (!handler) return n;
-  return handler(s.closure, hd, buf, n, handle);
-}
-
-UPB_INLINE bool upb_sink_putunknown(upb_sink s, const char *buf, size_t n) {
-  typedef upb_unknown_handlerfunc func;
-  func *handler;
-  const void *hd;
-  if (!s.handlers) return true;
-  handler =
-      (func *)upb_handlers_gethandler(s.handlers, UPB_UNKNOWN_SELECTOR, &hd);
-
-  if (!handler) return n;
-  return handler(s.closure, hd, buf, n);
-}
-
-UPB_INLINE bool upb_sink_startmsg(upb_sink s) {
-  typedef upb_startmsg_handlerfunc func;
-  func *startmsg;
-  const void *hd;
-  if (!s.handlers) return true;
-  startmsg =
-      (func *)upb_handlers_gethandler(s.handlers, UPB_STARTMSG_SELECTOR, &hd);
-
-  if (!startmsg) return true;
-  return startmsg(s.closure, hd);
-}
-
-UPB_INLINE bool upb_sink_endmsg(upb_sink s, upb_status *status) {
-  typedef upb_endmsg_handlerfunc func;
-  func *endmsg;
-  const void *hd;
-  if (!s.handlers) return true;
-  endmsg =
-      (func *)upb_handlers_gethandler(s.handlers, UPB_ENDMSG_SELECTOR, &hd);
-
-  if (!endmsg) return true;
-  return endmsg(s.closure, hd, status);
-}
-
-UPB_INLINE bool upb_sink_startseq(upb_sink s, upb_selector_t sel,
-                                  upb_sink *sub) {
-  typedef upb_startfield_handlerfunc func;
-  func *startseq;
-  const void *hd;
-  sub->closure = s.closure;
-  sub->handlers = s.handlers;
-  if (!s.handlers) return true;
-  startseq = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
-
-  if (!startseq) return true;
-  sub->closure = startseq(s.closure, hd);
-  return sub->closure ? true : false;
-}
-
-UPB_INLINE bool upb_sink_endseq(upb_sink s, upb_selector_t sel) {
-  typedef upb_endfield_handlerfunc func;
-  func *endseq;
-  const void *hd;
-  if (!s.handlers) return true;
-  endseq = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
-
-  if (!endseq) return true;
-  return endseq(s.closure, hd);
-}
-
-UPB_INLINE bool upb_sink_startstr(upb_sink s, upb_selector_t sel,
-                                  size_t size_hint, upb_sink *sub) {
-  typedef upb_startstr_handlerfunc func;
-  func *startstr;
-  const void *hd;
-  sub->closure = s.closure;
-  sub->handlers = s.handlers;
-  if (!s.handlers) return true;
-  startstr = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
-
-  if (!startstr) return true;
-  sub->closure = startstr(s.closure, hd, size_hint);
-  return sub->closure ? true : false;
-}
-
-UPB_INLINE bool upb_sink_endstr(upb_sink s, upb_selector_t sel) {
-  typedef upb_endfield_handlerfunc func;
-  func *endstr;
-  const void *hd;
-  if (!s.handlers) return true;
-  endstr = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
-
-  if (!endstr) return true;
-  return endstr(s.closure, hd);
-}
-
-UPB_INLINE bool upb_sink_startsubmsg(upb_sink s, upb_selector_t sel,
-                                     upb_sink *sub) {
-  typedef upb_startfield_handlerfunc func;
-  func *startsubmsg;
-  const void *hd;
-  sub->closure = s.closure;
-  if (!s.handlers) {
-    sub->handlers = NULL;
-    return true;
-  }
-  sub->handlers = upb_handlers_getsubhandlers_sel(s.handlers, sel);
-  startsubmsg = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
-
-  if (!startsubmsg) return true;
-  sub->closure = startsubmsg(s.closure, hd);
-  return sub->closure ? true : false;
-}
-
-UPB_INLINE bool upb_sink_endsubmsg(upb_sink s, upb_sink sub,
-                                   upb_selector_t sel) {
-  typedef upb_endfield_handlerfunc func;
-  func *endsubmsg;
-  const void *hd;
-  if (!s.handlers) return true;
-  endsubmsg = (func*)upb_handlers_gethandler(s.handlers, sel, &hd);
-
-  if (!endsubmsg) return true;
-  return endsubmsg(sub.closure, hd);
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* A upb::Sink is an object that binds a upb::Handlers object to some runtime
- * state.  It represents an endpoint to which data can be sent.
- *
- * TODO(haberman): right now all of these functions take selectors.  Should they
- * take selectorbase instead?
- *
- * ie. instead of calling:
- *   sink->StartString(FOO_FIELD_START_STRING, ...)
- * a selector base would let you say:
- *   sink->StartString(FOO_FIELD, ...)
- *
- * This would make call sites a little nicer and require emitting fewer selector
- * definitions in .h files.
- *
- * But the current scheme has the benefit that you can retrieve a function
- * pointer for any handler with handlers->GetHandler(selector), without having
- * to have a separate GetHandler() function for each handler type.  The JIT
- * compiler uses this.  To accommodate we'd have to expose a separate
- * GetHandler() for every handler type.
- *
- * Also to ponder: selectors right now are independent of a specific Handlers
- * instance.  In other words, they allocate a number to every possible handler
- * that *could* be registered, without knowing anything about what handlers
- * *are* registered.  That means that using selectors as table offsets prohibits
- * us from compacting the handler table at Freeze() time.  If the table is very
- * sparse, this could be wasteful.
- *
- * Having another selector-like thing that is specific to a Handlers instance
- * would allow this compacting, but then it would be impossible to write code
- * ahead-of-time that can be bound to any Handlers instance at runtime.  For
- * example, a .proto file parser written as straight C will not know what
- * Handlers it will be bound to, so when it calls sink->StartString() what
- * selector will it pass?  It needs a selector like we have today, that is
- * independent of any particular upb::Handlers.
- *
- * Is there a way then to allow Handlers table compaction? */
-class upb::Sink {
- public:
-  /* Constructor with no initialization; must be Reset() before use. */
-  Sink() {}
-
-  Sink(const Sink&) = default;
-  Sink& operator=(const Sink&) = default;
-
-  Sink(const upb_sink& sink) : sink_(sink) {}
-  Sink &operator=(const upb_sink &sink) {
-    sink_ = sink;
-    return *this;
-  }
-
-  upb_sink sink() { return sink_; }
-
-  /* Constructs a new sink for the given frozen handlers and closure.
-   *
-   * TODO: once the Handlers know the expected closure type, verify that T
-   * matches it. */
-  template <class T> Sink(const upb_handlers* handlers, T* closure) {
-    Reset(handlers, closure);
-  }
-
-  upb_sink* ptr() { return &sink_; }
-
-  /* Resets the value of the sink. */
-  template <class T> void Reset(const upb_handlers* handlers, T* closure) {
-    upb_sink_reset(&sink_, handlers, closure);
-  }
-
-  /* Returns the top-level object that is bound to this sink.
-   *
-   * TODO: once the Handlers know the expected closure type, verify that T
-   * matches it. */
-  template <class T> T* GetObject() const {
-    return static_cast<T*>(sink_.closure);
-  }
-
-  /* Functions for pushing data into the sink.
-   *
-   * These return false if processing should stop (either due to error or just
-   * to suspend).
-   *
-   * These may not be called from within one of the same sink's handlers (in
-   * other words, handlers are not re-entrant). */
-
-  /* Should be called at the start and end of every message; both the top-level
-   * message and submessages.  This means that submessages should use the
-   * following sequence:
-   *   sink->StartSubMessage(startsubmsg_selector);
-   *   sink->StartMessage();
-   *   // ...
-   *   sink->EndMessage(&status);
-   *   sink->EndSubMessage(endsubmsg_selector); */
-  bool StartMessage() { return upb_sink_startmsg(sink_); }
-  bool EndMessage(upb_status *status) {
-    return upb_sink_endmsg(sink_, status);
-  }
-
-  /* Putting of individual values.  These work for both repeated and
-   * non-repeated fields, but for repeated fields you must wrap them in
-   * calls to StartSequence()/EndSequence(). */
-  bool PutInt32(HandlersPtr::Selector s, int32_t val) {
-    return upb_sink_putint32(sink_, s, val);
-  }
-
-  bool PutInt64(HandlersPtr::Selector s, int64_t val) {
-    return upb_sink_putint64(sink_, s, val);
-  }
-
-  bool PutUInt32(HandlersPtr::Selector s, uint32_t val) {
-    return upb_sink_putuint32(sink_, s, val);
-  }
-
-  bool PutUInt64(HandlersPtr::Selector s, uint64_t val) {
-    return upb_sink_putuint64(sink_, s, val);
-  }
-
-  bool PutFloat(HandlersPtr::Selector s, float val) {
-    return upb_sink_putfloat(sink_, s, val);
-  }
-
-  bool PutDouble(HandlersPtr::Selector s, double val) {
-    return upb_sink_putdouble(sink_, s, val);
-  }
-
-  bool PutBool(HandlersPtr::Selector s, bool val) {
-    return upb_sink_putbool(sink_, s, val);
-  }
-
-  /* Putting of string/bytes values.  Each string can consist of zero or more
-   * non-contiguous buffers of data.
-   *
-   * For StartString(), the function will write a sink for the string to "sub."
-   * The sub-sink must be used for any/all PutStringBuffer() calls. */
-  bool StartString(HandlersPtr::Selector s, size_t size_hint, Sink* sub) {
-    upb_sink sub_c;
-    bool ret = upb_sink_startstr(sink_, s, size_hint, &sub_c);
-    *sub = sub_c;
-    return ret;
-  }
-
-  size_t PutStringBuffer(HandlersPtr::Selector s, const char *buf, size_t len,
-                         const upb_bufhandle *handle) {
-    return upb_sink_putstring(sink_, s, buf, len, handle);
-  }
-
-  bool EndString(HandlersPtr::Selector s) {
-    return upb_sink_endstr(sink_, s);
-  }
-
-  /* For submessage fields.
-   *
-   * For StartSubMessage(), the function will write a sink for the string to
-   * "sub." The sub-sink must be used for any/all handlers called within the
-   * submessage. */
-  bool StartSubMessage(HandlersPtr::Selector s, Sink* sub) {
-    upb_sink sub_c;
-    bool ret = upb_sink_startsubmsg(sink_, s, &sub_c);
-    *sub = sub_c;
-    return ret;
-  }
-
-  bool EndSubMessage(HandlersPtr::Selector s, Sink sub) {
-    return upb_sink_endsubmsg(sink_, sub.sink_, s);
-  }
-
-  /* For repeated fields of any type, the sequence of values must be wrapped in
-   * these calls.
-   *
-   * For StartSequence(), the function will write a sink for the string to
-   * "sub." The sub-sink must be used for any/all handlers called within the
-   * sequence. */
-  bool StartSequence(HandlersPtr::Selector s, Sink* sub) {
-    upb_sink sub_c;
-    bool ret = upb_sink_startseq(sink_, s, &sub_c);
-    *sub = sub_c;
-    return ret;
-  }
-
-  bool EndSequence(HandlersPtr::Selector s) {
-    return upb_sink_endseq(sink_, s);
-  }
-
-  /* Copy and assign specifically allowed.
-   * We don't even bother making these members private because so many
-   * functions need them and this is mainly just a dumb data container anyway.
-   */
-
- private:
-  upb_sink sink_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_bytessink **************************************************************/
-
-typedef struct {
-  const upb_byteshandler *handler;
-  void *closure;
-} upb_bytessink ;
-
-UPB_INLINE void upb_bytessink_reset(upb_bytessink* s, const upb_byteshandler *h,
-                                    void *closure) {
-  s->handler = h;
-  s->closure = closure;
-}
-
-UPB_INLINE bool upb_bytessink_start(upb_bytessink s, size_t size_hint,
-                                    void **subc) {
-  typedef upb_startstr_handlerfunc func;
-  func *start;
-  *subc = s.closure;
-  if (!s.handler) return true;
-  start = (func *)s.handler->table[UPB_STARTSTR_SELECTOR].func;
-
-  if (!start) return true;
-  *subc = start(s.closure,
-                s.handler->table[UPB_STARTSTR_SELECTOR].attr.handler_data,
-                size_hint);
-  return *subc != NULL;
-}
-
-UPB_INLINE size_t upb_bytessink_putbuf(upb_bytessink s, void *subc,
-                                       const char *buf, size_t size,
-                                       const upb_bufhandle* handle) {
-  typedef upb_string_handlerfunc func;
-  func *putbuf;
-  if (!s.handler) return true;
-  putbuf = (func *)s.handler->table[UPB_STRING_SELECTOR].func;
-
-  if (!putbuf) return true;
-  return putbuf(subc, s.handler->table[UPB_STRING_SELECTOR].attr.handler_data,
-                buf, size, handle);
-}
-
-UPB_INLINE bool upb_bytessink_end(upb_bytessink s) {
-  typedef upb_endfield_handlerfunc func;
-  func *end;
-  if (!s.handler) return true;
-  end = (func *)s.handler->table[UPB_ENDSTR_SELECTOR].func;
-
-  if (!end) return true;
-  return end(s.closure,
-             s.handler->table[UPB_ENDSTR_SELECTOR].attr.handler_data);
-}
-
-#ifdef __cplusplus
-
-class upb::BytesSink {
- public:
-  BytesSink() {}
-
-  BytesSink(const BytesSink&) = default;
-  BytesSink& operator=(const BytesSink&) = default;
-
-  BytesSink(const upb_bytessink& sink) : sink_(sink) {}
-  BytesSink &operator=(const upb_bytessink &sink) {
-    sink_ = sink;
-    return *this;
-  }
-
-  upb_bytessink sink() { return sink_; }
-
-  /* Constructs a new sink for the given frozen handlers and closure.
-   *
-   * TODO(haberman): once the Handlers know the expected closure type, verify
-   * that T matches it. */
-  template <class T> BytesSink(const upb_byteshandler* handler, T* closure) {
-    upb_bytessink_reset(sink_, handler, closure);
-  }
-
-  /* Resets the value of the sink. */
-  template <class T> void Reset(const upb_byteshandler* handler, T* closure) {
-    upb_bytessink_reset(&sink_, handler, closure);
-  }
-
-  bool Start(size_t size_hint, void **subc) {
-    return upb_bytessink_start(sink_, size_hint, subc);
-  }
-
-  size_t PutBuffer(void *subc, const char *buf, size_t len,
-                   const upb_bufhandle *handle) {
-    return upb_bytessink_putbuf(sink_, subc, buf, len, handle);
-  }
-
-  bool End() {
-    return upb_bytessink_end(sink_);
-  }
-
- private:
-  upb_bytessink sink_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_bufsrc *****************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink sink);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-namespace upb {
-template <class T> bool PutBuffer(const T& str, BytesSink sink) {
-  return upb_bufsrc_putbuf(str.data(), str.size(), sink.sink());
-}
-}
-
-#endif  /* __cplusplus */
-
-
-#endif
-/*
-** Internal-only definitions for the decoder.
-*/
-
-#ifndef UPB_DECODER_INT_H_
-#define UPB_DECODER_INT_H_
-
-/*
-** upb::pb::Decoder
-**
-** A high performance, streaming, resumable decoder for the binary protobuf
-** format.
-**
-** This interface works the same regardless of what decoder backend is being
-** used.  A client of this class does not need to know whether decoding is using
-** a JITted decoder (DynASM, LLVM, etc) or an interpreted decoder.  By default,
-** it will always use the fastest available decoder.  However, you can call
-** set_allow_jit(false) to disable any JIT decoder that might be available.
-** This is primarily useful for testing purposes.
-*/
-
-#ifndef UPB_DECODER_H_
-#define UPB_DECODER_H_
-
-
-#ifdef __cplusplus
-namespace upb {
-namespace pb {
-class CodeCache;
-class DecoderPtr;
-class DecoderMethodPtr;
-class DecoderMethodOptions;
-}  /* namespace pb */
-}  /* namespace upb */
-#endif
-
-/* The maximum number of bytes we are required to buffer internally between
- * calls to the decoder.  The value is 14: a 5 byte unknown tag plus ten-byte
- * varint, less one because we are buffering an incomplete value.
- *
- * Should only be used by unit tests. */
-#define UPB_DECODER_MAX_RESIDUAL_BYTES 14
-
-/* upb_pbdecodermethod ********************************************************/
-
-struct upb_pbdecodermethod;
-typedef struct upb_pbdecodermethod upb_pbdecodermethod;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-const upb_handlers *upb_pbdecodermethod_desthandlers(
-    const upb_pbdecodermethod *m);
-const upb_byteshandler *upb_pbdecodermethod_inputhandler(
-    const upb_pbdecodermethod *m);
-bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* Represents the code to parse a protobuf according to a destination
- * Handlers. */
-class upb::pb::DecoderMethodPtr {
- public:
-  DecoderMethodPtr() : ptr_(nullptr) {}
-  DecoderMethodPtr(const upb_pbdecodermethod* ptr) : ptr_(ptr) {}
-
-  const upb_pbdecodermethod* ptr() { return ptr_; }
-
-  /* The destination handlers that are statically bound to this method.
-   * This method is only capable of outputting to a sink that uses these
-   * handlers. */
-  const Handlers *dest_handlers() const {
-    return upb_pbdecodermethod_desthandlers(ptr_);
-  }
-
-  /* The input handlers for this decoder method. */
-  const BytesHandler* input_handler() const {
-    return upb_pbdecodermethod_inputhandler(ptr_);
-  }
-
-  /* Whether this method is native. */
-  bool is_native() const {
-    return upb_pbdecodermethod_isnative(ptr_);
-  }
-
- private:
-  const upb_pbdecodermethod* ptr_;
-};
-
-#endif
-
-/* upb_pbdecoder **************************************************************/
-
-/* Preallocation hint: decoder won't allocate more bytes than this when first
- * constructed.  This hint may be an overestimate for some build configurations.
- * But if the decoder library is upgraded without recompiling the application,
- * it may be an underestimate. */
-#define UPB_PB_DECODER_SIZE 4416
-
-struct upb_pbdecoder;
-typedef struct upb_pbdecoder upb_pbdecoder;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-upb_pbdecoder *upb_pbdecoder_create(upb_arena *arena,
-                                    const upb_pbdecodermethod *method,
-                                    upb_sink output, upb_status *status);
-const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d);
-upb_bytessink upb_pbdecoder_input(upb_pbdecoder *d);
-uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d);
-size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d);
-bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max);
-void upb_pbdecoder_reset(upb_pbdecoder *d);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* A Decoder receives binary protobuf data on its input sink and pushes the
- * decoded data to its output sink. */
-class upb::pb::DecoderPtr {
- public:
-  DecoderPtr() : ptr_(nullptr) {}
-  DecoderPtr(upb_pbdecoder* ptr) : ptr_(ptr) {}
-
-  upb_pbdecoder* ptr() { return ptr_; }
-
-  /* Constructs a decoder instance for the given method, which must outlive this
-   * decoder.  Any errors during parsing will be set on the given status, which
-   * must also outlive this decoder.
-   *
-   * The sink must match the given method. */
-  static DecoderPtr Create(Arena *arena, DecoderMethodPtr method,
-                           upb::Sink output, Status *status) {
-    return DecoderPtr(upb_pbdecoder_create(arena->ptr(), method.ptr(),
-                                           output.sink(), status->ptr()));
-  }
-
-  /* Returns the DecoderMethod this decoder is parsing from. */
-  const DecoderMethodPtr method() const {
-    return DecoderMethodPtr(upb_pbdecoder_method(ptr_));
-  }
-
-  /* The sink on which this decoder receives input. */
-  BytesSink input() { return BytesSink(upb_pbdecoder_input(ptr())); }
-
-  /* Returns number of bytes successfully parsed.
-   *
-   * This can be useful for determining the stream position where an error
-   * occurred.
-   *
-   * This value may not be up-to-date when called from inside a parsing
-   * callback. */
-  uint64_t BytesParsed() { return upb_pbdecoder_bytesparsed(ptr()); }
-
-  /* Gets/sets the parsing nexting limit.  If the total number of nested
-   * submessages and repeated fields hits this limit, parsing will fail.  This
-   * is a resource limit that controls the amount of memory used by the parsing
-   * stack.
-   *
-   * Setting the limit will fail if the parser is currently suspended at a depth
-   * greater than this, or if memory allocation of the stack fails. */
-  size_t max_nesting() { return upb_pbdecoder_maxnesting(ptr()); }
-  bool set_max_nesting(size_t max) { return upb_pbdecoder_maxnesting(ptr()); }
-
-  void Reset() { upb_pbdecoder_reset(ptr()); }
-
-  static const size_t kSize = UPB_PB_DECODER_SIZE;
-
- private:
-  upb_pbdecoder *ptr_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_pbcodecache ************************************************************/
-
-/* Lazily builds and caches decoder methods that will push data to the given
- * handlers.  The destination handlercache must outlive this object. */
-
-struct upb_pbcodecache;
-typedef struct upb_pbcodecache upb_pbcodecache;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-upb_pbcodecache *upb_pbcodecache_new(upb_handlercache *dest);
-void upb_pbcodecache_free(upb_pbcodecache *c);
-bool upb_pbcodecache_allowjit(const upb_pbcodecache *c);
-void upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow);
-void upb_pbcodecache_setlazy(upb_pbcodecache *c, bool lazy);
-const upb_pbdecodermethod *upb_pbcodecache_get(upb_pbcodecache *c,
-                                               const upb_msgdef *md);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* A class for caching protobuf processing code, whether bytecode for the
- * interpreted decoder or machine code for the JIT.
- *
- * This class is not thread-safe. */
-class upb::pb::CodeCache {
- public:
-  CodeCache(upb::HandlerCache *dest)
-      : ptr_(upb_pbcodecache_new(dest->ptr()), upb_pbcodecache_free) {}
-  CodeCache(CodeCache&&) = default;
-  CodeCache& operator=(CodeCache&&) = default;
-
-  upb_pbcodecache* ptr() { return ptr_.get(); }
-  const upb_pbcodecache* ptr() const { return ptr_.get(); }
-
-  /* Whether the cache is allowed to generate machine code.  Defaults to true.
-   * There is no real reason to turn it off except for testing or if you are
-   * having a specific problem with the JIT.
-   *
-   * Note that allow_jit = true does not *guarantee* that the code will be JIT
-   * compiled.  If this platform is not supported or the JIT was not compiled
-   * in, the code may still be interpreted. */
-  bool allow_jit() const { return upb_pbcodecache_allowjit(ptr()); }
-
-  /* This may only be called when the object is first constructed, and prior to
-   * any code generation. */
-  void set_allow_jit(bool allow) { upb_pbcodecache_setallowjit(ptr(), allow); }
-
-  /* Should the decoder push submessages to lazy handlers for fields that have
-   * them?  The caller should set this iff the lazy handlers expect data that is
-   * in protobuf binary format and the caller wishes to lazy parse it. */
-  void set_lazy(bool lazy) { upb_pbcodecache_setlazy(ptr(), lazy); }
-
-  /* Returns a DecoderMethod that can push data to the given handlers.
-   * If a suitable method already exists, it will be returned from the cache. */
-  const DecoderMethodPtr Get(MessageDefPtr md) {
-    return DecoderMethodPtr(upb_pbcodecache_get(ptr(), md.ptr()));
-  }
-
- private:
-  std::unique_ptr<upb_pbcodecache, decltype(&upb_pbcodecache_free)> ptr_;
-};
-
-#endif  /* __cplusplus */
-
-#endif  /* UPB_DECODER_H_ */
-
-
-/* Opcode definitions.  The canonical meaning of each opcode is its
- * implementation in the interpreter (the JIT is written to match this).
- *
- * All instructions have the opcode in the low byte.
- * Instruction format for most instructions is:
- *
- * +-------------------+--------+
- * |     arg (24)      | op (8) |
- * +-------------------+--------+
- *
- * Exceptions are indicated below.  A few opcodes are multi-word. */
-typedef enum {
-  /* Opcodes 1-8, 13, 15-18 parse their respective descriptor types.
-   * Arg for all of these is the upb selector for this field. */
-#define T(type) OP_PARSE_ ## type = UPB_DESCRIPTOR_TYPE_ ## type
-  T(DOUBLE), T(FLOAT), T(INT64), T(UINT64), T(INT32), T(FIXED64), T(FIXED32),
-  T(BOOL), T(UINT32), T(SFIXED32), T(SFIXED64), T(SINT32), T(SINT64),
-#undef T
-  OP_STARTMSG       = 9,   /* No arg. */
-  OP_ENDMSG         = 10,  /* No arg. */
-  OP_STARTSEQ       = 11,
-  OP_ENDSEQ         = 12,
-  OP_STARTSUBMSG    = 14,
-  OP_ENDSUBMSG      = 19,
-  OP_STARTSTR       = 20,
-  OP_STRING         = 21,
-  OP_ENDSTR         = 22,
-
-  OP_PUSHTAGDELIM   = 23,  /* No arg. */
-  OP_PUSHLENDELIM   = 24,  /* No arg. */
-  OP_POP            = 25,  /* No arg. */
-  OP_SETDELIM       = 26,  /* No arg. */
-  OP_SETBIGGROUPNUM = 27,  /* two words:
-                            *   | unused (24)     | opc (8) |
-                            *   |        groupnum (32)      | */
-  OP_CHECKDELIM     = 28,
-  OP_CALL           = 29,
-  OP_RET            = 30,
-  OP_BRANCH         = 31,
-
-  /* Different opcodes depending on how many bytes expected. */
-  OP_TAG1           = 32,  /* | match tag (16) | jump target (8) | opc (8) | */
-  OP_TAG2           = 33,  /* | match tag (16) | jump target (8) | opc (8) | */
-  OP_TAGN           = 34,  /* three words: */
-                           /*   | unused (16) | jump target(8) | opc (8) | */
-                           /*   |           match tag 1 (32)             | */
-                           /*   |           match tag 2 (32)             | */
-
-  OP_SETDISPATCH    = 35,  /* N words: */
-                           /*   | unused (24)         | opc | */
-                           /*   | upb_inttable* (32 or 64)  | */
-
-  OP_DISPATCH       = 36,  /* No arg. */
-
-  OP_HALT           = 37   /* No arg. */
-} opcode;
-
-#define OP_MAX OP_HALT
-
-UPB_INLINE opcode getop(uint32_t instr) { return (opcode)(instr & 0xff); }
-
-struct upb_pbcodecache {
-  upb_arena *arena;
-  upb_handlercache *dest;
-  bool allow_jit;
-  bool lazy;
-
-  /* Map of upb_msgdef -> mgroup. */
-  upb_inttable groups;
-};
-
-/* Method group; represents a set of decoder methods that had their code
- * emitted together.  Immutable once created.  */
-typedef struct {
-  /* Maps upb_msgdef/upb_handlers -> upb_pbdecodermethod.  Owned by us.
-   *
-   * Ideally this would be on pbcodecache (if we were actually caching code).
-   * Right now we don't actually cache anything, which is wasteful. */
-  upb_inttable methods;
-
-  /* The bytecode for our methods, if any exists.  Owned by us. */
-  uint32_t *bytecode;
-  uint32_t *bytecode_end;
-} mgroup;
-
-/* The maximum that any submessages can be nested.  Matches proto2's limit.
- * This specifies the size of the decoder's statically-sized array and therefore
- * setting it high will cause the upb::pb::Decoder object to be larger.
- *
- * If necessary we can add a runtime-settable property to Decoder that allow
- * this to be larger than the compile-time setting, but this would add
- * complexity, particularly since we would have to decide how/if to give users
- * the ability to set a custom memory allocation function. */
-#define UPB_DECODER_MAX_NESTING 64
-
-/* Internal-only struct used by the decoder. */
-typedef struct {
-  /* Space optimization note: we store two pointers here that the JIT
-   * doesn't need at all; the upb_handlers* inside the sink and
-   * the dispatch table pointer.  We can optimize so that the JIT uses
-   * smaller stack frames than the interpreter.  The only thing we need
-   * to guarantee is that the fallback routines can find end_ofs. */
-  upb_sink sink;
-
-  /* The absolute stream offset of the end-of-frame delimiter.
-   * Non-delimited frames (groups and non-packed repeated fields) reuse the
-   * delimiter of their parent, even though the frame may not end there.
-   *
-   * NOTE: the JIT stores a slightly different value here for non-top frames.
-   * It stores the value relative to the end of the enclosed message.  But the
-   * top frame is still stored the same way, which is important for ensuring
-   * that calls from the JIT into C work correctly. */
-  uint64_t end_ofs;
-  const uint32_t *base;
-
-  /* 0 indicates a length-delimited field.
-   * A positive number indicates a known group.
-   * A negative number indicates an unknown group. */
-  int32_t groupnum;
-  upb_inttable *dispatch;  /* Not used by the JIT. */
-} upb_pbdecoder_frame;
-
-struct upb_pbdecodermethod {
-  /* While compiling, the base is relative in "ofs", after compiling it is
-   * absolute in "ptr". */
-  union {
-    uint32_t ofs;     /* PC offset of method. */
-    void *ptr;        /* Pointer to bytecode or machine code for this method. */
-  } code_base;
-
-  /* The decoder method group to which this method belongs. */
-  const mgroup *group;
-
-  /* Whether this method is native code or bytecode. */
-  bool is_native_;
-
-  /* The handler one calls to invoke this method. */
-  upb_byteshandler input_handler_;
-
-  /* The destination handlers this method is bound to.  We own a ref. */
-  const upb_handlers *dest_handlers_;
-
-  /* Dispatch table -- used by both bytecode decoder and JIT when encountering a
-   * field number that wasn't the one we were expecting to see.  See
-   * decoder.int.h for the layout of this table. */
-  upb_inttable dispatch;
-};
-
-struct upb_pbdecoder {
-  upb_arena *arena;
-
-  /* Our input sink. */
-  upb_bytessink input_;
-
-  /* The decoder method we are parsing with (owned). */
-  const upb_pbdecodermethod *method_;
-
-  size_t call_len;
-  const uint32_t *pc, *last;
-
-  /* Current input buffer and its stream offset. */
-  const char *buf, *ptr, *end, *checkpoint;
-
-  /* End of the delimited region, relative to ptr, NULL if not in this buf. */
-  const char *delim_end;
-
-  /* End of the delimited region, relative to ptr, end if not in this buf. */
-  const char *data_end;
-
-  /* Overall stream offset of "buf." */
-  uint64_t bufstart_ofs;
-
-  /* Buffer for residual bytes not parsed from the previous buffer. */
-  char residual[UPB_DECODER_MAX_RESIDUAL_BYTES];
-  char *residual_end;
-
-  /* Bytes of data that should be discarded from the input beore we start
-   * parsing again.  We set this when we internally determine that we can
-   * safely skip the next N bytes, but this region extends past the current
-   * user buffer. */
-  size_t skip;
-
-  /* Stores the user buffer passed to our decode function. */
-  const char *buf_param;
-  size_t size_param;
-  const upb_bufhandle *handle;
-
-  /* Our internal stack. */
-  upb_pbdecoder_frame *stack, *top, *limit;
-  const uint32_t **callstack;
-  size_t stack_size;
-
-  upb_status *status;
-};
-
-/* Decoder entry points; used as handlers. */
-void *upb_pbdecoder_startbc(void *closure, const void *pc, size_t size_hint);
-size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf,
-                            size_t size, const upb_bufhandle *handle);
-bool upb_pbdecoder_end(void *closure, const void *handler_data);
-
-/* Decoder-internal functions that the JIT calls to handle fallback paths. */
-int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf,
-                             size_t size, const upb_bufhandle *handle);
-size_t upb_pbdecoder_suspend(upb_pbdecoder *d);
-int32_t upb_pbdecoder_skipunknown(upb_pbdecoder *d, int32_t fieldnum,
-                                  uint8_t wire_type);
-int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d, uint64_t expected);
-int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d, uint64_t *u64);
-int32_t upb_pbdecoder_decode_f32(upb_pbdecoder *d, uint32_t *u32);
-int32_t upb_pbdecoder_decode_f64(upb_pbdecoder *d, uint64_t *u64);
-void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg);
-
-/* Error messages that are shared between the bytecode and JIT decoders. */
-extern const char *kPbDecoderStackOverflow;
-extern const char *kPbDecoderSubmessageTooLong;
-
-/* Access to decoderplan members needed by the decoder. */
-const char *upb_pbdecoder_getopname(unsigned int op);
-
-/* A special label that means "do field dispatch for this message and branch to
- * wherever that takes you." */
-#define LABEL_DISPATCH 0
-
-/* A special slot in the dispatch table that stores the epilogue (ENDMSG and/or
- * RET) for branching to when we find an appropriate ENDGROUP tag. */
-#define DISPATCH_ENDMSG 0
-
-/* It's important to use this invalid wire type instead of 0 (which is a valid
- * wire type). */
-#define NO_WIRE_TYPE 0xff
-
-/* The dispatch table layout is:
- *   [field number] -> [ 48-bit offset ][ 8-bit wt2 ][ 8-bit wt1 ]
- *
- * If wt1 matches, jump to the 48-bit offset.  If wt2 matches, lookup
- * (UPB_MAX_FIELDNUMBER + fieldnum) and jump there.
- *
- * We need two wire types because of packed/non-packed compatibility.  A
- * primitive repeated field can use either wire type and be valid.  While we
- * could key the table on fieldnum+wiretype, the table would be 8x sparser.
- *
- * Storing two wire types in the primary value allows us to quickly rule out
- * the second wire type without needing to do a separate lookup (this case is
- * less common than an unknown field). */
-UPB_INLINE uint64_t upb_pbdecoder_packdispatch(uint64_t ofs, uint8_t wt1,
-                                               uint8_t wt2) {
-  return (ofs << 16) | (wt2 << 8) | wt1;
-}
-
-UPB_INLINE void upb_pbdecoder_unpackdispatch(uint64_t dispatch, uint64_t *ofs,
-                                             uint8_t *wt1, uint8_t *wt2) {
-  *wt1 = (uint8_t)dispatch;
-  *wt2 = (uint8_t)(dispatch >> 8);
-  *ofs = dispatch >> 16;
-}
-
-/* All of the functions in decoder.c that return int32_t return values according
- * to the following scheme:
- *   1. negative values indicate a return code from the following list.
- *   2. positive values indicate that error or end of buffer was hit, and
- *      that the decode function should immediately return the given value
- *      (the decoder state has already been suspended and is ready to be
- *      resumed). */
-#define DECODE_OK -1
-#define DECODE_MISMATCH -2  /* Used only from checktag_slow(). */
-#define DECODE_ENDGROUP -3  /* Used only from checkunknown(). */
-
-#define CHECK_RETURN(x) { int32_t ret = x; if (ret >= 0) return ret; }
-
-
-#endif  /* UPB_DECODER_INT_H_ */
-/*
-** A number of routines for varint manipulation (we keep them all around to
-** have multiple approaches available for benchmarking).
-*/
-
-#ifndef UPB_VARINT_DECODER_H_
-#define UPB_VARINT_DECODER_H_
-
-#include <assert.h>
-#include <stdint.h>
-#include <string.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define UPB_MAX_WIRE_TYPE 5
-
-/* The maximum number of bytes that it takes to encode a 64-bit varint. */
-#define UPB_PB_VARINT_MAX_LEN 10
-
-/* Array of the "native" (ie. non-packed-repeated) wire type for the given a
- * descriptor type (upb_descriptortype_t). */
-extern const uint8_t upb_pb_native_wire_types[];
-
-UPB_INLINE uint64_t byteswap64(uint64_t val) {
-  uint64_t byte = 0xff;
-  return (val & (byte << 56) >> 56)
-    | (val & (byte << 48) >> 40)
-    | (val & (byte << 40) >> 24)
-    | (val & (byte << 32) >> 8)
-    | (val & (byte << 24) << 8)
-    | (val & (byte << 16) << 24)
-    | (val & (byte <<  8) << 40)
-    | (val & (byte <<  0) << 56);
-}
-
-/* Zig-zag encoding/decoding **************************************************/
-
-UPB_INLINE int32_t upb_zzdec_32(uint64_t _n) {
-  uint32_t n = (uint32_t)_n;
-  return (n >> 1) ^ -(int32_t)(n & 1);
-}
-UPB_INLINE int64_t upb_zzdec_64(uint64_t n) {
-  return (n >> 1) ^ -(int64_t)(n & 1);
-}
-UPB_INLINE uint32_t upb_zzenc_32(int32_t n) {
-  return ((uint32_t)n << 1) ^ (n >> 31);
-}
-UPB_INLINE uint64_t upb_zzenc_64(int64_t n) {
-  return ((uint64_t)n << 1) ^ (n >> 63);
-}
-
-/* Decoding *******************************************************************/
-
-/* All decoding functions return this struct by value. */
-typedef struct {
-  const char *p;  /* NULL if the varint was unterminated. */
-  uint64_t val;
-} upb_decoderet;
-
-UPB_INLINE upb_decoderet upb_decoderet_make(const char *p, uint64_t val) {
-  upb_decoderet ret;
-  ret.p = p;
-  ret.val = val;
-  return ret;
-}
-
-upb_decoderet upb_vdecode_max8_branch32(upb_decoderet r);
-upb_decoderet upb_vdecode_max8_branch64(upb_decoderet r);
-
-/* Template for a function that checks the first two bytes with branching
- * and dispatches 2-10 bytes with a separate function.  Note that this may read
- * up to 10 bytes, so it must not be used unless there are at least ten bytes
- * left in the buffer! */
-#define UPB_VARINT_DECODER_CHECK2(name, decode_max8_function)                  \
-UPB_INLINE upb_decoderet upb_vdecode_check2_ ## name(const char *_p) {         \
-  uint8_t *p = (uint8_t*)_p;                                                   \
-  upb_decoderet r;                                                             \
-  if ((*p & 0x80) == 0) {                                                      \
-  /* Common case: one-byte varint. */                                          \
-    return upb_decoderet_make(_p + 1, *p & 0x7fU);                             \
-  }                                                                            \
-  r = upb_decoderet_make(_p + 2, (*p & 0x7fU) | ((*(p + 1) & 0x7fU) << 7));    \
-  if ((*(p + 1) & 0x80) == 0) {                                                \
-    /* Two-byte varint. */                                                     \
-    return r;                                                                  \
-  }                                                                            \
-  /* Longer varint, fallback to out-of-line function. */                       \
-  return decode_max8_function(r);                                              \
-}
-
-UPB_VARINT_DECODER_CHECK2(branch32, upb_vdecode_max8_branch32)
-UPB_VARINT_DECODER_CHECK2(branch64, upb_vdecode_max8_branch64)
-#undef UPB_VARINT_DECODER_CHECK2
-
-/* Our canonical functions for decoding varints, based on the currently
- * favored best-performing implementations. */
-UPB_INLINE upb_decoderet upb_vdecode_fast(const char *p) {
-  if (sizeof(long) == 8)
-    return upb_vdecode_check2_branch64(p);
-  else
-    return upb_vdecode_check2_branch32(p);
-}
-
-
-/* Encoding *******************************************************************/
-
-UPB_INLINE int upb_value_size(uint64_t val) {
-#ifdef __GNUC__
-  int high_bit = 63 - __builtin_clzll(val);  /* 0-based, undef if val == 0. */
-#else
-  int high_bit = 0;
-  uint64_t tmp = val;
-  while(tmp >>= 1) high_bit++;
-#endif
-  return val == 0 ? 1 : high_bit / 8 + 1;
-}
-
-/* Encodes a 64-bit varint into buf (which must be >=UPB_PB_VARINT_MAX_LEN
- * bytes long), returning how many bytes were used.
- *
- * TODO: benchmark and optimize if necessary. */
-UPB_INLINE size_t upb_vencode64(uint64_t val, char *buf) {
-  size_t i;
-  if (val == 0) { buf[0] = 0; return 1; }
-  i = 0;
-  while (val) {
-    uint8_t byte = val & 0x7fU;
-    val >>= 7;
-    if (val) byte |= 0x80U;
-    buf[i++] = byte;
-  }
-  return i;
-}
-
-UPB_INLINE size_t upb_varint_size(uint64_t val) {
-  char buf[UPB_PB_VARINT_MAX_LEN];
-  return upb_vencode64(val, buf);
-}
-
-/* Encodes a 32-bit varint, *not* sign-extended. */
-UPB_INLINE uint64_t upb_vencode32(uint32_t val) {
-  char buf[UPB_PB_VARINT_MAX_LEN];
-  size_t bytes = upb_vencode64(val, buf);
-  uint64_t ret = 0;
-  UPB_ASSERT(bytes <= 5);
-  memcpy(&ret, buf, bytes);
-#ifdef UPB_BIG_ENDIAN
-  ret = byteswap64(ret);
-#endif
-  UPB_ASSERT(ret <= 0xffffffffffU);
-  return ret;
-}
-
-#ifdef __cplusplus
-}  /* extern "C" */
-#endif
-
-
-#endif  /* UPB_VARINT_DECODER_H_ */
-/*
-** upb::pb::Encoder (upb_pb_encoder)
-**
-** Implements a set of upb_handlers that write protobuf data to the binary wire
-** format.
-**
-** This encoder implementation does not have any access to any out-of-band or
-** precomputed lengths for submessages, so it must buffer submessages internally
-** before it can emit the first byte.
-*/
-
-#ifndef UPB_ENCODER_H_
-#define UPB_ENCODER_H_
-
-
-#ifdef __cplusplus
-namespace upb {
-namespace pb {
-class EncoderPtr;
-}  /* namespace pb */
-}  /* namespace upb */
-#endif
-
-#define UPB_PBENCODER_MAX_NESTING 100
-
-/* upb_pb_encoder *************************************************************/
-
-/* Preallocation hint: decoder won't allocate more bytes than this when first
- * constructed.  This hint may be an overestimate for some build configurations.
- * But if the decoder library is upgraded without recompiling the application,
- * it may be an underestimate. */
-#define UPB_PB_ENCODER_SIZE 784
-
-struct upb_pb_encoder;
-typedef struct upb_pb_encoder upb_pb_encoder;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-upb_sink upb_pb_encoder_input(upb_pb_encoder *p);
-upb_pb_encoder* upb_pb_encoder_create(upb_arena* a, const upb_handlers* h,
-                                      upb_bytessink output);
-
-/* Lazily builds and caches handlers that will push encoded data to a bytessink.
- * Any msgdef objects used with this object must outlive it. */
-upb_handlercache *upb_pb_encoder_newcache(void);
-
-#ifdef __cplusplus
-}  /* extern "C" { */
-
-class upb::pb::EncoderPtr {
- public:
-  EncoderPtr(upb_pb_encoder* ptr) : ptr_(ptr) {}
-
-  upb_pb_encoder* ptr() { return ptr_; }
-
-  /* Creates a new encoder in the given environment.  The Handlers must have
-   * come from NewHandlers() below. */
-  static EncoderPtr Create(Arena* arena, const Handlers* handlers,
-                           BytesSink output) {
-    return EncoderPtr(
-        upb_pb_encoder_create(arena->ptr(), handlers, output.sink()));
-  }
-
-  /* The input to the encoder. */
-  upb::Sink input() { return upb_pb_encoder_input(ptr()); }
-
-  /* Creates a new set of handlers for this MessageDef. */
-  static HandlerCache NewCache() {
-    return HandlerCache(upb_pb_encoder_newcache());
-  }
-
-  static const size_t kSize = UPB_PB_ENCODER_SIZE;
-
- private:
-  upb_pb_encoder* ptr_;
-};
-
-#endif  /* __cplusplus */
-
-#endif  /* UPB_ENCODER_H_ */
-/*
-** upb::pb::TextPrinter (upb_textprinter)
-**
-** Handlers for writing to protobuf text format.
-*/
-
-#ifndef UPB_TEXT_H_
-#define UPB_TEXT_H_
-
-
-#ifdef __cplusplus
-namespace upb {
-namespace pb {
-class TextPrinterPtr;
-}  /* namespace pb */
-}  /* namespace upb */
-#endif
-
-/* upb_textprinter ************************************************************/
-
-struct upb_textprinter;
-typedef struct upb_textprinter upb_textprinter;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* C API. */
-upb_textprinter *upb_textprinter_create(upb_arena *arena, const upb_handlers *h,
-                                        upb_bytessink output);
-void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line);
-upb_sink upb_textprinter_input(upb_textprinter *p);
-upb_handlercache *upb_textprinter_newcache(void);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-class upb::pb::TextPrinterPtr {
- public:
-  TextPrinterPtr(upb_textprinter* ptr) : ptr_(ptr) {}
-
-  /* The given handlers must have come from NewHandlers().  It must outlive the
-   * TextPrinter. */
-  static TextPrinterPtr Create(Arena *arena, upb::HandlersPtr *handlers,
-                               BytesSink output) {
-    return TextPrinterPtr(
-        upb_textprinter_create(arena->ptr(), handlers->ptr(), output.sink()));
-  }
-
-  void SetSingleLineMode(bool single_line) {
-    upb_textprinter_setsingleline(ptr_, single_line);
-  }
-
-  Sink input() { return upb_textprinter_input(ptr_); }
-
-  /* If handler caching becomes a requirement we can add a code cache as in
-   * decoder.h */
-  static HandlerCache NewCache() {
-    return HandlerCache(upb_textprinter_newcache());
-  }
-
- private:
-  upb_textprinter* ptr_;
-};
-
-#endif
-
-#endif  /* UPB_TEXT_H_ */
-/*
-** upb::json::Parser (upb_json_parser)
-**
-** Parses JSON according to a specific schema.
-** Support for parsing arbitrary JSON (schema-less) will be added later.
-*/
-
-#ifndef UPB_JSON_PARSER_H_
-#define UPB_JSON_PARSER_H_
-
-
-#ifdef __cplusplus
-namespace upb {
-namespace json {
-class CodeCache;
-class ParserPtr;
-class ParserMethodPtr;
-}  /* namespace json */
-}  /* namespace upb */
-#endif
-
-/* upb_json_parsermethod ******************************************************/
-
-struct upb_json_parsermethod;
-typedef struct upb_json_parsermethod upb_json_parsermethod;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-const upb_byteshandler* upb_json_parsermethod_inputhandler(
-    const upb_json_parsermethod* m);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-class upb::json::ParserMethodPtr {
- public:
-  ParserMethodPtr() : ptr_(nullptr) {}
-  ParserMethodPtr(const upb_json_parsermethod* ptr) : ptr_(ptr) {}
-
-  const upb_json_parsermethod* ptr() const { return ptr_; }
-
-  const BytesHandler* input_handler() const {
-    return upb_json_parsermethod_inputhandler(ptr());
-  }
-
- private:
-  const upb_json_parsermethod* ptr_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_json_parser ************************************************************/
-
-/* Preallocation hint: parser won't allocate more bytes than this when first
- * constructed.  This hint may be an overestimate for some build configurations.
- * But if the parser library is upgraded without recompiling the application,
- * it may be an underestimate. */
-#define UPB_JSON_PARSER_SIZE 5712
-
-struct upb_json_parser;
-typedef struct upb_json_parser upb_json_parser;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-upb_json_parser* upb_json_parser_create(upb_arena* a,
-                                        const upb_json_parsermethod* m,
-                                        const upb_symtab* symtab,
-                                        upb_sink output,
-                                        upb_status *status,
-                                        bool ignore_json_unknown);
-upb_bytessink upb_json_parser_input(upb_json_parser* p);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* Parses an incoming BytesStream, pushing the results to the destination
- * sink. */
-class upb::json::ParserPtr {
- public:
-  ParserPtr(upb_json_parser* ptr) : ptr_(ptr) {}
-
-  static ParserPtr Create(Arena* arena, ParserMethodPtr method,
-                          SymbolTable* symtab, Sink output, Status* status,
-                          bool ignore_json_unknown) {
-    upb_symtab* symtab_ptr = symtab ? symtab->ptr() : nullptr;
-    return ParserPtr(upb_json_parser_create(
-        arena->ptr(), method.ptr(), symtab_ptr, output.sink(), status->ptr(),
-        ignore_json_unknown));
-  }
-
-  BytesSink input() { return upb_json_parser_input(ptr_); }
-
- private:
-  upb_json_parser* ptr_;
-};
-
-#endif  /* __cplusplus */
-
-/* upb_json_codecache *********************************************************/
-
-/* Lazily builds and caches decoder methods that will push data to the given
- * handlers.  The upb_symtab object(s) must outlive this object. */
-
-struct upb_json_codecache;
-typedef struct upb_json_codecache upb_json_codecache;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-upb_json_codecache *upb_json_codecache_new(void);
-void upb_json_codecache_free(upb_json_codecache *cache);
-const upb_json_parsermethod* upb_json_codecache_get(upb_json_codecache* cache,
-                                                    const upb_msgdef* md);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-class upb::json::CodeCache {
- public:
-  CodeCache() : ptr_(upb_json_codecache_new(), upb_json_codecache_free) {}
-
-  /* Returns a DecoderMethod that can push data to the given handlers.
-   * If a suitable method already exists, it will be returned from the cache. */
-  ParserMethodPtr Get(MessageDefPtr md) {
-    return upb_json_codecache_get(ptr_.get(), md.ptr());
-  }
-
- private:
-  std::unique_ptr<upb_json_codecache, decltype(&upb_json_codecache_free)> ptr_;
-};
-
-#endif
-
-#endif  /* UPB_JSON_PARSER_H_ */
-/*
-** upb::json::Printer
-**
-** Handlers that emit JSON according to a specific protobuf schema.
-*/
-
-#ifndef UPB_JSON_TYPED_PRINTER_H_
-#define UPB_JSON_TYPED_PRINTER_H_
-
-
-#ifdef __cplusplus
-namespace upb {
-namespace json {
-class PrinterPtr;
-}  /* namespace json */
-}  /* namespace upb */
-#endif
-
-/* upb_json_printer ***********************************************************/
-
-#define UPB_JSON_PRINTER_SIZE 192
-
-struct upb_json_printer;
-typedef struct upb_json_printer upb_json_printer;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Native C API. */
-upb_json_printer *upb_json_printer_create(upb_arena *a, const upb_handlers *h,
-                                          upb_bytessink output);
-upb_sink upb_json_printer_input(upb_json_printer *p);
-const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md,
-                                                 bool preserve_fieldnames,
-                                                 const void *owner);
-
-/* Lazily builds and caches handlers that will push encoded data to a bytessink.
- * Any msgdef objects used with this object must outlive it. */
-upb_handlercache *upb_json_printer_newcache(bool preserve_proto_fieldnames);
-
-#ifdef __cplusplus
-}  /* extern "C" */
-
-/* Prints an incoming stream of data to a BytesSink in JSON format. */
-class upb::json::PrinterPtr {
- public:
-  PrinterPtr(upb_json_printer* ptr) : ptr_(ptr) {}
-
-  static PrinterPtr Create(Arena *arena, const upb::Handlers *handlers,
-                           BytesSink output) {
-    return PrinterPtr(
-        upb_json_printer_create(arena->ptr(), handlers, output.sink()));
-  }
-
-  /* The input to the printer. */
-  Sink input() { return upb_json_printer_input(ptr_); }
-
-  static const size_t kSize = UPB_JSON_PRINTER_SIZE;
-
-  static HandlerCache NewCache(bool preserve_proto_fieldnames) {
-    return upb_json_printer_newcache(preserve_proto_fieldnames);
-  }
-
- private:
-  upb_json_printer* ptr_;
-};
-
-#endif  /* __cplusplus */
-
-#endif  /* UPB_JSON_TYPED_PRINTER_H_ */
-/* See port_def.inc.  This should #undef all macros #defined there. */
-
-#undef UPB_MAPTYPE_STRING
-#undef UPB_SIZE
-#undef UPB_PTR_AT
-#undef UPB_READ_ONEOF
-#undef UPB_WRITE_ONEOF
-#undef UPB_INLINE
-#undef UPB_FORCEINLINE
-#undef UPB_NOINLINE
-#undef UPB_NORETURN
-#undef UPB_MAX
-#undef UPB_MIN
-#undef UPB_UNUSED
-#undef UPB_ASSUME
-#undef UPB_ASSERT
-#undef UPB_ASSERT_DEBUGVAR
-#undef UPB_UNREACHABLE
-#undef UPB_INFINITY
-#undef UPB_MSVC_VSNPRINTF
-#undef _upb_snprintf
-#undef _upb_vsnprintf
-#undef _upb_va_copy
diff --git a/ruby/google-protobuf.gemspec b/ruby/google-protobuf.gemspec
index 1a18da3..4852f7d 100644
--- a/ruby/google-protobuf.gemspec
+++ b/ruby/google-protobuf.gemspec
@@ -17,7 +17,7 @@
   else
     s.files     += Dir.glob('ext/**/*')
     s.extensions= ["ext/google/protobuf_c/extconf.rb"]
-    s.add_development_dependency "rake-compiler-dock", ">= 1.0.1", "< 2.0"
+    s.add_development_dependency "rake-compiler-dock", ">= 1.1.0", "< 2.0"
   end
   s.test_files  = ["tests/basic.rb",
                   "tests/stress.rb",
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyFileBuilderContext.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyFileBuilderContext.java
index 7d90be1..00ce3f2 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyFileBuilderContext.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyFileBuilderContext.java
@@ -52,6 +52,7 @@
 
 import java.util.HashMap;
 import java.util.List;
+import java.util.TreeMap;
 
 @JRubyClass(name = "FileBuilderContext")
 public class RubyFileBuilderContext extends RubyObject {
@@ -154,7 +155,7 @@
         }
 
         // Make an index of the message builders so we can easily nest them
-        HashMap<String, DescriptorProto.Builder> messageBuilderMap = new HashMap();
+        TreeMap<String, DescriptorProto.Builder> messageBuilderMap = new TreeMap();
         for (DescriptorProto.Builder messageBuilder : messageBuilderList) {
             messageBuilderMap.put(messageBuilder.getName(), messageBuilder);
         }
@@ -176,7 +177,6 @@
         EnumDescriptorProto.Builder[] enumBuilders = new EnumDescriptorProto.Builder[enumBuilderList.size()];
         enumBuilderList.toArray(enumBuilders);
 
-
         for (EnumDescriptorProto.Builder enumBuilder : enumBuilders) {
             String name = enumBuilder.getName();
             int lastDot = name.lastIndexOf('.');
@@ -216,28 +216,17 @@
             }
         }
 
-        for (DescriptorProto.Builder messageBuilder : messageBuilders) {
-            String name = messageBuilder.getName();
-            int lastDot = name.lastIndexOf('.');
+        // Wipe out top level message builders so we can insert only the ones that should be there
+        builder.clearMessageType();
 
-            if (lastDot > packageNameLength) {
-                String parentName = name.substring(0, lastDot);
-                String shortName = name.substring(lastDot + 1);
-
-                messageBuilder.setName(shortName);
-                messageBuilderMap.get(parentName).addNestedType(messageBuilder);
-
-                builder.removeMessageType(currentMessageIndex);
-
-            } else {
-                if (packageNameLength > 0) {
-                    // Remove the package name
-                    String shortName = name.substring(packageNameLength + 1);
-                    messageBuilder.setName(shortName);
-                }
-
-                currentMessageIndex++;
-            }
+        /*
+         * This block is done in this order because calling
+         * `addNestedType` and `addMessageType` makes a copy of the builder
+         * so the objects that our maps point to are no longer the objects
+         * that are being used to build the descriptions.
+         */
+        for (HashMap.Entry<String, DescriptorProto.Builder> entry : messageBuilderMap.descendingMap().entrySet()) {
+            DescriptorProto.Builder messageBuilder = entry.getValue();
 
             // Rewrite any enum defaults needed
             for(FieldDescriptorProto.Builder field : messageBuilder.getFieldBuilderList()) {
@@ -258,6 +247,28 @@
                     }
                 }
             }
+
+            // Turn Foo.Bar.Baz into a correctly nested structure with the correct name
+            String name = messageBuilder.getName();
+            int lastDot = name.lastIndexOf('.');
+
+            if (lastDot > packageNameLength) {
+                String parentName = name.substring(0, lastDot);
+                String shortName = name.substring(lastDot + 1);
+                messageBuilder.setName(shortName);
+                messageBuilderMap.get(parentName).addNestedType(messageBuilder);
+
+            } else {
+                if (packageNameLength > 0) {
+                    // Remove the package name
+                    messageBuilder.setName(name.substring(packageNameLength + 1));
+                }
+
+                // Add back in top level message definitions
+                builder.addMessageType(messageBuilder);
+
+                currentMessageIndex++;
+            }
         }
 
         descriptorPool.registerFileDescriptor(context, builder);
diff --git a/ruby/tests/basic.rb b/ruby/tests/basic.rb
index 60a7050..098ac41 100755
--- a/ruby/tests/basic.rb
+++ b/ruby/tests/basic.rb
@@ -216,7 +216,7 @@
         m.map_string_int32 = {}
       end
 
-      assert_raise TypeError do
+      assert_raise Google::Protobuf::TypeError do
         m = MapMessage.new(:map_string_int32 => { 1 => "I am not a number" })
       end
     end
@@ -447,6 +447,7 @@
         :optional_int32=>0,
         :optional_int64=>0,
         :optional_msg=>nil,
+        :optional_msg2=>nil,
         :optional_string=>"foo",
         :optional_uint32=>0,
         :optional_uint64=>0,
@@ -484,9 +485,9 @@
       m = MapMessage.new(:map_string_int32 => {"a" => 1})
       expected = {mapStringInt32: {a: 1}, mapStringMsg: {}, mapStringEnum: {}}
       expected_preserve = {map_string_int32: {a: 1}, map_string_msg: {}, map_string_enum: {}}
-      assert_equal JSON.parse(MapMessage.encode_json(m), :symbolize_names => true), expected
+      assert_equal JSON.parse(MapMessage.encode_json(m, :emit_defaults=>true), :symbolize_names => true), expected
 
-      json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true)
+      json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true, :emit_defaults=>true)
       assert_equal JSON.parse(json, :symbolize_names => true), expected_preserve
 
       m2 = MapMessage.decode_json(MapMessage.encode_json(m))
@@ -496,7 +497,7 @@
     def test_json_maps_emit_defaults_submsg
       # TODO: Fix JSON in JRuby version.
       return if RUBY_PLATFORM == "java"
-      m = MapMessage.new(:map_string_msg => {"a" => TestMessage2.new})
+      m = MapMessage.new(:map_string_msg => {"a" => TestMessage2.new(foo: 0)})
       expected = {mapStringInt32: {}, mapStringMsg: {a: {foo: 0}}, mapStringEnum: {}}
 
       actual = MapMessage.encode_json(m, :emit_defaults => true)
@@ -504,6 +505,30 @@
       assert_equal JSON.parse(actual, :symbolize_names => true), expected
     end
 
+    def test_json_emit_defaults_submsg
+      # TODO: Fix JSON in JRuby version.
+      return if RUBY_PLATFORM == "java"
+      m = TestSingularFields.new(singular_msg: proto_module::TestMessage2.new)
+
+      expected = {
+        singularInt32: 0,
+        singularInt64: "0",
+        singularUint32: 0,
+        singularUint64: "0",
+        singularBool: false,
+        singularFloat: 0,
+        singularDouble: 0,
+        singularString: "",
+        singularBytes: "",
+        singularMsg: {},
+        singularEnum: "Default",
+      }
+
+      actual = proto_module::TestMessage.encode_json(m, :emit_defaults => true)
+
+      assert_equal expected, JSON.parse(actual, :symbolize_names => true)
+    end
+
     def test_respond_to
       # This test fails with JRuby 1.7.23, likely because of an old JRuby bug.
       return if RUBY_PLATFORM == "java"
diff --git a/ruby/tests/basic_proto2.rb b/ruby/tests/basic_proto2.rb
index 2d30a08..a7114ea 100755
--- a/ruby/tests/basic_proto2.rb
+++ b/ruby/tests/basic_proto2.rb
@@ -237,23 +237,6 @@
       assert_equal expected_result, m.to_h
     end
 
-    def test_map_keyword_disabled
-      pool = Google::Protobuf::DescriptorPool.new
-
-      e = assert_raise ArgumentError do
-        pool.build do
-          add_file 'test_file.proto', syntax: :proto2 do
-            add_message "MapMessage" do
-              map :map_string_int32, :string, :int32, 1
-              map :map_string_msg, :string, :message, 2, "TestMessage2"
-            end
-          end
-        end
-      end
-
-      assert_match(/Cannot add a native map/, e.message)
-    end
-
     def test_respond_to
       # This test fails with JRuby 1.7.23, likely because of an old JRuby bug.
       return if RUBY_PLATFORM == "java"
diff --git a/ruby/tests/basic_test.proto b/ruby/tests/basic_test.proto
index 6086879..5b4ed63 100644
--- a/ruby/tests/basic_test.proto
+++ b/ruby/tests/basic_test.proto
@@ -44,6 +44,8 @@
   repeated bytes repeated_bytes = 20;
   repeated TestMessage2 repeated_msg = 21;
   repeated TestEnum repeated_enum = 22;
+
+  optional TestSingularFields optional_msg2 = 23;
 }
 
 message TestSingularFields {
@@ -61,7 +63,7 @@
 }
 
 message TestMessage2 {
-  int32 foo = 1;
+  optional int32 foo = 1;
 }
 
 enum TestEnum {
diff --git a/ruby/tests/common_tests.rb b/ruby/tests/common_tests.rb
index 1f5013a..589934b 100644
--- a/ruby/tests/common_tests.rb
+++ b/ruby/tests/common_tests.rb
@@ -115,14 +115,14 @@
     m = proto_module::TestMessage.new(
       :optional_int32 => -42,
       :optional_enum => :A,
-      :optional_msg => proto_module::TestMessage2.new,
+      :optional_msg => proto_module::TestMessage2.new(foo: 0),
       :repeated_string => ["hello", "there", "world"])
-    expected = "<#{proto_module}::TestMessage: optional_int32: -42, optional_int64: 0, optional_uint32: 0, optional_uint64: 0, optional_bool: false, optional_float: 0.0, optional_double: 0.0, optional_string: \"\", optional_bytes: \"\", optional_msg: <#{proto_module}::TestMessage2: foo: 0>, optional_enum: :A, repeated_int32: [], repeated_int64: [], repeated_uint32: [], repeated_uint64: [], repeated_bool: [], repeated_float: [], repeated_double: [], repeated_string: [\"hello\", \"there\", \"world\"], repeated_bytes: [], repeated_msg: [], repeated_enum: []>"
+    expected = "<#{proto_module}::TestMessage: optional_int32: -42, optional_msg: <#{proto_module}::TestMessage2: foo: 0>, optional_enum: :A, repeated_int32: [], repeated_int64: [], repeated_uint32: [], repeated_uint64: [], repeated_bool: [], repeated_float: [], repeated_double: [], repeated_string: [\"hello\", \"there\", \"world\"], repeated_bytes: [], repeated_msg: [], repeated_enum: []>"
     assert_equal expected, m.inspect
     assert_equal expected, m.to_s
 
     m = proto_module::OneofMessage.new(:b => -42)
-    expected = "<#{proto_module}::OneofMessage: a: \"\", b: -42, c: nil, d: :Default>"
+    expected = "<#{proto_module}::OneofMessage: b: -42>"
     assert_equal expected, m.inspect
     assert_equal expected, m.to_s
   end
@@ -428,7 +428,7 @@
     assert m.length == 0
     assert m == {}
 
-    assert_raise TypeError do
+    assert_raise Google::Protobuf::TypeError do
       m[1] = 1
     end
     assert_raise RangeError do
@@ -492,7 +492,7 @@
 
     m = Google::Protobuf::Map.new(:string, :int32)
     m["asdf"] = 1
-    assert_raise TypeError do
+    assert_raise Google::Protobuf::TypeError do
       m[1] = 1
     end
     assert_raise Encoding::UndefinedConversionError do
@@ -505,7 +505,7 @@
     m[bytestring] = 1
     # Allowed -- we will automatically convert to ASCII-8BIT.
     m["asdf"] = 1
-    assert_raise TypeError do
+    assert_raise Google::Protobuf::TypeError do
       m[1] = 1
     end
   end
@@ -547,6 +547,7 @@
         "b" => proto_module::TestMessage.new(:optional_int32 => 84) })
 
     m2 = m.dup
+    assert m.to_h == m2.to_h
     assert m == m2
     assert m.object_id != m2.object_id
     assert m["a"].object_id == m2["a"].object_id
@@ -1103,16 +1104,6 @@
     m = proto_module::TestMessage.new
 
     expected = {
-      optionalInt32: 0,
-      optionalInt64: "0",
-      optionalUint32: 0,
-      optionalUint64: "0",
-      optionalBool: false,
-      optionalFloat: 0,
-      optionalDouble: 0,
-      optionalString: "",
-      optionalBytes: "",
-      optionalEnum: "Default",
       repeatedInt32: [],
       repeatedInt64: [],
       repeatedUint32: [],
@@ -1137,17 +1128,7 @@
     m = proto_module::TestMessage.new(optional_msg: proto_module::TestMessage2.new)
 
     expected = {
-      optionalInt32: 0,
-      optionalInt64: "0",
-      optionalUint32: 0,
-      optionalUint64: "0",
-      optionalBool: false,
-      optionalFloat: 0,
-      optionalDouble: 0,
-      optionalString: "",
-      optionalBytes: "",
-      optionalMsg: {foo: 0},
-      optionalEnum: "Default",
+      optionalMsg: {},
       repeatedInt32: [],
       repeatedInt64: [],
       repeatedUint32: [],
@@ -1172,16 +1153,6 @@
     m = proto_module::TestMessage.new(repeated_msg: [proto_module::TestMessage2.new])
 
     expected = {
-      optionalInt32: 0,
-      optionalInt64: "0",
-      optionalUint32: 0,
-      optionalUint64: "0",
-      optionalBool: false,
-      optionalFloat: 0,
-      optionalDouble: 0,
-      optionalString: "",
-      optionalBytes: "",
-      optionalEnum: "Default",
       repeatedInt32: [],
       repeatedInt64: [],
       repeatedUint32: [],
@@ -1191,7 +1162,7 @@
       repeatedDouble: [],
       repeatedString: [],
       repeatedBytes: [],
-      repeatedMsg: [{foo: 0}],
+      repeatedMsg: [{}],
       repeatedEnum: []
     }
 
@@ -1256,8 +1227,9 @@
     assert_equal json, struct.to_json
 
     assert_raise(RuntimeError, "Maximum recursion depth exceeded during encoding") do
-      proto_module::MyRepeatedStruct.encode(
-        proto_module::MyRepeatedStruct.new(structs: [proto_module::MyStruct.new(struct: struct)]))
+      struct = Google::Protobuf::Struct.new
+      struct.fields["foobar"] = Google::Protobuf::Value.new(struct_value: struct)
+      Google::Protobuf::Struct.encode(struct)
     end
   end
 
@@ -1786,4 +1758,25 @@
     assert m1.hash != m2.hash
     assert_nil h[m2]
   end
+
+  def test_object_gc
+    m = proto_module::TestMessage.new(optional_msg: proto_module::TestMessage2.new)
+    m.optional_msg
+    GC.start(full_mark: true, immediate_sweep: true)
+    m.optional_msg.inspect
+  end
+
+  def test_object_gc_freeze
+    m = proto_module::TestMessage.new
+    m.repeated_float.freeze
+    GC.start(full_mark: true)
+
+    # Make sure we remember that the object is frozen.
+    # The wrapper object contains this information, so we need to ensure that
+    # the previous GC did not collect it.
+    assert m.repeated_float.frozen?
+
+    GC.start(full_mark: true, immediate_sweep: true)
+    assert m.repeated_float.frozen?
+  end
 end
diff --git a/ruby/tests/multi_level_nesting_test.proto b/ruby/tests/multi_level_nesting_test.proto
new file mode 100644
index 0000000..84c3fa4
--- /dev/null
+++ b/ruby/tests/multi_level_nesting_test.proto
@@ -0,0 +1,19 @@
+syntax = "proto3";
+
+message Function {
+  string name = 1;
+  repeated Function.Parameter parameters = 2;
+  string return_type = 3;
+
+  message Parameter {
+    string name = 1;
+    Function.Parameter.Value value = 2;
+
+    message Value {
+      oneof type {
+        string string = 1;
+        int64 integer = 2;
+      }
+    }
+  }
+}
diff --git a/ruby/tests/multi_level_nesting_test.rb b/ruby/tests/multi_level_nesting_test.rb
new file mode 100644
index 0000000..7e5d0ec
--- /dev/null
+++ b/ruby/tests/multi_level_nesting_test.rb
@@ -0,0 +1,20 @@
+#!/usr/bin/ruby
+
+# multi_level_nesting_test_pb.rb is in the same directory as this test.
+$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
+
+require 'test/unit'
+require 'multi_level_nesting_test_pb'
+
+#
+# Provide tests for having messages nested 3 levels deep
+#
+class MultiLevelNestingTest < Test::Unit::TestCase
+
+  def test_levels_exist
+    assert ::Google::Protobuf::DescriptorPool.generated_pool.lookup("Function").msgclass
+    assert ::Google::Protobuf::DescriptorPool.generated_pool.lookup("Function.Parameter").msgclass
+    assert ::Google::Protobuf::DescriptorPool.generated_pool.lookup("Function.Parameter.Value").msgclass
+  end
+
+end
diff --git a/ruby/travis-test.sh b/ruby/travis-test.sh
index 513c0ec..faf0f9d 100755
--- a/ruby/travis-test.sh
+++ b/ruby/travis-test.sh
@@ -18,7 +18,7 @@
        rake gc_test &&
        cd ../conformance && make test_jruby &&
        cd ../ruby/compatibility_tests/v3.0.0 && ./test.sh"
-  elif [ "$version" == "ruby-2.6.0" -o "$version" == "ruby-2.7.0" ] ; then
+  elif [ "$version" == "ruby-2.6.0" -o "$version" == "ruby-2.7.0" -o "$version" == "ruby-3.0.0" ] ; then
     bash --login -c \
       "rvm install $version && rvm use $version && \
        which ruby && \
diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc
index c421045..dea9cd6 100644
--- a/src/google/protobuf/any.pb.cc
+++ b/src/google/protobuf/any.pb.cc
@@ -17,24 +17,21 @@
 
 PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class AnyDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Any> _instance;
-} _Any_default_instance_;
+constexpr Any::Any(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : type_url_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , _any_metadata_(&type_url_, &value_){}
+struct AnyDefaultTypeInternal {
+  constexpr AnyDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~AnyDefaultTypeInternal() {}
+  union {
+    Any _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY AnyDefaultTypeInternal _Any_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_Any_google_2fprotobuf_2fany_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Any_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Any();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Any_google_2fprotobuf_2fany_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Any_google_2fprotobuf_2fany_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fany_2eproto[1];
 static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fany_2eproto = nullptr;
@@ -64,18 +61,18 @@
   "anypb\242\002\003GPB\252\002\036Google.Protobuf.WellKnownT"
   "ypesb\006proto3"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fany_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fany_2eproto_sccs[1] = {
-  &scc_info_Any_google_2fprotobuf_2fany_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fany_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fany_2eproto, "google/protobuf/any.proto", 212,
-  &descriptor_table_google_2fprotobuf_2fany_2eproto_once, descriptor_table_google_2fprotobuf_2fany_2eproto_sccs, descriptor_table_google_2fprotobuf_2fany_2eproto_deps, 1, 0,
+  false, false, 212, descriptor_table_protodef_google_2fprotobuf_2fany_2eproto, "google/protobuf/any.proto", 
+  &descriptor_table_google_2fprotobuf_2fany_2eproto_once, nullptr, 0, 1,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fany_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fany_2eproto, 1, file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto, file_level_service_descriptors_google_2fprotobuf_2fany_2eproto,
+  file_level_metadata_google_2fprotobuf_2fany_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto, file_level_service_descriptors_google_2fprotobuf_2fany_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
+descriptor_table_google_2fprotobuf_2fany_2eproto_metadata_getter(int index) {
+  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fany_2eproto);
+  return descriptor_table_google_2fprotobuf_2fany_2eproto.file_level_metadata[index];
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
 PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fany_2eproto(&descriptor_table_google_2fprotobuf_2fany_2eproto);
@@ -126,9 +123,8 @@
 }
 
 void Any::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Any_google_2fprotobuf_2fany_2eproto.base);
-  type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
 Any::~Any() {
@@ -152,11 +148,6 @@
 void Any::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Any& Any::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Any_google_2fprotobuf_2fany_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Any::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Any)
diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h
index ae1151a..a91d456 100644
--- a/src/google/protobuf/any.pb.h
+++ b/src/google/protobuf/any.pb.h
@@ -53,9 +53,10 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto;
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fany_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class Any;
-class AnyDefaultTypeInternal;
+struct AnyDefaultTypeInternal;
 PROTOBUF_EXPORT extern AnyDefaultTypeInternal _Any_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -70,6 +71,7 @@
  public:
   inline Any() : Any(nullptr) {}
   virtual ~Any();
+  explicit constexpr Any(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Any(const Any& from);
   Any(Any&& from) noexcept
@@ -99,8 +101,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Any& default_instance();
-
+  static const Any& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Any* internal_default_instance() {
     return reinterpret_cast<const Any*>(
                &_Any_default_instance_);
@@ -199,8 +202,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fany_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fany_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fany_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
diff --git a/src/google/protobuf/any_lite.cc b/src/google/protobuf/any_lite.cc
index 55b55ee..48e0fac 100644
--- a/src/google/protobuf/any_lite.cc
+++ b/src/google/protobuf/any_lite.cc
@@ -79,7 +79,7 @@
 
 bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix,
                      std::string* full_type_name) {
-  size_t pos = type_url.find_last_of("/");
+  size_t pos = type_url.find_last_of('/');
   if (pos == std::string::npos || pos + 1 == type_url.size()) {
     return false;
   }
diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc
index 7ee673a..64aa6c0 100644
--- a/src/google/protobuf/api.pb.cc
+++ b/src/google/protobuf/api.pb.cc
@@ -16,68 +16,59 @@
 #include <google/protobuf/port_def.inc>
 
 PROTOBUF_PRAGMA_INIT_SEG
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fapi_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Method_google_2fprotobuf_2fapi_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fapi_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Mixin_google_2fprotobuf_2fapi_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftype_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Option_google_2fprotobuf_2ftype_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fsource_5fcontext_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto;
 PROTOBUF_NAMESPACE_OPEN
-class ApiDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Api> _instance;
-} _Api_default_instance_;
-class MethodDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Method> _instance;
-} _Method_default_instance_;
-class MixinDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Mixin> _instance;
-} _Mixin_default_instance_;
+constexpr Api::Api(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : methods_()
+  , options_()
+  , mixins_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , version_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , source_context_(nullptr)
+  , syntax_(0)
+{}
+struct ApiDefaultTypeInternal {
+  constexpr ApiDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~ApiDefaultTypeInternal() {}
+  union {
+    Api _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY ApiDefaultTypeInternal _Api_default_instance_;
+constexpr Method::Method(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : options_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , request_type_url_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , response_type_url_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , request_streaming_(false)
+  , response_streaming_(false)
+  , syntax_(0)
+{}
+struct MethodDefaultTypeInternal {
+  constexpr MethodDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~MethodDefaultTypeInternal() {}
+  union {
+    Method _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY MethodDefaultTypeInternal _Method_default_instance_;
+constexpr Mixin::Mixin(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , root_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string){}
+struct MixinDefaultTypeInternal {
+  constexpr MixinDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~MixinDefaultTypeInternal() {}
+  union {
+    Mixin _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY MixinDefaultTypeInternal _Mixin_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_Api_google_2fprotobuf_2fapi_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Api_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Api();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<4> scc_info_Api_google_2fprotobuf_2fapi_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 4, 0, InitDefaultsscc_info_Api_google_2fprotobuf_2fapi_2eproto}, {
-      &scc_info_Method_google_2fprotobuf_2fapi_2eproto.base,
-      &scc_info_Option_google_2fprotobuf_2ftype_2eproto.base,
-      &scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto.base,
-      &scc_info_Mixin_google_2fprotobuf_2fapi_2eproto.base,}};
-
-static void InitDefaultsscc_info_Method_google_2fprotobuf_2fapi_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Method_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Method();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Method_google_2fprotobuf_2fapi_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_Method_google_2fprotobuf_2fapi_2eproto}, {
-      &scc_info_Option_google_2fprotobuf_2ftype_2eproto.base,}};
-
-static void InitDefaultsscc_info_Mixin_google_2fprotobuf_2fapi_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Mixin_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Mixin();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Mixin_google_2fprotobuf_2fapi_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Mixin_google_2fprotobuf_2fapi_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fapi_2eproto[3];
 static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fapi_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fapi_2eproto = nullptr;
@@ -152,18 +143,18 @@
   &::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto,
   &::descriptor_table_google_2fprotobuf_2ftype_2eproto,
 };
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fapi_2eproto_sccs[3] = {
-  &scc_info_Api_google_2fprotobuf_2fapi_2eproto.base,
-  &scc_info_Method_google_2fprotobuf_2fapi_2eproto.base,
-  &scc_info_Mixin_google_2fprotobuf_2fapi_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fapi_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fapi_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fapi_2eproto, "google/protobuf/api.proto", 751,
-  &descriptor_table_google_2fprotobuf_2fapi_2eproto_once, descriptor_table_google_2fprotobuf_2fapi_2eproto_sccs, descriptor_table_google_2fprotobuf_2fapi_2eproto_deps, 3, 2,
+  false, false, 751, descriptor_table_protodef_google_2fprotobuf_2fapi_2eproto, "google/protobuf/api.proto", 
+  &descriptor_table_google_2fprotobuf_2fapi_2eproto_once, descriptor_table_google_2fprotobuf_2fapi_2eproto_deps, 2, 3,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fapi_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fapi_2eproto, 3, file_level_enum_descriptors_google_2fprotobuf_2fapi_2eproto, file_level_service_descriptors_google_2fprotobuf_2fapi_2eproto,
+  file_level_metadata_google_2fprotobuf_2fapi_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fapi_2eproto, file_level_service_descriptors_google_2fprotobuf_2fapi_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
+descriptor_table_google_2fprotobuf_2fapi_2eproto_metadata_getter(int index) {
+  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fapi_2eproto);
+  return descriptor_table_google_2fprotobuf_2fapi_2eproto.file_level_metadata[index];
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
 PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fapi_2eproto(&descriptor_table_google_2fprotobuf_2fapi_2eproto);
@@ -224,13 +215,12 @@
 }
 
 void Api::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Api_google_2fprotobuf_2fapi_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  version_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&source_context_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&syntax_) -
-      reinterpret_cast<char*>(&source_context_)) + sizeof(syntax_));
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+version_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&source_context_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&syntax_) -
+    reinterpret_cast<char*>(&source_context_)) + sizeof(syntax_));
 }
 
 Api::~Api() {
@@ -255,11 +245,6 @@
 void Api::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Api& Api::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Api_google_2fprotobuf_2fapi_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Api::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Api)
@@ -636,14 +621,13 @@
 }
 
 void Method::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Method_google_2fprotobuf_2fapi_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  request_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  response_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&request_streaming_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&syntax_) -
-      reinterpret_cast<char*>(&request_streaming_)) + sizeof(syntax_));
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+request_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+response_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&request_streaming_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&syntax_) -
+    reinterpret_cast<char*>(&request_streaming_)) + sizeof(syntax_));
 }
 
 Method::~Method() {
@@ -668,11 +652,6 @@
 void Method::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Method& Method::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Method_google_2fprotobuf_2fapi_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Method::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Method)
@@ -1022,9 +1001,8 @@
 }
 
 void Mixin::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Mixin_google_2fprotobuf_2fapi_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  root_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+root_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
 Mixin::~Mixin() {
@@ -1048,11 +1026,6 @@
 void Mixin::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Mixin& Mixin::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Mixin_google_2fprotobuf_2fapi_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Mixin::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Mixin)
diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h
index b141b54..3aea532 100644
--- a/src/google/protobuf/api.pb.h
+++ b/src/google/protobuf/api.pb.h
@@ -55,15 +55,16 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fapi_2eproto;
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fapi_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class Api;
-class ApiDefaultTypeInternal;
+struct ApiDefaultTypeInternal;
 PROTOBUF_EXPORT extern ApiDefaultTypeInternal _Api_default_instance_;
 class Method;
-class MethodDefaultTypeInternal;
+struct MethodDefaultTypeInternal;
 PROTOBUF_EXPORT extern MethodDefaultTypeInternal _Method_default_instance_;
 class Mixin;
-class MixinDefaultTypeInternal;
+struct MixinDefaultTypeInternal;
 PROTOBUF_EXPORT extern MixinDefaultTypeInternal _Mixin_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -80,6 +81,7 @@
  public:
   inline Api() : Api(nullptr) {}
   virtual ~Api();
+  explicit constexpr Api(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Api(const Api& from);
   Api(Api&& from) noexcept
@@ -109,8 +111,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Api& default_instance();
-
+  static const Api& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Api* internal_default_instance() {
     return reinterpret_cast<const Api*>(
                &_Api_default_instance_);
@@ -176,8 +179,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fapi_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fapi_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fapi_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -332,6 +334,7 @@
  public:
   inline Method() : Method(nullptr) {}
   virtual ~Method();
+  explicit constexpr Method(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Method(const Method& from);
   Method(Method&& from) noexcept
@@ -361,8 +364,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Method& default_instance();
-
+  static const Method& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Method* internal_default_instance() {
     return reinterpret_cast<const Method*>(
                &_Method_default_instance_);
@@ -428,8 +432,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fapi_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fapi_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fapi_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -564,6 +567,7 @@
  public:
   inline Mixin() : Mixin(nullptr) {}
   virtual ~Mixin();
+  explicit constexpr Mixin(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Mixin(const Mixin& from);
   Mixin(Mixin&& from) noexcept
@@ -593,8 +597,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Mixin& default_instance();
-
+  static const Mixin& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Mixin* internal_default_instance() {
     return reinterpret_cast<const Mixin*>(
                &_Mixin_default_instance_);
@@ -660,8 +665,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fapi_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fapi_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fapi_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc
index d4779a2..bd9516b 100644
--- a/src/google/protobuf/arena.cc
+++ b/src/google/protobuf/arena.cc
@@ -46,9 +46,6 @@
 
 #include <google/protobuf/port_def.inc>
 
-static const size_t kMinCleanupListElements = 8;
-static const size_t kMaxCleanupListElements = 64;  // 1kB on 64-bit.
-
 namespace google {
 namespace protobuf {
 namespace internal {
diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h
index 2b8782a..cf1de66 100644
--- a/src/google/protobuf/arena.h
+++ b/src/google/protobuf/arena.h
@@ -313,17 +313,9 @@
   // if the object were allocated on the heap (except that the underlying memory
   // is obtained from the arena).
   template <typename T, typename... Args>
-  PROTOBUF_ALWAYS_INLINE static T* Create(Arena* arena, Args&&... args) {
-    if (arena == NULL) {
-      return new T(std::forward<Args>(args)...);
-    } else {
-      auto destructor =
-          internal::ObjectDestructor<std::is_trivially_destructible<T>::value,
-                                     T>::destructor;
-      return new (arena->AllocateInternal(sizeof(T), alignof(T), destructor,
-                                          RTTI_TYPE_ID(T)))
-          T(std::forward<Args>(args)...);
-    }
+  PROTOBUF_NDEBUG_INLINE static T* Create(Arena* arena, Args&&... args) {
+    return CreateInternal<T>(arena, std::is_convertible<T*, MessageLite*>(),
+                             std::forward<Args>(args)...);
   }
 
   // Create an array of object type T on the arena *without* invoking the
@@ -333,9 +325,9 @@
   // (when compiled as C++11) that T is trivially default-constructible and
   // trivially destructible.
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE static T* CreateArray(Arena* arena,
+  PROTOBUF_NDEBUG_INLINE static T* CreateArray(Arena* arena,
                                                size_t num_elements) {
-    static_assert(std::is_standard_layout<T>::value && std::is_trivial<T>::value,
+    static_assert(std::is_pod<T>::value,
                   "CreateArray requires a trivially constructible type");
     static_assert(std::is_trivially_destructible<T>::value,
                   "CreateArray requires a trivially destructible type");
@@ -477,7 +469,7 @@
   struct has_get_arena : InternalHelper<T>::has_get_arena {};
 
   template <typename T, typename... Args>
-  PROTOBUF_ALWAYS_INLINE static T* CreateMessageInternal(Arena* arena,
+  PROTOBUF_NDEBUG_INLINE static T* CreateMessageInternal(Arena* arena,
                                                          Args&&... args) {
     static_assert(
         InternalHelper<T>::is_arena_constructable::value,
@@ -493,7 +485,7 @@
   // slightly different.  When the arena pointer is nullptr, it calls T()
   // instead of T(nullptr).
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE static T* CreateMessageInternal(Arena* arena) {
+  PROTOBUF_NDEBUG_INLINE static T* CreateMessageInternal(Arena* arena) {
     static_assert(
         InternalHelper<T>::is_arena_constructable::value,
         "CreateMessage can only construct types that are ArenaConstructable");
@@ -506,7 +498,7 @@
 
   // Allocate and also optionally call collector with the allocated type info
   // when allocation recording is enabled.
-  PROTOBUF_ALWAYS_INLINE void* AllocateInternal(size_t size, size_t align,
+  PROTOBUF_NDEBUG_INLINE void* AllocateInternal(size_t size, size_t align,
                                                 void (*destructor)(void*),
                                                 const std::type_info* type) {
     // Monitor allocation if needed.
@@ -557,7 +549,7 @@
   // Just allocate the required size for the given type assuming the
   // type has a trivial constructor.
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE T* CreateInternalRawArray(size_t num_elements) {
+  PROTOBUF_NDEBUG_INLINE T* CreateInternalRawArray(size_t num_elements) {
     GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T))
         << "Requested size is too large to fit into size_t.";
     // We count on compiler to realize that if sizeof(T) is a multiple of
@@ -568,7 +560,7 @@
   }
 
   template <typename T, typename... Args>
-  PROTOBUF_ALWAYS_INLINE T* DoCreateMessage(Args&&... args) {
+  PROTOBUF_NDEBUG_INLINE T* DoCreateMessage(Args&&... args) {
     return InternalHelper<T>::Construct(
         AllocateInternal(sizeof(T), alignof(T),
                          internal::ObjectDestructor<
@@ -611,6 +603,40 @@
     arena->OwnDestructor(ptr);
   }
 
+  // These implement Create(). The second parameter has type 'true_type' if T is
+  // a subtype of Message and 'false_type' otherwise.
+  template <typename T, typename... Args>
+  PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena, std::true_type,
+                                                  Args&&... args) {
+    if (arena == nullptr) {
+      return new T(std::forward<Args>(args)...);
+    } else {
+      auto destructor =
+          internal::ObjectDestructor<std::is_trivially_destructible<T>::value,
+                                     T>::destructor;
+      T* result =
+          new (arena->AllocateInternal(sizeof(T), alignof(T), destructor,
+                                       RTTI_TYPE_ID(T)))
+          T(std::forward<Args>(args)...);
+      result->SetOwningArena(arena);
+      return result;
+    }
+  }
+  template <typename T, typename... Args>
+  PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena, std::false_type,
+                                                  Args&&... args) {
+    if (arena == nullptr) {
+      return new T(std::forward<Args>(args)...);
+    } else {
+      auto destructor =
+          internal::ObjectDestructor<std::is_trivially_destructible<T>::value,
+                                     T>::destructor;
+      return new (arena->AllocateInternal(sizeof(T), alignof(T), destructor,
+                                          RTTI_TYPE_ID(T)))
+          T(std::forward<Args>(args)...);
+    }
+  }
+
   // These implement Own(), which registers an object for deletion (destructor
   // call and operator delete()). The second parameter has type 'true_type' if T
   // is a subtype of Message and 'false_type' otherwise. Collapsing
@@ -620,6 +646,7 @@
   PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::true_type) {
     if (object != NULL) {
       impl_.AddCleanup(object, &internal::arena_delete_object<MessageLite>);
+      object->SetOwningArena(this);
     }
   }
   template <typename T>
diff --git a/src/google/protobuf/arena_impl.h b/src/google/protobuf/arena_impl.h
index 84c5d05..40608df 100644
--- a/src/google/protobuf/arena_impl.h
+++ b/src/google/protobuf/arena_impl.h
@@ -296,7 +296,7 @@
   // semantics is necessary to allow callers to program functions that only
   // have fallback function calls in tail position. This substantially improves
   // code for the happy path.
-  PROTOBUF_ALWAYS_INLINE bool MaybeAllocateAligned(size_t n, void** out) {
+  PROTOBUF_NDEBUG_INLINE bool MaybeAllocateAligned(size_t n, void** out) {
     SerialArena* a;
     if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFromThreadCache(tag_and_id_, &a))) {
       return a->MaybeAllocateAligned(n, out);
@@ -362,7 +362,7 @@
     hint_.store(serial, std::memory_order_release);
   }
 
-  PROTOBUF_ALWAYS_INLINE bool GetSerialArenaFast(uint64 lifecycle_id,
+  PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFast(uint64 lifecycle_id,
                                                  SerialArena** arena) {
     if (GetSerialArenaFromThreadCache(lifecycle_id, arena)) return true;
     if (lifecycle_id & kRecordAllocs) return false;
@@ -378,7 +378,7 @@
     return false;
   }
 
-  PROTOBUF_ALWAYS_INLINE bool GetSerialArenaFromThreadCache(
+  PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFromThreadCache(
       uint64 lifecycle_id, SerialArena** arena) {
     // If this thread already owns a block in this arena then try to use that.
     // This fast path optimizes the case where multiple threads allocate from
diff --git a/src/google/protobuf/arenastring.h b/src/google/protobuf/arenastring.h
index acd177f..927553c 100644
--- a/src/google/protobuf/arenastring.h
+++ b/src/google/protobuf/arenastring.h
@@ -51,6 +51,9 @@
 namespace protobuf {
 namespace internal {
 
+template <typename T>
+class ExplicitlyConstructed;
+
 // Lazy string instance to support string fields with non-empty default.
 // These are initialized on the first call to .get().
 class PROTOBUF_EXPORT LazyString {
@@ -88,8 +91,8 @@
 class TaggedPtr {
  public:
   TaggedPtr() = default;
-  explicit constexpr TaggedPtr(const std::string* ptr)
-      : ptr_(const_cast<std::string*>(ptr)) {}
+  explicit constexpr TaggedPtr(const ExplicitlyConstructed<std::string>* ptr)
+      : ptr_(const_cast<ExplicitlyConstructed<std::string>*>(ptr)) {}
 
   void SetTagged(T* p) {
     Set(p);
@@ -171,7 +174,8 @@
 // requires the String tag to be 0 so we can avoid the mask before comparing.)
 struct PROTOBUF_EXPORT ArenaStringPtr {
   ArenaStringPtr() = default;
-  explicit constexpr ArenaStringPtr(const std::string* default_value)
+  explicit constexpr ArenaStringPtr(
+      const ExplicitlyConstructed<std::string>* default_value)
       : tagged_ptr_(default_value) {}
 
   // Some methods below are overloaded on a `default_value` and on tags.
@@ -191,11 +195,11 @@
   void Set(NonEmptyDefault, std::string&& value, ::google::protobuf::Arena* arena);
 
   // Basic accessors.
-  const std::string& Get() const PROTOBUF_ALWAYS_INLINE {
+  const std::string& Get() const PROTOBUF_NDEBUG_INLINE {
     // Unconditionally mask away the tag.
     return *tagged_ptr_.Get();
   }
-  const std::string* GetPointer() const PROTOBUF_ALWAYS_INLINE {
+  const std::string* GetPointer() const PROTOBUF_NDEBUG_INLINE {
     // Unconditionally mask away the tag.
     return tagged_ptr_.Get();
   }
@@ -224,7 +228,7 @@
   // logic in Swap()/UnsafeArenaSwap() at the message level, so this method is
   // 'unsafe' if called directly.
   inline void Swap(ArenaStringPtr* other, const std::string* default_value,
-                   Arena* arena) PROTOBUF_ALWAYS_INLINE;
+                   Arena* arena) PROTOBUF_NDEBUG_INLINE;
 
   // Frees storage (if not on an arena).
   void Destroy(const std::string* default_value, ::google::protobuf::Arena* arena);
@@ -329,8 +333,8 @@
     this_ptr->swap(*other_ptr);
   }
 #else
-  (void) default_value;
-  (void) arena;
+  (void)default_value;
+  (void)arena;
   std::swap(tagged_ptr_, other->tagged_ptr_);
 #endif
 }
diff --git a/src/google/protobuf/arenastring_unittest.cc b/src/google/protobuf/arenastring_unittest.cc
index 8d7b520..bd4b4d8 100644
--- a/src/google/protobuf/arenastring_unittest.cc
+++ b/src/google/protobuf/arenastring_unittest.cc
@@ -41,6 +41,7 @@
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/message_lite.h>
 #include <gtest/gtest.h>
 #include <google/protobuf/stubs/strutil.h>
 
diff --git a/src/google/protobuf/compiler/annotation_test_util.cc b/src/google/protobuf/compiler/annotation_test_util.cc
index d33f29f..fb659f6 100644
--- a/src/google/protobuf/compiler/annotation_test_util.cc
+++ b/src/google/protobuf/compiler/annotation_test_util.cc
@@ -31,15 +31,15 @@
 #include <google/protobuf/compiler/annotation_test_util.h>
 
 #include <memory>
+
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/compiler/code_generator.h>
 #include <google/protobuf/compiler/command_line_interface.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <google/protobuf/descriptor.pb.h>
-
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index 242cb7d..ab49ac2 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -234,7 +234,7 @@
 // Add the paths where google/protobuf/descriptor.proto and other well-known
 // type protos are installed.
 void AddDefaultProtoPaths(
-    std::vector<std::pair<std::string, std::string> >* paths) {
+    std::vector<std::pair<std::string, std::string>>* paths) {
   // TODO(xiaofeng): The code currently only checks relative paths of where
   // the protoc binary is installed. We probably should make it handle more
   // cases than that.
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index 7602e9f..57e6d7e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -156,6 +156,12 @@
       "));\n");
 }
 
+void EnumFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  format("$name$_($default$)\n");
+}
+
 // ===================================================================
 
 EnumOneofFieldGenerator::EnumOneofFieldGenerator(
@@ -484,6 +490,16 @@
   format("}\n");
 }
 
+void RepeatedEnumFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  format("$name$_()");
+  if (descriptor_->is_packed() &&
+      HasGeneratedMethods(descriptor_->file(), options_)) {
+    format("\n, _$name$_cached_byte_size_()");
+  }
+}
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
index 3b97608..3fa64a8 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
@@ -60,6 +60,7 @@
   void GenerateCopyConstructorCode(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
+  void GenerateConstinitInitializer(io::Printer* printer) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
@@ -100,6 +101,7 @@
   void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
+  void GenerateConstinitInitializer(io::Printer* printer) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h
index 2d11f90..e05f49b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -164,6 +164,12 @@
     return false;
   }
 
+  // Generate initialization code for private members declared by
+  // GeneratePrivateMembers(), specifically for the constexpr construtor.
+  // These go into the constructor's initializer list and must follow that
+  // syntax (eg `field_(args)`). Does not include `:` or `,` separators.
+  virtual void GenerateConstinitInitializer(io::Printer* printer) const {}
+
   // Generate lines to serialize this field directly to the array "target",
   // which are placed within the message's SerializeWithCachedSizesToArray()
   // method. This must also advance "target" past the written bytes.
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index 8ca7ba2..d590af3 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -38,6 +38,7 @@
 #include <map>
 #include <memory>
 #include <set>
+#include <unordered_map>
 #include <unordered_set>
 #include <vector>
 
@@ -52,6 +53,7 @@
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/stubs/strutil.h>
 
+// Must be last.
 #include <google/protobuf/port_def.inc>
 
 namespace google {
@@ -138,13 +140,6 @@
   for (int i = 0; i < file->weak_dependency_count(); ++i) {
     weak_deps_.insert(file->weak_dependency(i));
   }
-  for (int i = 0; i < message_generators_.size(); i++) {
-    if (IsSCCRepresentative(message_generators_[i]->descriptor_)) {
-      sccs_.push_back(GetSCC(message_generators_[i]->descriptor_));
-    }
-  }
-
-  std::sort(sccs_.begin(), sccs_.end(), CompareSortKeys<SCC>);
 }
 
 FileGenerator::~FileGenerator() = default;
@@ -426,6 +421,10 @@
       format("#include \"$1$.proto.h\"\n", basename);
     }
   }
+  if (HasCordFields(file_, options_)) {
+    format(
+        "#include \"third_party/absl/strings/internal/string_constant.h\"\n");
+  }
 
   format("// @@protoc_insertion_point(includes)\n");
   IncludeFile("net/proto2/public/port_def.inc", printer);
@@ -441,13 +440,28 @@
                                                   io::Printer* printer) {
   Formatter format(printer, variables_);
   MessageGenerator* generator = message_generators_[idx].get();
+  generator->GenerateConstexprConstructor(printer);
+  // Use a union to disable the destructor of the _instance member.
+  // We can constant initialize, but the object will still have a non-trivial
+  // destructor that we need to elide.
   format(
-      "class $1$ {\n"
-      " public:\n"
-      "  ::$proto_ns$::internal::ExplicitlyConstructed<$2$> _instance;\n",
+      "struct $1$ {\n"
+      "  constexpr $1$()\n"
+      "    : _instance(::$proto_ns$::internal::ConstantInitialized{}) {}\n"
+      "  ~$1$() {}\n"
+      "  union {\n"
+      "    $2$ _instance;\n"
+      "  };\n"
+      "};\n",
       DefaultInstanceType(generator->descriptor_, options_),
       generator->classname_);
-  format("} $1$;\n", DefaultInstanceName(generator->descriptor_, options_));
+  // NO_DESTROY is not necessary for correctness. The empty destructor is
+  // enough. However, the empty destructor fails to be elided in some
+  // configurations (like non-opt or with certain sanitizers). NO_DESTROY is
+  // there just to improve performance and binary size in these builds.
+  format("PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY $1$ $2$;\n",
+         DefaultInstanceType(generator->descriptor_, options_),
+         DefaultInstanceName(generator->descriptor_, options_));
 
   if (options_.lite_implicit_weak_fields) {
     format("$1$* $2$ = &$3$;\n",
@@ -461,8 +475,6 @@
 // another .pb.cc file.
 struct FileGenerator::CrossFileReferences {
   // Populated if we are referencing from messages or files.
-  std::unordered_set<const SCC*> strong_sccs;
-  std::unordered_set<const SCC*> weak_sccs;
   std::unordered_set<const Descriptor*> weak_default_instances;
 
   // Only if we are referencing from files.
@@ -474,16 +486,10 @@
                                                    CrossFileReferences* refs) {
   const Descriptor* msg = field->message_type();
   if (msg == nullptr) return;
-  const SCC* scc = GetSCC(msg);
 
   if (IsImplicitWeakField(field, options_, &scc_analyzer_) ||
       IsWeak(field, options_)) {
-    refs->weak_sccs.insert(scc);
     refs->weak_default_instances.insert(msg);
-  } else {
-    refs->strong_sccs.insert(scc);
-    // We don't need to declare default instances, because it is declared in the
-    // .proto.h file we imported.
   }
 }
 
@@ -510,35 +516,6 @@
     const CrossFileReferences& refs, io::Printer* printer) {
   Formatter format(printer, variables_);
 
-  for (auto scc : Sorted(refs.strong_sccs)) {
-    format("extern $1$ ::$proto_ns$::internal::SCCInfo<$2$> $3$;\n",
-           FileDllExport(scc->GetFile(), options_), scc->children.size(),
-           SccInfoSymbol(scc, options_));
-  }
-
-  for (auto scc : Sorted(refs.weak_sccs)) {
-    // We do things a little bit differently for proto1-style weak fields versus
-    // lite implicit weak fields, even though they are trying to accomplish
-    // similar things. We need to support implicit weak fields on iOS, and the
-    // Apple linker only supports weak definitions, not weak declarations. For
-    // that reason we need a pointer type which we can weakly define to be null.
-    // However, code size considerations prevent us from using the same approach
-    // for proto1-style weak fields.
-    if (options_.lite_implicit_weak_fields) {
-      format("extern ::$proto_ns$::internal::SCCInfo<$1$> $2$;\n",
-             scc->children.size(), SccInfoSymbol(scc, options_));
-      format(
-          "__attribute__((weak)) ::$proto_ns$::internal::SCCInfo<$1$>*\n"
-          "    $2$ = nullptr;\n",
-          scc->children.size(), SccInfoPtrSymbol(scc, options_));
-    } else {
-      format(
-          "extern __attribute__((weak)) ::$proto_ns$::internal::SCCInfo<$1$> "
-          "$2$;\n",
-          scc->children.size(), SccInfoSymbol(scc, options_));
-    }
-  }
-
   {
     NamespaceOpener ns(format);
     for (auto instance : Sorted(refs.weak_default_instances)) {
@@ -569,24 +546,13 @@
   Formatter format(printer, variables_);
   GenerateSourceIncludes(printer);
 
-  // Generate weak declarations. We do this for the whole strongly-connected
-  // component (SCC), because we have a single InitDefaults* function for the
-  // SCC.
   CrossFileReferences refs;
-  for (const Descriptor* message :
-       scc_analyzer_.GetSCC(message_generators_[idx]->descriptor_)
-           ->descriptors) {
-    ForEachField(message, [this, &refs](const FieldDescriptor* field) {
-      GetCrossFileReferencesForField(field, &refs);
-    });
-  }
+  ForEachField(message_generators_[idx]->descriptor_,
+               [this, &refs](const FieldDescriptor* field) {
+                 GetCrossFileReferencesForField(field, &refs);
+               });
   GenerateInternalForwardDeclarations(refs, printer);
 
-  if (IsSCCRepresentative(message_generators_[idx]->descriptor_)) {
-    GenerateInitForSCC(GetSCC(message_generators_[idx]->descriptor_), refs,
-                       printer);
-  }
-
   {  // package namespace
     NamespaceOpener ns(Namespace(file_, options_), format);
 
@@ -668,11 +634,6 @@
   {
     GenerateTables(printer);
 
-    // Now generate the InitDefaults for each SCC.
-    for (auto scc : sccs_) {
-      GenerateInitForSCC(scc, refs, printer);
-    }
-
     if (HasDescriptorMethods(file_, options_)) {
       // Define the code to initialize reflection. This code uses a global
       // constructor to register reflection data with the runtime pre-main.
@@ -872,31 +833,21 @@
       refs.strong_reflection_files.size() + refs.weak_reflection_files.size();
 
   // Build array of DescriptorTable deps.
-  format(
-      "static const ::$proto_ns$::internal::DescriptorTable*const "
-      "$desc_table$_deps[$1$] = {\n",
-      std::max(num_deps, 1));
+  if (num_deps > 0) {
+    format(
+        "static const ::$proto_ns$::internal::DescriptorTable*const "
+        "$desc_table$_deps[$1$] = {\n",
+        num_deps);
 
-  for (auto dep : Sorted(refs.strong_reflection_files)) {
-    format("  &::$1$,\n", DescriptorTableName(dep, options_));
+    for (auto dep : Sorted(refs.strong_reflection_files)) {
+      format("  &::$1$,\n", DescriptorTableName(dep, options_));
+    }
+    for (auto dep : Sorted(refs.weak_reflection_files)) {
+      format("  &::$1$,\n", DescriptorTableName(dep, options_));
+    }
+
+    format("};\n");
   }
-  for (auto dep : Sorted(refs.weak_reflection_files)) {
-    format("  &::$1$,\n", DescriptorTableName(dep, options_));
-  }
-
-  format("};\n");
-
-  // Build array of SCCs from this file.
-  format(
-      "static ::$proto_ns$::internal::SCCInfoBase*const "
-      "$desc_table$_sccs[$1$] = {\n",
-      std::max<int>(sccs_.size(), 1));
-
-  for (auto scc : sccs_) {
-    format("  &$1$.base,\n", SccInfoSymbol(scc, options_));
-  }
-
-  format("};\n");
 
   // The DescriptorTable itself.
   // Should be "bool eager = NeedsEagerDescriptorAssignment(file_, options_);"
@@ -906,14 +857,27 @@
   format(
       "static ::$proto_ns$::internal::once_flag $desc_table$_once;\n"
       "const ::$proto_ns$::internal::DescriptorTable $desc_table$ = {\n"
-      "  false, $1$, $2$, \"$filename$\", $3$,\n"
-      "  &$desc_table$_once, $desc_table$_sccs, $desc_table$_deps, $4$, $5$,\n"
+      "  false, $1$, $2$, $3$, \"$filename$\", \n"
+      "  &$desc_table$_once, $4$, $5$, $6$,\n"
       "  schemas, file_default_instances, $tablename$::offsets,\n"
-      "  $file_level_metadata$, $6$, $file_level_enum_descriptors$, "
+      "  $file_level_metadata$, $file_level_enum_descriptors$, "
       "$file_level_service_descriptors$,\n"
-      "};\n\n",
-      eager ? "true" : "false", protodef_name, file_data.size(), sccs_.size(),
-      num_deps, message_generators_.size());
+      "};\n"
+      // This function exists to be marked as weak.
+      // It can significantly speed up compilation by breaking up the SCC.
+      // Without the weak attribute all the messages in the file, including all
+      // the vtables and everything they use become part of the same SCC.
+      // By adding a weak function here we break the connection from the
+      // individual vtables back into the descriptor table.
+      "PROTOBUF_ATTRIBUTE_WEAK ::$proto_ns$::Metadata\n"
+      "$desc_table$_metadata_getter(int index) {\n"
+      "  ::$proto_ns$::internal::AssignDescriptors(&$desc_table$);\n"
+      "  return $desc_table$.file_level_metadata[index];\n"
+      "}\n"
+      "\n",
+      eager ? "true" : "false", file_data.size(), protodef_name,
+      num_deps == 0 ? "nullptr" : variables_["desc_table"] + "_deps", num_deps,
+      message_generators_.size());
 
   // For descriptor.proto we want to avoid doing any dynamic initialization,
   // because in some situations that would otherwise pull in a lot of
@@ -929,86 +893,6 @@
   }
 }
 
-void FileGenerator::GenerateInitForSCC(const SCC* scc,
-                                       const CrossFileReferences& refs,
-                                       io::Printer* printer) {
-  Formatter format(printer, variables_);
-  // We use static and not anonymous namespace because symbol names are
-  // substantially shorter.
-  format("static void InitDefaults$1$() {\n", SccInfoSymbol(scc, options_));
-
-  if (options_.opensource_runtime) {
-    format("  GOOGLE_PROTOBUF_VERIFY_VERSION;\n\n");
-  }
-
-  format.Indent();
-
-  // First construct all the necessary default instances.
-  for (int i = 0; i < message_generators_.size(); i++) {
-    if (scc_analyzer_.GetSCC(message_generators_[i]->descriptor_) != scc) {
-      continue;
-    }
-    format(
-        "{\n"
-        "  void* ptr = &$1$;\n"
-        "  new (ptr) $2$();\n",
-        QualifiedDefaultInstanceName(message_generators_[i]->descriptor_,
-                                     options_),
-        QualifiedClassName(message_generators_[i]->descriptor_, options_));
-    if (options_.opensource_runtime &&
-        !IsMapEntryMessage(message_generators_[i]->descriptor_)) {
-      format(
-          "  "
-          "::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);"
-          "\n");
-    }
-    format("}\n");
-  }
-  format.Outdent();
-  format("}\n\n");
-
-  // If we are using lite implicit weak fields then we need to distinguish
-  // between regular SCC dependencies and ones that we need to reference weakly
-  // through an extra pointer indirection.
-  std::vector<const SCC*> regular_sccs;
-  std::vector<const SCC*> implicit_weak_sccs;
-  for (const SCC* child : scc->children) {
-    if (options_.lite_implicit_weak_fields &&
-        refs.weak_sccs.find(child) != refs.weak_sccs.end()) {
-      implicit_weak_sccs.push_back(child);
-    } else {
-      regular_sccs.push_back(child);
-    }
-  }
-
-  format(
-      "$dllexport_decl $::$proto_ns$::internal::SCCInfo<$1$> $2$ =\n"
-      "    "
-      "{{ATOMIC_VAR_INIT(::$proto_ns$::internal::SCCInfoBase::kUninitialized), "
-      "$3$, $4$, InitDefaults$2$}, {",
-      scc->children.size(),  // 1
-      SccInfoSymbol(scc, options_), regular_sccs.size(),
-      implicit_weak_sccs.size());
-  for (const SCC* child : regular_sccs) {
-    format("\n      &$1$.base,", SccInfoSymbol(child, options_));
-  }
-  for (const SCC* child : implicit_weak_sccs) {
-    format(
-        "\n      reinterpret_cast<::$proto_ns$::internal::SCCInfoBase**>("
-        "\n          &$1$),",
-        SccInfoPtrSymbol(child, options_));
-  }
-  format("}};\n\n");
-
-  if (options_.lite_implicit_weak_fields) {
-    format(
-        "$dllexport_decl $::$proto_ns$::internal::SCCInfo<$1$>*\n"
-        "    $2$ = &$3$;\n\n",
-        scc->children.size(), SccInfoPtrSymbol(scc, options_),
-        SccInfoSymbol(scc, options_));
-  }
-}
-
 void FileGenerator::GenerateTables(io::Printer* printer) {
   Formatter format(printer, variables_);
   if (options_.table_driven_parsing) {
@@ -1138,7 +1022,7 @@
       const Descriptor* class_desc = p.second;
       format(
           "class ${1$$2$$}$;\n"
-          "class $3$;\n"
+          "struct $3$;\n"
           "$dllexport_decl $extern $3$ $4$;\n",
           class_desc, classname, DefaultInstanceType(class_desc, options),
           DefaultInstanceName(class_desc, options));
@@ -1409,7 +1293,9 @@
   if (HasDescriptorMethods(file_, options_)) {
     format(
         "extern $dllexport_decl $const ::$proto_ns$::internal::DescriptorTable "
-        "$desc_table$;\n");
+        "$desc_table$;\n"
+        "$dllexport_decl $::$proto_ns$::Metadata "
+        "$desc_table$_metadata_getter(int index);\n");
   }
 }
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h
index da5e1de..35a9085 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.h
+++ b/src/google/protobuf/compiler/cpp/cpp_file.h
@@ -162,14 +162,6 @@
   // generally a breaking change so we prefer the #undef approach.
   void GenerateMacroUndefs(io::Printer* printer);
 
-  bool IsSCCRepresentative(const Descriptor* d) {
-    return GetSCCRepresentative(d) == d;
-  }
-  const Descriptor* GetSCCRepresentative(const Descriptor* d) {
-    return GetSCC(d)->GetRepresentative();
-  }
-  const SCC* GetSCC(const Descriptor* d) { return scc_analyzer_.GetSCC(d); }
-
   bool IsDepWeak(const FileDescriptor* dep) const {
     if (weak_deps_.count(dep) != 0) {
       GOOGLE_CHECK(!options_.opensource_runtime);
@@ -179,7 +171,6 @@
   }
 
   std::set<const FileDescriptor*> weak_deps_;
-  std::vector<const SCC*> sccs_;
 
   const FileDescriptor* file_;
   const Options options_;
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index 46fe55c..5825af2 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -44,6 +44,7 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/compiler/cpp/cpp_names.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/compiler/scc.h>
@@ -521,6 +522,14 @@
   return QualifiedClassName(field->message_type(), options);
 }
 
+std::string StripProto(const std::string& filename) {
+  /*
+   * TODO(github/georgthegreat) remove this proxy method
+   * once Google's internal codebase will become ready
+   */
+  return compiler::StripProto(filename);
+}
+
 const char* PrimitiveTypeName(FieldDescriptor::CppType type) {
   switch (type) {
     case FieldDescriptor::CPPTYPE_INT32:
@@ -1147,11 +1156,6 @@
     const Descriptor* descriptor = scc->descriptors[i];
     if (descriptor->extension_range_count() > 0) {
       result.contains_extension = true;
-      // Extensions are found by looking up default_instance and extension
-      // number in a map. So you'd maybe expect here
-      // result.constructor_requires_initialization = true;
-      // However the extension registration mechanism already makes sure
-      // the default will be initialized.
     }
     for (int i = 0; i < descriptor->field_count(); i++) {
       const FieldDescriptor* field = descriptor->field(i);
@@ -1161,7 +1165,6 @@
       switch (field->type()) {
         case FieldDescriptor::TYPE_STRING:
         case FieldDescriptor::TYPE_BYTES: {
-          result.constructor_requires_initialization = true;
           if (field->options().ctype() == FieldOptions::CORD) {
             result.contains_cord = true;
           }
@@ -1169,7 +1172,6 @@
         }
         case FieldDescriptor::TYPE_GROUP:
         case FieldDescriptor::TYPE_MESSAGE: {
-          result.constructor_requires_initialization = true;
           const SCC* child = analyzer_.GetSCC(field->message_type());
           if (child != scc) {
             MessageAnalysis analysis = GetSCCAnalysis(child);
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index 125f059..46d9477 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -539,7 +539,6 @@
   bool contains_cord;
   bool contains_extension;
   bool contains_required;
-  bool constructor_requires_initialization;
 };
 
 // This class is used in FileGenerator, to ensure linear instead of
@@ -577,16 +576,6 @@
   std::map<const SCC*, MessageAnalysis> analysis_cache_;
 };
 
-inline std::string SccInfoSymbol(const SCC* scc, const Options& options) {
-  return UniqueName("scc_info_" + ClassName(scc->GetRepresentative()),
-                    scc->GetRepresentative(), options);
-}
-
-inline std::string SccInfoPtrSymbol(const SCC* scc, const Options& options) {
-  return UniqueName("scc_info_ptr_" + ClassName(scc->GetRepresentative()),
-                    scc->GetRepresentative(), options);
-}
-
 void ListAllFields(const Descriptor* d,
                    std::vector<const FieldDescriptor*>* fields);
 void ListAllFields(const FileDescriptor* d,
@@ -881,13 +870,7 @@
                         const Options& options,
                         MessageSCCAnalyzer* scc_analyzer, io::Printer* printer);
 
-inline std::string StripProto(const std::string& filename) {
-  /*
-   * TODO(github/georgthegreat) remove this proxy method
-   * once Google's internal codebase will become ready
-   */
-  return compiler::StripProto(filename);
-}
+PROTOC_EXPORT std::string StripProto(const std::string& filename);
 
 }  // namespace cpp
 }  // namespace compiler
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
index 39312b3..c9c30e0 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
@@ -290,6 +290,16 @@
       "}\n");
 }
 
+void MapFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  if (HasDescriptorMethods(descriptor_->file(), options_)) {
+    format("$name$_(::$proto_ns$::internal::ConstantInitialized{})");
+  } else {
+    format("$name$_()");
+  }
+}
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.h b/src/google/protobuf/compiler/cpp/cpp_map_field.h
index e0c14f3..149e8a3 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.h
@@ -57,6 +57,7 @@
   void GenerateCopyConstructorCode(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
+  void GenerateConstinitInitializer(io::Printer* printer) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index c72ed68..4878d18 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -241,9 +241,9 @@
     return true;
   }
   // For message types without true field presence, only fields with a message
-  // type have a has_$name$() method.
+  // type or inside an one-of have a has_$name$() method.
   return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
-         field->has_optional_keyword();
+         field->has_optional_keyword() || field->real_containing_oneof();
 }
 
 // Collects map entry message type information.
@@ -296,21 +296,6 @@
          options.opensource_runtime;
 }
 
-bool ShouldMarkIsInitializedAsFinal(const Descriptor* descriptor,
-                                    const Options& options) {
-  static std::set<std::string> exclusions{
-  };
-
-  const std::string name = ClassName(descriptor, true);
-  return exclusions.find(name) == exclusions.end() ||
-         options.opensource_runtime;
-}
-
-bool ShouldMarkNewAsFinal(const Descriptor* descriptor,
-                          const Options& options) {
-  return true;
-}
-
 // Returns true to make the message serialize in order, decided by the following
 // factors in the order of precedence.
 // --options().message_set_wire_format() == true
@@ -582,8 +567,6 @@
   // Variables that apply to this class
   variables_["classname"] = classname_;
   variables_["classtype"] = QualifiedClassName(descriptor_, options);
-  variables_["scc_info"] =
-      SccInfoSymbol(scc_analyzer_->GetSCC(descriptor_), options_);
   variables_["full_name"] = descriptor_->full_name();
   variables_["superclass"] = SuperClassName(descriptor_, options_);
 
@@ -1024,6 +1007,8 @@
         "    ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> "
         "SuperType;\n"
         "  $classname$();\n"
+        "  explicit constexpr $classname$(\n"
+        "      ::$proto_ns$::internal::ConstantInitialized);\n"
         "  explicit $classname$(::$proto_ns$::Arena* arena);\n"
         "  void MergeFrom(const $classname$& other);\n"
         "  static const $classname$* internal_default_instance() { return "
@@ -1041,7 +1026,7 @@
             " }\n",
             descriptor_->field(0)->full_name());
       } else {
-        GOOGLE_CHECK(utf8_check == VERIFY);
+        GOOGLE_CHECK_EQ(utf8_check, VERIFY);
         format(
             "  static bool ValidateKey(std::string* s) {\n"
             "#ifndef NDEBUG\n"
@@ -1070,7 +1055,7 @@
             " }\n",
             descriptor_->field(1)->full_name());
       } else {
-        GOOGLE_CHECK(utf8_check == VERIFY);
+        GOOGLE_CHECK_EQ(utf8_check, VERIFY);
         format(
             "  static bool ValidateValue(std::string* s) {\n"
             "#ifndef NDEBUG\n"
@@ -1118,6 +1103,8 @@
   format(
       "inline $classname$() : $classname$(nullptr) {}\n"
       "virtual ~$classname$();\n"
+      "explicit constexpr "
+      "$classname$(::$proto_ns$::internal::ConstantInitialized);\n"
       "\n"
       "$classname$(const $classname$& from);\n"
       "$classname$($classname$&& from) noexcept\n"
@@ -1189,8 +1176,9 @@
   }
 
   format(
-      "static const $classname$& default_instance();\n"
-      "\n");
+      "static const $classname$& default_instance() {\n"
+      "  return *internal_default_instance();\n"
+      "}\n");
 
   // Generate enum values for every field in oneofs. One list is generated for
   // each oneof with an additional *_NOT_SET value.
@@ -1288,9 +1276,6 @@
         "                            std::string* full_type_name);\n");
   }
 
-  format.Set("new_final",
-             ShouldMarkNewAsFinal(descriptor_, options_) ? "final" : "");
-
   format(
       "friend void swap($classname$& a, $classname$& b) {\n"
       "  a.Swap(&b);\n"
@@ -1313,11 +1298,11 @@
       "\n"
       "// implements Message ----------------------------------------------\n"
       "\n"
-      "inline $classname$* New() const$ new_final$ {\n"
+      "inline $classname$* New() const final {\n"
       "  return CreateMaybeMessage<$classname$>(nullptr);\n"
       "}\n"
       "\n"
-      "$classname$* New(::$proto_ns$::Arena* arena) const$ new_final$ {\n"
+      "$classname$* New(::$proto_ns$::Arena* arena) const final {\n"
       "  return CreateMaybeMessage<$classname$>(arena);\n"
       "}\n");
 
@@ -1340,15 +1325,12 @@
 
     format.Set("clear_final",
                ShouldMarkClearAsFinal(descriptor_, options_) ? "final" : "");
-    format.Set(
-        "is_initialized_final",
-        ShouldMarkIsInitializedAsFinal(descriptor_, options_) ? "final" : "");
 
     format(
         "void CopyFrom(const $classname$& from);\n"
         "void MergeFrom(const $classname$& from);\n"
         "PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear()$ clear_final$;\n"
-        "bool IsInitialized() const$ is_initialized_final$;\n"
+        "bool IsInitialized() const final;\n"
         "\n"
         "size_t ByteSizeLong() const final;\n"
         "const char* _InternalParse(const char* ptr, "
@@ -1400,8 +1382,7 @@
         "::$proto_ns$::Metadata GetMetadata() const final;\n"
         "private:\n"
         "static ::$proto_ns$::Metadata GetMetadataStatic() {\n"
-        "  ::$proto_ns$::internal::AssignDescriptors(&::$desc_table$);\n"
-        "  return ::$desc_table$.file_level_metadata[kIndexInFileMessages];\n"
+        "  return ::$desc_table$_metadata_getter(kIndexInFileMessages);\n"
         "}\n"
         "\n"
         "public:\n"
@@ -1540,13 +1521,14 @@
   // For each oneof generate a union
   for (auto oneof : OneOfRange(descriptor_)) {
     std::string camel_oneof_name = UnderscoresToCamelCase(oneof->name(), true);
+    format("union $1$Union {\n", camel_oneof_name);
+    format.Indent();
     format(
-        "union $1$Union {\n"
         // explicit empty constructor is needed when union contains
         // ArenaStringPtr members for string fields.
-        "  $1$Union() {}\n",
+        "constexpr $1$Union() : _constinit_{} {}\n"
+        "  ::$proto_ns$::internal::ConstantInitialized _constinit_;\n",
         camel_oneof_name);
-    format.Indent();
     for (auto field : FieldRange(oneof)) {
       if (!IsFieldStripped(field, options_)) {
         field_generators_.get(field).GeneratePrivateMembers(printer);
@@ -2328,12 +2310,6 @@
   Formatter format(printer, variables_);
 
   format("void $classname$::SharedCtor() {\n");
-  if (scc_analyzer_->GetSCCAnalysis(scc_analyzer_->GetSCC(descriptor_))
-          .constructor_requires_initialization) {
-    format("  ::$proto_ns$::internal::InitSCC(&$scc_info$.base);\n");
-  }
-
-  format.Indent();
 
   std::vector<bool> processed(optimized_order_.size(), false);
   GenerateConstructorBody(printer, processed, false);
@@ -2342,7 +2318,6 @@
     format("clear_has_$1$();\n", oneof->name());
   }
 
-  format.Outdent();
   format("}\n\n");
 }
 
@@ -2413,12 +2388,6 @@
       }
     }
   }
-  if (num_weak_fields_) {
-    // _this is the object being destructed (we are inside a static method
-    // here).
-    format("_this->_weak_field_map_.ClearAll();\n");
-    need_registration = true;
-  }
 
   format.Outdent();
   format("}\n");
@@ -2438,6 +2407,42 @@
   }
 }
 
+void MessageGenerator::GenerateConstexprConstructor(io::Printer* printer) {
+  Formatter format(printer, variables_);
+
+  format(
+      "constexpr $classname$::$classname$(\n"
+      "  ::$proto_ns$::internal::ConstantInitialized)");
+  format.Indent();
+  const char* field_sep = ":";
+  const auto put_sep = [&] {
+    format("\n$1$ ", field_sep);
+    field_sep = ",";
+  };
+
+  if (!IsMapEntryMessage(descriptor_)) {
+    // Process non-oneof fields first.
+    for (auto field : optimized_order_) {
+      auto& gen = field_generators_.get(field);
+      put_sep();
+      gen.GenerateConstinitInitializer(printer);
+    }
+
+    if (IsAnyMessage(descriptor_, options_)) {
+      put_sep();
+      format("_any_metadata_(&type_url_, &value_)");
+    }
+
+    if (descriptor_->real_oneof_decl_count() != 0) {
+      put_sep();
+      format("_oneof_case_{}");
+    }
+  }
+
+  format.Outdent();
+  format("{}\n");
+}
+
 void MessageGenerator::GenerateConstructorBody(io::Printer* printer,
                                                std::vector<bool> processed,
                                                bool copy_constructor) const {
@@ -2664,14 +2669,6 @@
       "void $classname$::SetCachedSize(int size) const {\n"
       "  _cached_size_.Set(size);\n"
       "}\n");
-
-  format(
-      "const $classname$& $classname$::default_instance() {\n"
-      "  "
-      "::$proto_ns$::internal::InitSCC(&::$scc_info$.base)"
-      ";\n"
-      "  return *internal_default_instance();\n"
-      "}\n\n");
 }
 
 void MessageGenerator::GenerateSourceInProto2Namespace(io::Printer* printer) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index 933386f..4e3f4b9 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -124,6 +124,10 @@
   // Generate the arena-specific destructor code.
   void GenerateArenaDestructorCode(io::Printer* printer);
 
+  // Generate the constexpr constructor for constant initialization of the
+  // default instance.
+  void GenerateConstexprConstructor(io::Printer* printer);
+
   // Generate standard Message methods.
   void GenerateClear(io::Printer* printer);
   void GenerateOneofClear(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index f1a5cef..7bad24c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -466,6 +466,12 @@
       "    *$field_member$);\n");
 }
 
+void MessageFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  format("$name$_(nullptr)");
+}
+
 // ===================================================================
 
 MessageOneofFieldGenerator::MessageOneofFieldGenerator(
@@ -809,6 +815,12 @@
       "}\n");
 }
 
+void RepeatedMessageFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  format("$name$_()");
+}
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h
index fe5cf13..4b4b8ea 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h
@@ -68,6 +68,7 @@
   void GenerateCopyConstructorCode(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
+  void GenerateConstinitInitializer(io::Printer* printer) const;
 
  protected:
   const bool implicit_weak_field_;
@@ -117,6 +118,7 @@
   void GenerateCopyConstructorCode(io::Printer* printer) const {}
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
+  void GenerateConstinitInitializer(io::Printer* printer) const;
 
  private:
   const bool implicit_weak_field_;
diff --git a/src/google/protobuf/compiler/cpp/cpp_names.h b/src/google/protobuf/compiler/cpp/cpp_names.h
new file mode 100644
index 0000000..9bede74
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_names.h
@@ -0,0 +1,85 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_NAMES_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_NAMES_H__
+
+#include <string>
+
+#include <google/protobuf/port_def.inc>
+
+namespace google {
+namespace protobuf {
+
+class Descriptor;
+class EnumDescriptor;
+class FieldDescriptor;
+
+namespace compiler {
+namespace cpp {
+
+// Returns the unqualified C++ name.
+//
+// For example, if you had:
+//   package foo.bar;
+//   message Baz { message Qux {} }
+// Then the non-qualified version would be:
+//   Baz_Qux
+std::string ClassName(const Descriptor* descriptor);
+std::string ClassName(const EnumDescriptor* enum_descriptor);
+
+// Returns the fully qualified C++ name.
+//
+// For example, if you had:
+//   package foo.bar;
+//   message Baz { message Qux {} }
+// Then the qualified ClassName for Qux would be:
+//   ::foo::bar::Baz_Qux
+std::string QualifiedClassName(const Descriptor* d);
+std::string QualifiedClassName(const EnumDescriptor* d);
+std::string QualifiedExtensionName(const FieldDescriptor* d);
+
+// Get the (unqualified) name that should be used for this field in C++ code.
+// The name is coerced to lower-case to emulate proto1 behavior.  People
+// should be using lowercase-with-underscores style for proto field names
+// anyway, so normally this just returns field->name().
+std::string FieldName(const FieldDescriptor* field);
+
+// Strips ".proto" or ".protodevel" from the end of a filename.
+PROTOC_EXPORT std::string StripProto(const std::string& filename);
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#include <google/protobuf/port_undef.inc>
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_NAMES_H__
diff --git a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
index 10e468b..31f3f0c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
@@ -36,13 +36,12 @@
 
 #include <memory>
 
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/compiler/cpp/cpp_generator.h>
 #include <google/protobuf/compiler/command_line_interface.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
-
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index 042776c..d840492 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -217,6 +217,12 @@
   }
 }
 
+void PrimitiveFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  format("$name$_($default$)");
+}
+
 // ===================================================================
 
 PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
@@ -470,6 +476,16 @@
   format("}\n");
 }
 
+void RepeatedPrimitiveFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  format("$name$_()");
+  if (descriptor_->is_packed() &&
+      HasGeneratedMethods(descriptor_->file(), options_)) {
+    format("\n, _$name$_cached_byte_size_()");
+  }
+}
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
index fe54ce3..394b304 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
@@ -61,6 +61,7 @@
   void GenerateCopyConstructorCode(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
+  void GenerateConstinitInitializer(io::Printer* printer) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
@@ -99,6 +100,7 @@
   void GenerateCopyConstructorCode(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
+  void GenerateConstinitInitializer(io::Printer* printer) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index beed6e5..3769437 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -399,6 +399,16 @@
       "    this->_internal_$name$());\n");
 }
 
+void StringFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  if (descriptor_->default_value_string().empty()) {
+    format("$name$_(&::$proto_ns$::internal::fixed_address_empty_string)");
+  } else {
+    format("$name$_(nullptr)");
+  }
+}
+
 // ===================================================================
 
 StringOneofFieldGenerator::StringOneofFieldGenerator(
@@ -818,6 +828,12 @@
       "}\n");
 }
 
+void RepeatedStringFieldGenerator::GenerateConstinitInitializer(
+    io::Printer* printer) const {
+  Formatter format(printer, variables_);
+  format("$name$_()");
+}
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h
index 91424d2..213f134 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h
@@ -65,6 +65,7 @@
   void GenerateDestructorCode(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
+  void GenerateConstinitInitializer(io::Printer* printer) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator);
@@ -107,6 +108,7 @@
   void GenerateCopyConstructorCode(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
   void GenerateByteSize(io::Printer* printer) const;
+  void GenerateConstinitInitializer(io::Printer* printer) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator);
diff --git a/src/google/protobuf/compiler/cpp/metadata_test.cc b/src/google/protobuf/compiler/cpp/metadata_test.cc
index a16c8b5..b5cac8f4 100644
--- a/src/google/protobuf/compiler/cpp/metadata_test.cc
+++ b/src/google/protobuf/compiler/cpp/metadata_test.cc
@@ -30,14 +30,13 @@
 
 #include <memory>
 
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/compiler/cpp/cpp_generator.h>
 #include <google/protobuf/compiler/annotation_test_util.h>
 #include <google/protobuf/compiler/command_line_interface.h>
 #include <google/protobuf/descriptor.pb.h>
-
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 
diff --git a/src/google/protobuf/compiler/importer.cc b/src/google/protobuf/compiler/importer.cc
index 23a4eff..c629b2e 100644
--- a/src/google/protobuf/compiler/importer.cc
+++ b/src/google/protobuf/compiler/importer.cc
@@ -497,8 +497,8 @@
   } while (ret != 0 && errno == EINTR);
 #if defined(_WIN32)
   if (ret == 0 && sb.st_mode & S_IFDIR) {
-      last_error_message_ = "Input file is a directory.";
-      return NULL;
+    last_error_message_ = "Input file is a directory.";
+    return NULL;
   }
 #else
   if (ret == 0 && S_ISDIR(sb.st_mode)) {
diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc
index d96ac7d..9706c6d 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -154,7 +154,7 @@
 
 void ImmutableEnumFieldGenerator::GenerateInterfaceMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "$deprecation$boolean has$capitalized_name$();\n");
@@ -171,7 +171,7 @@
 void ImmutableEnumFieldGenerator::GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_, "private int $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "@java.lang.Override $deprecation$public boolean "
@@ -203,7 +203,7 @@
 void ImmutableEnumFieldGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
   printer->Print(variables_, "private int $name$_ = $default_number$;\n");
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "@java.lang.Override $deprecation$public boolean "
@@ -287,7 +287,7 @@
 
 void ImmutableEnumFieldGenerator::GenerateMergingCode(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     printer->Print(variables_,
                    "if (other.has$capitalized_name$()) {\n"
                    "  set$capitalized_name$(other.get$capitalized_name$());\n"
@@ -305,7 +305,7 @@
 
 void ImmutableEnumFieldGenerator::GenerateBuildingCode(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     printer->Print(variables_,
                    "if ($get_has_field_bit_from_local$) {\n"
                    "  $set_has_field_bit_to_local$;\n"
@@ -389,15 +389,14 @@
 void ImmutableEnumOneofFieldGenerator::GenerateMembers(
     io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
+
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
     printer->Print(
@@ -426,16 +425,15 @@
 
 void ImmutableEnumOneofFieldGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
+
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
     printer->Print(
diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.cc b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
index b0b3b78..dfa051c 100644
--- a/src/google/protobuf/compiler/java/java_enum_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
@@ -142,7 +142,7 @@
 
 void ImmutableEnumFieldLiteGenerator::GenerateInterfaceMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "$deprecation$boolean has$capitalized_name$();\n");
@@ -160,7 +160,7 @@
     io::Printer* printer) const {
   printer->Print(variables_, "private int $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -214,7 +214,7 @@
 
 void ImmutableEnumFieldLiteGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -316,16 +316,15 @@
 void ImmutableEnumOneofFieldLiteGenerator::GenerateMembers(
     io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
+
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
     printer->Print(
@@ -393,16 +392,15 @@
 
 void ImmutableEnumOneofFieldLiteGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return instance.has$capitalized_name$();\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return instance.has$capitalized_name$();\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
+
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
     printer->Print(
diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc
index fb00110..5cdb00d 100644
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -387,7 +387,6 @@
   printer->Print("}\n");
 }
 
-
 void FileGenerator::GenerateDescriptorInitializationCodeForImmutable(
     io::Printer* printer) {
   printer->Print(
@@ -676,6 +675,7 @@
   }
 }
 
+
 bool FileGenerator::ShouldIncludeDependency(const FileDescriptor* descriptor,
                                             bool immutable_api) {
   return true;
diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc
index e9bc6f7..4f14802 100644
--- a/src/google/protobuf/compiler/java/java_helpers.cc
+++ b/src/google/protobuf/compiler/java/java_helpers.cc
@@ -41,6 +41,7 @@
 
 #include <google/protobuf/stubs/stringprintf.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/compiler/java/java_names.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/strutil.h>
diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
index 1ff4667..8cc2f5a 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -103,21 +103,11 @@
 std::string FileClassName(const FileDescriptor* file, bool immutable = true);
 
 // Returns the file's Java package name.
-std::string FileJavaPackage(const FileDescriptor* file);
 std::string FileJavaPackage(const FileDescriptor* file, bool immutable);
 
 // Returns output directory for the given package name.
 std::string JavaPackageToDir(std::string package_name);
 
-// TODO(xiaofeng): the following methods are kept for they are exposed
-// publicly in //net/proto2/compiler/java/public/names.h. They return
-// immutable names only and should be removed after mutable API is
-// integrated into google3.
-std::string ClassName(const Descriptor* descriptor);
-std::string ClassName(const EnumDescriptor* descriptor);
-std::string ClassName(const ServiceDescriptor* descriptor);
-std::string ClassName(const FileDescriptor* descriptor);
-
 // Comma-separate list of option-specified interfaces implemented by the
 // Message, to follow the "implements" declaration of the Message definition.
 std::string ExtraMessageInterfaces(const Descriptor* descriptor);
@@ -357,24 +347,22 @@
   return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2;
 }
 
-inline bool SupportFieldPresence(const FieldDescriptor* descriptor) {
-  // Note that while proto3 oneofs do conceptually support present, we return
-  // false for them because they do not offer a public hazzer. Therefore this
-  // method could be named HasHazzer().
-  return !descriptor->is_repeated() &&
-         (descriptor->message_type() || descriptor->has_optional_keyword() ||
-          IsProto2(descriptor->file()));
-}
-
 inline bool IsRealOneof(const FieldDescriptor* descriptor) {
   return descriptor->containing_oneof() &&
          !descriptor->containing_oneof()->is_synthetic();
 }
 
+inline bool HasHazzer(const FieldDescriptor* descriptor) {
+  return !descriptor->is_repeated() &&
+         (descriptor->message_type() || descriptor->has_optional_keyword() ||
+          IsProto2(descriptor->file()) || IsRealOneof(descriptor));
+}
+
 inline bool HasHasbit(const FieldDescriptor* descriptor) {
   // Note that currently message fields inside oneofs have hasbits. This is
   // surprising, as the oneof case should avoid any need for a hasbit. But if
   // you change this method to remove hasbits for oneofs, a few tests fail.
+  // TODO(b/124347790): remove hasbits for oneofs
   return !descriptor->is_repeated() &&
          (descriptor->has_optional_keyword() || IsProto2(descriptor->file()));
 }
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index 6623595..f9d4e43 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -491,6 +491,7 @@
     printer->Print("public static final int $constant_name$ = $number$;\n",
                    "constant_name", FieldConstantName(descriptor_->field(i)),
                    "number", StrCat(descriptor_->field(i)->number()));
+    printer->Annotate("constant_name", descriptor_->field(i));
     field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
     printer->Print("\n");
   }
diff --git a/src/google/protobuf/compiler/java/java_name_resolver.cc b/src/google/protobuf/compiler/java/java_name_resolver.cc
index f3c96c4..ed33dae 100644
--- a/src/google/protobuf/compiler/java/java_name_resolver.cc
+++ b/src/google/protobuf/compiler/java/java_name_resolver.cc
@@ -33,8 +33,9 @@
 #include <map>
 #include <string>
 
-#include <google/protobuf/compiler/code_generator.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_names.h>
+#include <google/protobuf/compiler/code_generator.h>
 #include <google/protobuf/stubs/substitute.h>
 
 namespace google {
diff --git a/src/google/protobuf/compiler/java/java_names.h b/src/google/protobuf/compiler/java/java_names.h
index 73a340e..313ace4 100644
--- a/src/google/protobuf/compiler/java/java_names.h
+++ b/src/google/protobuf/compiler/java/java_names.h
@@ -93,18 +93,6 @@
 //   Capitalized camel case name field name.
 std::string CapitalizedFieldName(const FieldDescriptor* descriptor);
 
-// Requires:
-//   descriptor != NULL
-// Returns:
-//   Primitive Java type name for the field.
-const char* PrimitiveTypeName(const FieldDescriptor* descriptor);
-
-// Requires:
-//   descriptor != NULL
-// Returns:
-//   Boes primitive Java type name for the field.
-const char* BoxedPrimitiveTypeName(const FieldDescriptor* descriptor);
-
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_plugin_unittest.cc b/src/google/protobuf/compiler/java/java_plugin_unittest.cc
index 744b2c8..3bdd53b 100644
--- a/src/google/protobuf/compiler/java/java_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/java/java_plugin_unittest.cc
@@ -36,13 +36,12 @@
 
 #include <memory>
 
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/compiler/java/java_generator.h>
 #include <google/protobuf/compiler/command_line_interface.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
-
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index f06e8fb..8bc68b7 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -204,7 +204,7 @@
 
 void ImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "$deprecation$boolean has$capitalized_name$();\n");
@@ -217,7 +217,7 @@
     io::Printer* printer) const {
   printer->Print(variables_, "private $field_type$ $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -241,7 +241,7 @@
     io::Printer* printer) const {
   printer->Print(variables_, "private $field_type$ $name$_ $default_init$;\n");
 
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -318,7 +318,7 @@
 
 void ImmutablePrimitiveFieldGenerator::GenerateMergingCode(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     printer->Print(variables_,
                    "if (other.has$capitalized_name$()) {\n"
                    "  set$capitalized_name$(other.get$capitalized_name$());\n"
@@ -333,7 +333,7 @@
 
 void ImmutablePrimitiveFieldGenerator::GenerateBuildingCode(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     if (IsDefaultValueJavaDefault(descriptor_)) {
       printer->Print(variables_,
                      "if ($get_has_field_bit_from_local$) {\n"
@@ -497,16 +497,14 @@
 void ImmutablePrimitiveOneofFieldGenerator::GenerateMembers(
     io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(variables_,
@@ -522,15 +520,13 @@
 
 void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(variables_,
diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
index 59dba76..e807066 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
@@ -193,7 +193,7 @@
 
 void ImmutablePrimitiveFieldLiteGenerator::GenerateInterfaceMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "$deprecation$boolean has$capitalized_name$();\n");
@@ -213,7 +213,7 @@
   }
   printer->Print(variables_, "private $field_type$ $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -259,7 +259,7 @@
 
 void ImmutablePrimitiveFieldLiteGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -345,16 +345,14 @@
 void ImmutablePrimitiveOneofFieldLiteGenerator::GenerateMembers(
     io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(variables_,
@@ -395,16 +393,14 @@
 
 void ImmutablePrimitiveOneofFieldLiteGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return instance.has$capitalized_name$();\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return instance.has$capitalized_name$();\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(variables_,
diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.cc b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
index f673e68..45943d7 100644
--- a/src/google/protobuf/compiler/java/java_shared_code_generator.cc
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
@@ -36,6 +36,7 @@
 
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/compiler/java/java_names.h>
 #include <google/protobuf/compiler/code_generator.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/printer.h>
diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc
index 548f898..485fcf8 100644
--- a/src/google/protobuf/compiler/java/java_string_field.cc
+++ b/src/google/protobuf/compiler/java/java_string_field.cc
@@ -188,7 +188,7 @@
 // UnmodifiableLazyStringList.
 void ImmutableStringFieldGenerator::GenerateInterfaceMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "$deprecation$boolean has$capitalized_name$();\n");
@@ -207,7 +207,7 @@
   printer->Print(variables_, "private volatile java.lang.Object $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
 
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -266,7 +266,7 @@
     io::Printer* printer) const {
   printer->Print(variables_,
                  "private java.lang.Object $name$_ $default_init$;\n");
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -384,7 +384,7 @@
 
 void ImmutableStringFieldGenerator::GenerateMergingCode(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     // Allow a slight breach of abstraction here in order to avoid forcing
     // all string fields to Strings when copying fields from a Message.
     printer->Print(variables_,
@@ -404,7 +404,7 @@
 
 void ImmutableStringFieldGenerator::GenerateBuildingCode(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     printer->Print(variables_,
                    "if ($get_has_field_bit_from_local$) {\n"
                    "  $set_has_field_bit_to_local$;\n"
@@ -484,16 +484,13 @@
 void ImmutableStringOneofFieldGenerator::GenerateMembers(
     io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(
@@ -551,16 +548,14 @@
 
 void ImmutableStringOneofFieldGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(
diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.cc b/src/google/protobuf/compiler/java/java_string_field_lite.cc
index 06a3c25..25bfedc 100644
--- a/src/google/protobuf/compiler/java/java_string_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_string_field_lite.cc
@@ -157,7 +157,7 @@
 //     shouldn't be necessary or used on devices.
 void ImmutableStringFieldLiteGenerator::GenerateInterfaceMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
                    "$deprecation$boolean has$capitalized_name$();\n");
@@ -176,7 +176,7 @@
   printer->Print(variables_, "private java.lang.String $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
 
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -238,7 +238,7 @@
 
 void ImmutableStringFieldLiteGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
+  if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(
         variables_,
@@ -337,17 +337,14 @@
 void ImmutableStringOneofFieldLiteGenerator::GenerateMembers(
     io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return $has_oneof_case_message$;\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return $has_oneof_case_message$;\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(
@@ -418,16 +415,14 @@
 
 void ImmutableStringOneofFieldLiteGenerator::GenerateBuilderMembers(
     io::Printer* printer) const {
-  if (SupportFieldPresence(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-    printer->Print(
-        variables_,
-        "@java.lang.Override\n"
-        "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
-        "  return instance.has$capitalized_name$();\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
-  }
+  GOOGLE_DCHECK(HasHazzer(descriptor_));
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  printer->Print(variables_,
+                 "@java.lang.Override\n"
+                 "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+                 "  return instance.has$capitalized_name$();\n"
+                 "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index cbb24a5..a413d74 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -2184,7 +2184,7 @@
 void StripFieldTypeName(DescriptorProto* proto) {
   for (int i = 0; i < proto->field_size(); ++i) {
     std::string type_name = proto->field(i).type_name();
-    std::string::size_type pos = type_name.find_last_of(".");
+    std::string::size_type pos = type_name.find_last_of('.');
     if (pos != std::string::npos) {
       proto->mutable_field(i)->mutable_type_name()->assign(
           type_name.begin() + pos + 1, type_name.end());
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index 58283cd..84a90f6 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -16,86 +16,69 @@
 #include <google/protobuf/port_def.inc>
 
 PROTOBUF_PRAGMA_INIT_SEG
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<6> scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_GeneratedCodeInfo_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fcompiler_2fplugin_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fcompiler_2fplugin_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
 PROTOBUF_NAMESPACE_OPEN
 namespace compiler {
-class VersionDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Version> _instance;
-} _Version_default_instance_;
-class CodeGeneratorRequestDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<CodeGeneratorRequest> _instance;
-} _CodeGeneratorRequest_default_instance_;
-class CodeGeneratorResponse_FileDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<CodeGeneratorResponse_File> _instance;
-} _CodeGeneratorResponse_File_default_instance_;
-class CodeGeneratorResponseDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<CodeGeneratorResponse> _instance;
-} _CodeGeneratorResponse_default_instance_;
+constexpr Version::Version(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : suffix_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , major_(0)
+  , minor_(0)
+  , patch_(0){}
+struct VersionDefaultTypeInternal {
+  constexpr VersionDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~VersionDefaultTypeInternal() {}
+  union {
+    Version _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY VersionDefaultTypeInternal _Version_default_instance_;
+constexpr CodeGeneratorRequest::CodeGeneratorRequest(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : file_to_generate_()
+  , proto_file_()
+  , parameter_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , compiler_version_(nullptr){}
+struct CodeGeneratorRequestDefaultTypeInternal {
+  constexpr CodeGeneratorRequestDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~CodeGeneratorRequestDefaultTypeInternal() {}
+  union {
+    CodeGeneratorRequest _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY CodeGeneratorRequestDefaultTypeInternal _CodeGeneratorRequest_default_instance_;
+constexpr CodeGeneratorResponse_File::CodeGeneratorResponse_File(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , insertion_point_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , content_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , generated_code_info_(nullptr){}
+struct CodeGeneratorResponse_FileDefaultTypeInternal {
+  constexpr CodeGeneratorResponse_FileDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~CodeGeneratorResponse_FileDefaultTypeInternal() {}
+  union {
+    CodeGeneratorResponse_File _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY CodeGeneratorResponse_FileDefaultTypeInternal _CodeGeneratorResponse_File_default_instance_;
+constexpr CodeGeneratorResponse::CodeGeneratorResponse(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : file_()
+  , error_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , supported_features_(PROTOBUF_ULONGLONG(0)){}
+struct CodeGeneratorResponseDefaultTypeInternal {
+  constexpr CodeGeneratorResponseDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~CodeGeneratorResponseDefaultTypeInternal() {}
+  union {
+    CodeGeneratorResponse _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY CodeGeneratorResponseDefaultTypeInternal _CodeGeneratorResponse_default_instance_;
 }  // namespace compiler
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorRequest_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 2, 0, InitDefaultsscc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto}, {
-      &scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base,}};
-
-static void InitDefaultsscc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorResponse_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto}, {
-      &scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base,}};
-
-static void InitDefaultsscc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorResponse_File_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto}, {
-      &scc_info_GeneratedCodeInfo_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::compiler::_Version_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::compiler::Version();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[4];
 static const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto[1];
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto = nullptr;
@@ -191,19 +174,18 @@
 static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps[1] = {
   &::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto,
 };
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_sccs[4] = {
-  &scc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base,
-  &scc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base,
-  &scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base,
-  &scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto, "google/protobuf/compiler/plugin.proto", 773,
-  &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once, descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_sccs, descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps, 4, 1,
+  false, false, 773, descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto, "google/protobuf/compiler/plugin.proto", 
+  &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once, descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps, 1, 4,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto, 4, file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto, file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto,
+  file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto, file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
+descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(int index) {
+  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
+  return descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto.file_level_metadata[index];
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
 PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fcompiler_2fplugin_2eproto(&descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
@@ -272,12 +254,11 @@
 }
 
 void Version::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  suffix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&major_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&patch_) -
-      reinterpret_cast<char*>(&major_)) + sizeof(patch_));
+suffix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&major_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&patch_) -
+    reinterpret_cast<char*>(&major_)) + sizeof(patch_));
 }
 
 Version::~Version() {
@@ -300,11 +281,6 @@
 void Version::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Version& Version::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Version::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.Version)
@@ -607,9 +583,8 @@
 }
 
 void CodeGeneratorRequest::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  parameter_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  compiler_version_ = nullptr;
+parameter_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+compiler_version_ = nullptr;
 }
 
 CodeGeneratorRequest::~CodeGeneratorRequest() {
@@ -633,11 +608,6 @@
 void CodeGeneratorRequest::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void CodeGeneratorRequest::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorRequest)
@@ -969,11 +939,10 @@
 }
 
 void CodeGeneratorResponse_File::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  insertion_point_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  content_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  generated_code_info_ = nullptr;
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+insertion_point_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+content_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+generated_code_info_ = nullptr;
 }
 
 CodeGeneratorResponse_File::~CodeGeneratorResponse_File() {
@@ -999,11 +968,6 @@
 void CodeGeneratorResponse_File::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void CodeGeneratorResponse_File::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse.File)
@@ -1310,9 +1274,8 @@
 }
 
 void CodeGeneratorResponse::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  error_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  supported_features_ = PROTOBUF_ULONGLONG(0);
+error_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+supported_features_ = PROTOBUF_ULONGLONG(0);
 }
 
 CodeGeneratorResponse::~CodeGeneratorResponse() {
@@ -1335,11 +1298,6 @@
 void CodeGeneratorResponse::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void CodeGeneratorResponse::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse)
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index 6f48efa..208b8ef 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -61,19 +61,20 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOC_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
+PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 namespace compiler {
 class CodeGeneratorRequest;
-class CodeGeneratorRequestDefaultTypeInternal;
+struct CodeGeneratorRequestDefaultTypeInternal;
 PROTOC_EXPORT extern CodeGeneratorRequestDefaultTypeInternal _CodeGeneratorRequest_default_instance_;
 class CodeGeneratorResponse;
-class CodeGeneratorResponseDefaultTypeInternal;
+struct CodeGeneratorResponseDefaultTypeInternal;
 PROTOC_EXPORT extern CodeGeneratorResponseDefaultTypeInternal _CodeGeneratorResponse_default_instance_;
 class CodeGeneratorResponse_File;
-class CodeGeneratorResponse_FileDefaultTypeInternal;
+struct CodeGeneratorResponse_FileDefaultTypeInternal;
 PROTOC_EXPORT extern CodeGeneratorResponse_FileDefaultTypeInternal _CodeGeneratorResponse_File_default_instance_;
 class Version;
-class VersionDefaultTypeInternal;
+struct VersionDefaultTypeInternal;
 PROTOC_EXPORT extern VersionDefaultTypeInternal _Version_default_instance_;
 }  // namespace compiler
 PROTOBUF_NAMESPACE_CLOSE
@@ -116,6 +117,7 @@
  public:
   inline Version() : Version(nullptr) {}
   virtual ~Version();
+  explicit constexpr Version(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Version(const Version& from);
   Version(Version&& from) noexcept
@@ -152,8 +154,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Version& default_instance();
-
+  static const Version& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Version* internal_default_instance() {
     return reinterpret_cast<const Version*>(
                &_Version_default_instance_);
@@ -219,8 +222,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -316,6 +318,7 @@
  public:
   inline CodeGeneratorRequest() : CodeGeneratorRequest(nullptr) {}
   virtual ~CodeGeneratorRequest();
+  explicit constexpr CodeGeneratorRequest(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   CodeGeneratorRequest(const CodeGeneratorRequest& from);
   CodeGeneratorRequest(CodeGeneratorRequest&& from) noexcept
@@ -352,8 +355,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const CodeGeneratorRequest& default_instance();
-
+  static const CodeGeneratorRequest& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const CodeGeneratorRequest* internal_default_instance() {
     return reinterpret_cast<const CodeGeneratorRequest*>(
                &_CodeGeneratorRequest_default_instance_);
@@ -419,8 +423,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -537,6 +540,7 @@
  public:
   inline CodeGeneratorResponse_File() : CodeGeneratorResponse_File(nullptr) {}
   virtual ~CodeGeneratorResponse_File();
+  explicit constexpr CodeGeneratorResponse_File(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from);
   CodeGeneratorResponse_File(CodeGeneratorResponse_File&& from) noexcept
@@ -573,8 +577,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const CodeGeneratorResponse_File& default_instance();
-
+  static const CodeGeneratorResponse_File& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const CodeGeneratorResponse_File* internal_default_instance() {
     return reinterpret_cast<const CodeGeneratorResponse_File*>(
                &_CodeGeneratorResponse_File_default_instance_);
@@ -640,8 +645,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -756,6 +760,7 @@
  public:
   inline CodeGeneratorResponse() : CodeGeneratorResponse(nullptr) {}
   virtual ~CodeGeneratorResponse();
+  explicit constexpr CodeGeneratorResponse(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   CodeGeneratorResponse(const CodeGeneratorResponse& from);
   CodeGeneratorResponse(CodeGeneratorResponse&& from) noexcept
@@ -792,8 +797,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const CodeGeneratorResponse& default_instance();
-
+  static const CodeGeneratorResponse& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const CodeGeneratorResponse* internal_default_instance() {
     return reinterpret_cast<const CodeGeneratorResponse*>(
                &_CodeGeneratorResponse_default_instance_);
@@ -859,8 +865,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index d849fa6..95de716 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -69,6 +69,7 @@
 
 namespace {
 
+
 // Returns the Python module name expected for a given .proto filename.
 std::string ModuleName(const std::string& filename) {
   std::string basename = StripProto(filename);
@@ -312,7 +313,6 @@
     }
   }
 
-
   // Completely serialize all Generate() calls on this instance.  The
   // thread-safety constraints of the CodeGenerator interface aren't clear so
   // just be as conservative as possible.  It's easier to relax this later if
@@ -675,7 +675,8 @@
     const ServiceDescriptor& descriptor) const {
   std::string name = ModuleLevelServiceDescriptorName(descriptor);
   if (!pure_python_workable_) {
-    name = "'" + descriptor.full_name() + "'";
+    name = "_descriptor.ServiceDescriptor(full_name='" +
+           descriptor.full_name() + "')";
   }
   printer_->Print("$descriptor_key$ = $descriptor_name$,\n", "descriptor_key",
                   kDescriptorKey, "descriptor_name", name);
@@ -872,7 +873,8 @@
   if (pure_python_workable_) {
     m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor);
   } else {
-    m["descriptor_name"] = "'" + message_descriptor.full_name() + "'";
+    m["descriptor_name"] = "_descriptor.Descriptor(full_name='" +
+                           message_descriptor.full_name() + "')";
   }
   printer_->Print(m, "'$descriptor_key$' : $descriptor_name$,\n");
   std::string module_name = ModuleName(file_->name());
diff --git a/src/google/protobuf/compiler/python/python_plugin_unittest.cc b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
index 8d7ef98..76ceef3 100644
--- a/src/google/protobuf/compiler/python/python_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
@@ -36,13 +36,12 @@
 
 #include <memory>
 
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/testing/file.h>
 #include <google/protobuf/compiler/command_line_interface.h>
 #include <google/protobuf/compiler/python/python_generator.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
-
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc
index ebc972c..a6935c7 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generator.cc
+++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc
@@ -242,8 +242,7 @@
 bool GenerateMessage(const Descriptor* message, io::Printer* printer,
                      std::string* error) {
   if (message->extension_range_count() > 0 || message->extension_count() > 0) {
-    *error = "Extensions are not yet supported for proto2 .proto files.";
-    return false;
+    GOOGLE_LOG(WARNING) << "Extensions are not yet supported for proto2 .proto files.";
   }
 
   // Don't generate MapEntry messages -- we use the Ruby extension's native
@@ -543,8 +542,7 @@
   // TODO: Remove this when ruby supports extensions for proto2 syntax.
   if (file->syntax() == FileDescriptor::SYNTAX_PROTO2 &&
       file->extension_count() > 0) {
-    *error = "Extensions are not yet supported for proto2 .proto files.";
-    return false;
+    GOOGLE_LOG(WARNING) << "Extensions are not yet supported for proto2 .proto files.";
   }
 
   printer->Print("Google::Protobuf::DescriptorPool.generated_pool.build do\n");
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index 7af37c5..03c4e2b 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -1090,7 +1090,7 @@
 
 bool DescriptorPool::Tables::AddSymbol(const std::string& full_name,
                                        Symbol symbol) {
-  if (InsertIfNotPresent(&symbols_by_name_, full_name.c_str(), symbol)) {
+  if (InsertIfNotPresent(&symbols_by_name_, full_name, symbol)) {
     symbols_after_checkpoint_.push_back(full_name.c_str());
     return true;
   } else {
@@ -1106,7 +1106,7 @@
 }
 
 bool DescriptorPool::Tables::AddFile(const FileDescriptor* file) {
-  if (InsertIfNotPresent(&files_by_name_, file->name().c_str(), file)) {
+  if (InsertIfNotPresent(&files_by_name_, file->name(), file)) {
     files_after_checkpoint_.push_back(file->name().c_str());
     return true;
   } else {
@@ -2626,6 +2626,8 @@
       const Descriptor::ReservedRange* range = reserved_range(i);
       if (range->end == range->start + 1) {
         strings::SubstituteAndAppend(contents, "$0, ", range->start);
+      } else if (range->end > FieldDescriptor::kMaxNumber) {
+        strings::SubstituteAndAppend(contents, "$0 to max, ", range->start);
       } else {
         strings::SubstituteAndAppend(contents, "$0 to $1, ", range->start,
                                   range->end - 1);
@@ -2829,6 +2831,8 @@
       const EnumDescriptor::ReservedRange* range = reserved_range(i);
       if (range->end == range->start) {
         strings::SubstituteAndAppend(contents, "$0, ", range->start);
+      } else if (range->end == INT_MAX) {
+        strings::SubstituteAndAppend(contents, "$0 to max, ", range->start);
       } else {
         strings::SubstituteAndAppend(contents, "$0 to $1, ", range->start,
                                   range->end);
@@ -4019,6 +4023,11 @@
   // Use its file as the parent instead.
   if (parent == nullptr) parent = file_;
 
+  if (full_name.find('\0') != std::string::npos) {
+    AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
+             "\"" + full_name + "\" contains null character.");
+    return false;
+  }
   if (tables_->AddSymbol(full_name, symbol)) {
     if (!file_tables_->AddAliasUnderParent(parent, name, symbol)) {
       // This is only possible if there was already an error adding something of
@@ -4059,6 +4068,11 @@
 void DescriptorBuilder::AddPackage(const std::string& name,
                                    const Message& proto,
                                    const FileDescriptor* file) {
+  if (name.find('\0') != std::string::npos) {
+    AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
+             "\"" + name + "\" contains null character.");
+    return;
+  }
   if (tables_->AddSymbol(name, Symbol(file))) {
     // Success.  Also add parent package, if any.
     std::string::size_type dot_pos = name.find_last_of('.');
@@ -4372,6 +4386,12 @@
   }
   result->pool_ = pool_;
 
+  if (result->name().find('\0') != std::string::npos) {
+    AddError(result->name(), proto, DescriptorPool::ErrorCollector::NAME,
+             "\"" + result->name() + "\" contains null character.");
+    return nullptr;
+  }
+
   // Add to tables.
   if (!tables_->AddFile(result)) {
     AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index d9590f8..443a8bf 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -16,527 +16,439 @@
 #include <google/protobuf/port_def.inc>
 
 PROTOBUF_PRAGMA_INIT_SEG
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<6> scc_info_DescriptorProto_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_DescriptorProto_ExtensionRange_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_DescriptorProto_ReservedRange_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<3> scc_info_EnumDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_EnumDescriptorProto_EnumReservedRange_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_EnumOptions_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_EnumValueDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_EnumValueOptions_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_ExtensionRangeOptions_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_FieldDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_FieldOptions_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<6> scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_FileOptions_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_GeneratedCodeInfo_Annotation_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_MessageOptions_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_MethodDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_MethodOptions_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_OneofDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_OneofOptions_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_ServiceDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_ServiceOptions_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_SourceCodeInfo_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_SourceCodeInfo_Location_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_UninterpretedOption_NamePart_google_2fprotobuf_2fdescriptor_2eproto;
 PROTOBUF_NAMESPACE_OPEN
-class FileDescriptorSetDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<FileDescriptorSet> _instance;
-} _FileDescriptorSet_default_instance_;
-class FileDescriptorProtoDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<FileDescriptorProto> _instance;
-} _FileDescriptorProto_default_instance_;
-class DescriptorProto_ExtensionRangeDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<DescriptorProto_ExtensionRange> _instance;
-} _DescriptorProto_ExtensionRange_default_instance_;
-class DescriptorProto_ReservedRangeDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<DescriptorProto_ReservedRange> _instance;
-} _DescriptorProto_ReservedRange_default_instance_;
-class DescriptorProtoDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<DescriptorProto> _instance;
-} _DescriptorProto_default_instance_;
-class ExtensionRangeOptionsDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<ExtensionRangeOptions> _instance;
-} _ExtensionRangeOptions_default_instance_;
-class FieldDescriptorProtoDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<FieldDescriptorProto> _instance;
-} _FieldDescriptorProto_default_instance_;
-class OneofDescriptorProtoDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<OneofDescriptorProto> _instance;
-} _OneofDescriptorProto_default_instance_;
-class EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<EnumDescriptorProto_EnumReservedRange> _instance;
-} _EnumDescriptorProto_EnumReservedRange_default_instance_;
-class EnumDescriptorProtoDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<EnumDescriptorProto> _instance;
-} _EnumDescriptorProto_default_instance_;
-class EnumValueDescriptorProtoDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<EnumValueDescriptorProto> _instance;
-} _EnumValueDescriptorProto_default_instance_;
-class ServiceDescriptorProtoDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<ServiceDescriptorProto> _instance;
-} _ServiceDescriptorProto_default_instance_;
-class MethodDescriptorProtoDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<MethodDescriptorProto> _instance;
-} _MethodDescriptorProto_default_instance_;
-class FileOptionsDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<FileOptions> _instance;
-} _FileOptions_default_instance_;
-class MessageOptionsDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<MessageOptions> _instance;
-} _MessageOptions_default_instance_;
-class FieldOptionsDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<FieldOptions> _instance;
-} _FieldOptions_default_instance_;
-class OneofOptionsDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<OneofOptions> _instance;
-} _OneofOptions_default_instance_;
-class EnumOptionsDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<EnumOptions> _instance;
-} _EnumOptions_default_instance_;
-class EnumValueOptionsDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<EnumValueOptions> _instance;
-} _EnumValueOptions_default_instance_;
-class ServiceOptionsDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<ServiceOptions> _instance;
-} _ServiceOptions_default_instance_;
-class MethodOptionsDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<MethodOptions> _instance;
-} _MethodOptions_default_instance_;
-class UninterpretedOption_NamePartDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<UninterpretedOption_NamePart> _instance;
-} _UninterpretedOption_NamePart_default_instance_;
-class UninterpretedOptionDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<UninterpretedOption> _instance;
-} _UninterpretedOption_default_instance_;
-class SourceCodeInfo_LocationDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<SourceCodeInfo_Location> _instance;
-} _SourceCodeInfo_Location_default_instance_;
-class SourceCodeInfoDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<SourceCodeInfo> _instance;
-} _SourceCodeInfo_default_instance_;
-class GeneratedCodeInfo_AnnotationDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<GeneratedCodeInfo_Annotation> _instance;
-} _GeneratedCodeInfo_Annotation_default_instance_;
-class GeneratedCodeInfoDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<GeneratedCodeInfo> _instance;
-} _GeneratedCodeInfo_default_instance_;
+constexpr FileDescriptorSet::FileDescriptorSet(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : file_(){}
+struct FileDescriptorSetDefaultTypeInternal {
+  constexpr FileDescriptorSetDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~FileDescriptorSetDefaultTypeInternal() {}
+  union {
+    FileDescriptorSet _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY FileDescriptorSetDefaultTypeInternal _FileDescriptorSet_default_instance_;
+constexpr FileDescriptorProto::FileDescriptorProto(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : dependency_()
+  , message_type_()
+  , enum_type_()
+  , service_()
+  , extension_()
+  , public_dependency_()
+  , weak_dependency_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , package_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , syntax_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , options_(nullptr)
+  , source_code_info_(nullptr){}
+struct FileDescriptorProtoDefaultTypeInternal {
+  constexpr FileDescriptorProtoDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~FileDescriptorProtoDefaultTypeInternal() {}
+  union {
+    FileDescriptorProto _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY FileDescriptorProtoDefaultTypeInternal _FileDescriptorProto_default_instance_;
+constexpr DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : options_(nullptr)
+  , start_(0)
+  , end_(0){}
+struct DescriptorProto_ExtensionRangeDefaultTypeInternal {
+  constexpr DescriptorProto_ExtensionRangeDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~DescriptorProto_ExtensionRangeDefaultTypeInternal() {}
+  union {
+    DescriptorProto_ExtensionRange _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY DescriptorProto_ExtensionRangeDefaultTypeInternal _DescriptorProto_ExtensionRange_default_instance_;
+constexpr DescriptorProto_ReservedRange::DescriptorProto_ReservedRange(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : start_(0)
+  , end_(0){}
+struct DescriptorProto_ReservedRangeDefaultTypeInternal {
+  constexpr DescriptorProto_ReservedRangeDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~DescriptorProto_ReservedRangeDefaultTypeInternal() {}
+  union {
+    DescriptorProto_ReservedRange _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY DescriptorProto_ReservedRangeDefaultTypeInternal _DescriptorProto_ReservedRange_default_instance_;
+constexpr DescriptorProto::DescriptorProto(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : field_()
+  , nested_type_()
+  , enum_type_()
+  , extension_range_()
+  , extension_()
+  , oneof_decl_()
+  , reserved_range_()
+  , reserved_name_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , options_(nullptr){}
+struct DescriptorProtoDefaultTypeInternal {
+  constexpr DescriptorProtoDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~DescriptorProtoDefaultTypeInternal() {}
+  union {
+    DescriptorProto _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY DescriptorProtoDefaultTypeInternal _DescriptorProto_default_instance_;
+constexpr ExtensionRangeOptions::ExtensionRangeOptions(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : uninterpreted_option_(){}
+struct ExtensionRangeOptionsDefaultTypeInternal {
+  constexpr ExtensionRangeOptionsDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~ExtensionRangeOptionsDefaultTypeInternal() {}
+  union {
+    ExtensionRangeOptions _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY ExtensionRangeOptionsDefaultTypeInternal _ExtensionRangeOptions_default_instance_;
+constexpr FieldDescriptorProto::FieldDescriptorProto(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , extendee_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , type_name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , default_value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , json_name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , options_(nullptr)
+  , number_(0)
+  , oneof_index_(0)
+  , proto3_optional_(false)
+  , label_(1)
+
+  , type_(1)
+{}
+struct FieldDescriptorProtoDefaultTypeInternal {
+  constexpr FieldDescriptorProtoDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~FieldDescriptorProtoDefaultTypeInternal() {}
+  union {
+    FieldDescriptorProto _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY FieldDescriptorProtoDefaultTypeInternal _FieldDescriptorProto_default_instance_;
+constexpr OneofDescriptorProto::OneofDescriptorProto(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , options_(nullptr){}
+struct OneofDescriptorProtoDefaultTypeInternal {
+  constexpr OneofDescriptorProtoDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~OneofDescriptorProtoDefaultTypeInternal() {}
+  union {
+    OneofDescriptorProto _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY OneofDescriptorProtoDefaultTypeInternal _OneofDescriptorProto_default_instance_;
+constexpr EnumDescriptorProto_EnumReservedRange::EnumDescriptorProto_EnumReservedRange(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : start_(0)
+  , end_(0){}
+struct EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal {
+  constexpr EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal() {}
+  union {
+    EnumDescriptorProto_EnumReservedRange _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal _EnumDescriptorProto_EnumReservedRange_default_instance_;
+constexpr EnumDescriptorProto::EnumDescriptorProto(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : value_()
+  , reserved_range_()
+  , reserved_name_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , options_(nullptr){}
+struct EnumDescriptorProtoDefaultTypeInternal {
+  constexpr EnumDescriptorProtoDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~EnumDescriptorProtoDefaultTypeInternal() {}
+  union {
+    EnumDescriptorProto _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY EnumDescriptorProtoDefaultTypeInternal _EnumDescriptorProto_default_instance_;
+constexpr EnumValueDescriptorProto::EnumValueDescriptorProto(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , options_(nullptr)
+  , number_(0){}
+struct EnumValueDescriptorProtoDefaultTypeInternal {
+  constexpr EnumValueDescriptorProtoDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~EnumValueDescriptorProtoDefaultTypeInternal() {}
+  union {
+    EnumValueDescriptorProto _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY EnumValueDescriptorProtoDefaultTypeInternal _EnumValueDescriptorProto_default_instance_;
+constexpr ServiceDescriptorProto::ServiceDescriptorProto(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : method_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , options_(nullptr){}
+struct ServiceDescriptorProtoDefaultTypeInternal {
+  constexpr ServiceDescriptorProtoDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~ServiceDescriptorProtoDefaultTypeInternal() {}
+  union {
+    ServiceDescriptorProto _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY ServiceDescriptorProtoDefaultTypeInternal _ServiceDescriptorProto_default_instance_;
+constexpr MethodDescriptorProto::MethodDescriptorProto(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , input_type_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , output_type_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , options_(nullptr)
+  , client_streaming_(false)
+  , server_streaming_(false){}
+struct MethodDescriptorProtoDefaultTypeInternal {
+  constexpr MethodDescriptorProtoDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~MethodDescriptorProtoDefaultTypeInternal() {}
+  union {
+    MethodDescriptorProto _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY MethodDescriptorProtoDefaultTypeInternal _MethodDescriptorProto_default_instance_;
+constexpr FileOptions::FileOptions(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : uninterpreted_option_()
+  , java_package_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , java_outer_classname_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , go_package_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , objc_class_prefix_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , csharp_namespace_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , swift_prefix_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , php_class_prefix_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , php_namespace_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , php_metadata_namespace_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , ruby_package_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , java_multiple_files_(false)
+  , java_generate_equals_and_hash_(false)
+  , java_string_check_utf8_(false)
+  , cc_generic_services_(false)
+  , java_generic_services_(false)
+  , py_generic_services_(false)
+  , php_generic_services_(false)
+  , deprecated_(false)
+  , optimize_for_(1)
+
+  , cc_enable_arenas_(true){}
+struct FileOptionsDefaultTypeInternal {
+  constexpr FileOptionsDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~FileOptionsDefaultTypeInternal() {}
+  union {
+    FileOptions _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY FileOptionsDefaultTypeInternal _FileOptions_default_instance_;
+constexpr MessageOptions::MessageOptions(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : uninterpreted_option_()
+  , message_set_wire_format_(false)
+  , no_standard_descriptor_accessor_(false)
+  , deprecated_(false)
+  , map_entry_(false){}
+struct MessageOptionsDefaultTypeInternal {
+  constexpr MessageOptionsDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~MessageOptionsDefaultTypeInternal() {}
+  union {
+    MessageOptions _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY MessageOptionsDefaultTypeInternal _MessageOptions_default_instance_;
+constexpr FieldOptions::FieldOptions(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : uninterpreted_option_()
+  , ctype_(0)
+
+  , packed_(false)
+  , lazy_(false)
+  , deprecated_(false)
+  , weak_(false)
+  , jstype_(0)
+{}
+struct FieldOptionsDefaultTypeInternal {
+  constexpr FieldOptionsDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~FieldOptionsDefaultTypeInternal() {}
+  union {
+    FieldOptions _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY FieldOptionsDefaultTypeInternal _FieldOptions_default_instance_;
+constexpr OneofOptions::OneofOptions(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : uninterpreted_option_(){}
+struct OneofOptionsDefaultTypeInternal {
+  constexpr OneofOptionsDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~OneofOptionsDefaultTypeInternal() {}
+  union {
+    OneofOptions _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY OneofOptionsDefaultTypeInternal _OneofOptions_default_instance_;
+constexpr EnumOptions::EnumOptions(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : uninterpreted_option_()
+  , allow_alias_(false)
+  , deprecated_(false){}
+struct EnumOptionsDefaultTypeInternal {
+  constexpr EnumOptionsDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~EnumOptionsDefaultTypeInternal() {}
+  union {
+    EnumOptions _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY EnumOptionsDefaultTypeInternal _EnumOptions_default_instance_;
+constexpr EnumValueOptions::EnumValueOptions(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : uninterpreted_option_()
+  , deprecated_(false){}
+struct EnumValueOptionsDefaultTypeInternal {
+  constexpr EnumValueOptionsDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~EnumValueOptionsDefaultTypeInternal() {}
+  union {
+    EnumValueOptions _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY EnumValueOptionsDefaultTypeInternal _EnumValueOptions_default_instance_;
+constexpr ServiceOptions::ServiceOptions(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : uninterpreted_option_()
+  , deprecated_(false){}
+struct ServiceOptionsDefaultTypeInternal {
+  constexpr ServiceOptionsDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~ServiceOptionsDefaultTypeInternal() {}
+  union {
+    ServiceOptions _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY ServiceOptionsDefaultTypeInternal _ServiceOptions_default_instance_;
+constexpr MethodOptions::MethodOptions(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : uninterpreted_option_()
+  , deprecated_(false)
+  , idempotency_level_(0)
+{}
+struct MethodOptionsDefaultTypeInternal {
+  constexpr MethodOptionsDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~MethodOptionsDefaultTypeInternal() {}
+  union {
+    MethodOptions _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY MethodOptionsDefaultTypeInternal _MethodOptions_default_instance_;
+constexpr UninterpretedOption_NamePart::UninterpretedOption_NamePart(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : name_part_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , is_extension_(false){}
+struct UninterpretedOption_NamePartDefaultTypeInternal {
+  constexpr UninterpretedOption_NamePartDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~UninterpretedOption_NamePartDefaultTypeInternal() {}
+  union {
+    UninterpretedOption_NamePart _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY UninterpretedOption_NamePartDefaultTypeInternal _UninterpretedOption_NamePart_default_instance_;
+constexpr UninterpretedOption::UninterpretedOption(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : name_()
+  , identifier_value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , string_value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , aggregate_value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , positive_int_value_(PROTOBUF_ULONGLONG(0))
+  , negative_int_value_(PROTOBUF_LONGLONG(0))
+  , double_value_(0){}
+struct UninterpretedOptionDefaultTypeInternal {
+  constexpr UninterpretedOptionDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~UninterpretedOptionDefaultTypeInternal() {}
+  union {
+    UninterpretedOption _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY UninterpretedOptionDefaultTypeInternal _UninterpretedOption_default_instance_;
+constexpr SourceCodeInfo_Location::SourceCodeInfo_Location(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : path_()
+  , _path_cached_byte_size_()
+  , span_()
+  , _span_cached_byte_size_()
+  , leading_detached_comments_()
+  , leading_comments_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , trailing_comments_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string){}
+struct SourceCodeInfo_LocationDefaultTypeInternal {
+  constexpr SourceCodeInfo_LocationDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~SourceCodeInfo_LocationDefaultTypeInternal() {}
+  union {
+    SourceCodeInfo_Location _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY SourceCodeInfo_LocationDefaultTypeInternal _SourceCodeInfo_Location_default_instance_;
+constexpr SourceCodeInfo::SourceCodeInfo(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : location_(){}
+struct SourceCodeInfoDefaultTypeInternal {
+  constexpr SourceCodeInfoDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~SourceCodeInfoDefaultTypeInternal() {}
+  union {
+    SourceCodeInfo _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY SourceCodeInfoDefaultTypeInternal _SourceCodeInfo_default_instance_;
+constexpr GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : path_()
+  , _path_cached_byte_size_()
+  , source_file_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , begin_(0)
+  , end_(0){}
+struct GeneratedCodeInfo_AnnotationDefaultTypeInternal {
+  constexpr GeneratedCodeInfo_AnnotationDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~GeneratedCodeInfo_AnnotationDefaultTypeInternal() {}
+  union {
+    GeneratedCodeInfo_Annotation _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY GeneratedCodeInfo_AnnotationDefaultTypeInternal _GeneratedCodeInfo_Annotation_default_instance_;
+constexpr GeneratedCodeInfo::GeneratedCodeInfo(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : annotation_(){}
+struct GeneratedCodeInfoDefaultTypeInternal {
+  constexpr GeneratedCodeInfoDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~GeneratedCodeInfoDefaultTypeInternal() {}
+  union {
+    GeneratedCodeInfo _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY GeneratedCodeInfoDefaultTypeInternal _GeneratedCodeInfo_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_DescriptorProto_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_DescriptorProto_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::DescriptorProto();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<6> scc_info_DescriptorProto_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 6, 0, InitDefaultsscc_info_DescriptorProto_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_FieldDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_EnumDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_DescriptorProto_ExtensionRange_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_OneofDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_MessageOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_DescriptorProto_ReservedRange_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_DescriptorProto_ExtensionRange_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_DescriptorProto_ExtensionRange_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_DescriptorProto_ExtensionRange_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_DescriptorProto_ExtensionRange_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_ExtensionRangeOptions_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_DescriptorProto_ReservedRange_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_DescriptorProto_ReservedRange_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_DescriptorProto_ReservedRange_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_DescriptorProto_ReservedRange_google_2fprotobuf_2fdescriptor_2eproto}, {}};
-
-static void InitDefaultsscc_info_EnumDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_EnumDescriptorProto_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::EnumDescriptorProto();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<3> scc_info_EnumDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 3, 0, InitDefaultsscc_info_EnumDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_EnumValueDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_EnumOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_EnumDescriptorProto_EnumReservedRange_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_EnumDescriptorProto_EnumReservedRange_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_EnumDescriptorProto_EnumReservedRange_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_EnumDescriptorProto_EnumReservedRange_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_EnumDescriptorProto_EnumReservedRange_google_2fprotobuf_2fdescriptor_2eproto}, {}};
-
-static void InitDefaultsscc_info_EnumOptions_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_EnumOptions_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::EnumOptions();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_EnumOptions_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_EnumOptions_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_EnumValueDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_EnumValueDescriptorProto_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_EnumValueDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_EnumValueDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_EnumValueOptions_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_EnumValueOptions_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_EnumValueOptions_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::EnumValueOptions();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_EnumValueOptions_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_EnumValueOptions_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_ExtensionRangeOptions_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_ExtensionRangeOptions_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_ExtensionRangeOptions_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_ExtensionRangeOptions_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_FieldDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_FieldDescriptorProto_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::FieldDescriptorProto();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_FieldDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_FieldDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_FieldOptions_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_FieldOptions_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_FieldOptions_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::FieldOptions();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_FieldOptions_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_FieldOptions_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_FileDescriptorProto_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::FileDescriptorProto();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<6> scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 6, 0, InitDefaultsscc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_DescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_EnumDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_ServiceDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_FieldDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_FileOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_SourceCodeInfo_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_FileDescriptorSet_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_FileDescriptorSet_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::FileDescriptorSet();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_FileDescriptorSet_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_FileDescriptorSet_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_FileOptions_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_FileOptions_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::FileOptions();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_FileOptions_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_FileOptions_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_GeneratedCodeInfo_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_GeneratedCodeInfo_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_GeneratedCodeInfo_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_GeneratedCodeInfo_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_GeneratedCodeInfo_Annotation_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_GeneratedCodeInfo_Annotation_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_GeneratedCodeInfo_Annotation_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_GeneratedCodeInfo_Annotation_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_GeneratedCodeInfo_Annotation_google_2fprotobuf_2fdescriptor_2eproto}, {}};
-
-static void InitDefaultsscc_info_MessageOptions_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_MessageOptions_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::MessageOptions();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_MessageOptions_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_MessageOptions_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_MethodDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_MethodDescriptorProto_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::MethodDescriptorProto();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_MethodDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_MethodDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_MethodOptions_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_MethodOptions_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_MethodOptions_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::MethodOptions();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_MethodOptions_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_MethodOptions_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_OneofDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_OneofDescriptorProto_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::OneofDescriptorProto();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_OneofDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_OneofDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_OneofOptions_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_OneofOptions_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_OneofOptions_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::OneofOptions();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_OneofOptions_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_OneofOptions_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_ServiceDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_ServiceDescriptorProto_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_ServiceDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 2, 0, InitDefaultsscc_info_ServiceDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_MethodDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-      &scc_info_ServiceOptions_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_ServiceOptions_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_ServiceOptions_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::ServiceOptions();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_ServiceOptions_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_ServiceOptions_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_SourceCodeInfo_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_SourceCodeInfo_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::SourceCodeInfo();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_SourceCodeInfo_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_SourceCodeInfo_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_SourceCodeInfo_Location_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_SourceCodeInfo_Location_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_SourceCodeInfo_Location_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_SourceCodeInfo_Location_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_SourceCodeInfo_Location_google_2fprotobuf_2fdescriptor_2eproto}, {}};
-
-static void InitDefaultsscc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_UninterpretedOption_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::UninterpretedOption();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto}, {
-      &scc_info_UninterpretedOption_NamePart_google_2fprotobuf_2fdescriptor_2eproto.base,}};
-
-static void InitDefaultsscc_info_UninterpretedOption_NamePart_google_2fprotobuf_2fdescriptor_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_UninterpretedOption_NamePart_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_UninterpretedOption_NamePart_google_2fprotobuf_2fdescriptor_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_UninterpretedOption_NamePart_google_2fprotobuf_2fdescriptor_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[27];
 static const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[6];
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fdescriptor_2eproto = nullptr;
@@ -1136,44 +1048,18 @@
   "rg/protobuf/types/descriptorpb\370\001\001\242\002\003GPB\252"
   "\002\032Google.Protobuf.Reflection"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_sccs[27] = {
-  &scc_info_DescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_DescriptorProto_ExtensionRange_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_DescriptorProto_ReservedRange_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_EnumDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_EnumDescriptorProto_EnumReservedRange_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_EnumOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_EnumValueDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_EnumValueOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_ExtensionRangeOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_FieldDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_FieldOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_FileDescriptorSet_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_FileOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_GeneratedCodeInfo_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_GeneratedCodeInfo_Annotation_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_MessageOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_MethodDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_MethodOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_OneofDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_OneofOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_ServiceDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_ServiceOptions_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_SourceCodeInfo_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_SourceCodeInfo_Location_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base,
-  &scc_info_UninterpretedOption_NamePart_google_2fprotobuf_2fdescriptor_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fdescriptor_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto, "google/protobuf/descriptor.proto", 6028,
-  &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_sccs, descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_deps, 27, 0,
+  false, false, 6028, descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto, "google/protobuf/descriptor.proto", 
+  &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, nullptr, 0, 27,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fdescriptor_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto, 27, file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto, file_level_service_descriptors_google_2fprotobuf_2fdescriptor_2eproto,
+  file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto, file_level_service_descriptors_google_2fprotobuf_2fdescriptor_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
+descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(int index) {
+  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
+  return descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[index];
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
 PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fdescriptor_2eproto(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
@@ -1368,7 +1254,6 @@
 }
 
 void FileDescriptorSet::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_FileDescriptorSet_google_2fprotobuf_2fdescriptor_2eproto.base);
 }
 
 FileDescriptorSet::~FileDescriptorSet() {
@@ -1390,11 +1275,6 @@
 void FileDescriptorSet::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const FileDescriptorSet& FileDescriptorSet::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_FileDescriptorSet_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void FileDescriptorSet::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FileDescriptorSet)
@@ -1633,14 +1513,13 @@
 }
 
 void FileDescriptorProto::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  syntax_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&options_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&source_code_info_) -
-      reinterpret_cast<char*>(&options_)) + sizeof(source_code_info_));
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+syntax_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&options_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&source_code_info_) -
+    reinterpret_cast<char*>(&options_)) + sizeof(source_code_info_));
 }
 
 FileDescriptorProto::~FileDescriptorProto() {
@@ -1667,11 +1546,6 @@
 void FileDescriptorProto::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const FileDescriptorProto& FileDescriptorProto::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void FileDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FileDescriptorProto)
@@ -2250,11 +2124,10 @@
 }
 
 void DescriptorProto_ExtensionRange::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_DescriptorProto_ExtensionRange_google_2fprotobuf_2fdescriptor_2eproto.base);
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&options_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&end_) -
-      reinterpret_cast<char*>(&options_)) + sizeof(end_));
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&options_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&end_) -
+    reinterpret_cast<char*>(&options_)) + sizeof(end_));
 }
 
 DescriptorProto_ExtensionRange::~DescriptorProto_ExtensionRange() {
@@ -2277,11 +2150,6 @@
 void DescriptorProto_ExtensionRange::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const DescriptorProto_ExtensionRange& DescriptorProto_ExtensionRange::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_DescriptorProto_ExtensionRange_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void DescriptorProto_ExtensionRange::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto.ExtensionRange)
@@ -2538,10 +2406,10 @@
 }
 
 void DescriptorProto_ReservedRange::SharedCtor() {
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&start_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&end_) -
-      reinterpret_cast<char*>(&start_)) + sizeof(end_));
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&start_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&end_) -
+    reinterpret_cast<char*>(&start_)) + sizeof(end_));
 }
 
 DescriptorProto_ReservedRange::~DescriptorProto_ReservedRange() {
@@ -2563,11 +2431,6 @@
 void DescriptorProto_ReservedRange::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const DescriptorProto_ReservedRange& DescriptorProto_ReservedRange::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_DescriptorProto_ReservedRange_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void DescriptorProto_ReservedRange::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto.ReservedRange)
@@ -2820,9 +2683,8 @@
 }
 
 void DescriptorProto::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_DescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  options_ = nullptr;
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+options_ = nullptr;
 }
 
 DescriptorProto::~DescriptorProto() {
@@ -2846,11 +2708,6 @@
 void DescriptorProto::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const DescriptorProto& DescriptorProto::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_DescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void DescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto)
@@ -3331,7 +3188,6 @@
 }
 
 void ExtensionRangeOptions::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_ExtensionRangeOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
 }
 
 ExtensionRangeOptions::~ExtensionRangeOptions() {
@@ -3353,11 +3209,6 @@
 void ExtensionRangeOptions::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const ExtensionRangeOptions& ExtensionRangeOptions::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_ExtensionRangeOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void ExtensionRangeOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.ExtensionRangeOptions)
@@ -3622,18 +3473,17 @@
 }
 
 void FieldDescriptorProto::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_FieldDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  extendee_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  type_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  default_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  json_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&options_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&proto3_optional_) -
-      reinterpret_cast<char*>(&options_)) + sizeof(proto3_optional_));
-  label_ = 1;
-  type_ = 1;
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+extendee_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+type_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+default_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+json_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&options_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&proto3_optional_) -
+    reinterpret_cast<char*>(&options_)) + sizeof(proto3_optional_));
+label_ = 1;
+type_ = 1;
 }
 
 FieldDescriptorProto::~FieldDescriptorProto() {
@@ -3661,11 +3511,6 @@
 void FieldDescriptorProto::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const FieldDescriptorProto& FieldDescriptorProto::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_FieldDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void FieldDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FieldDescriptorProto)
@@ -4201,9 +4046,8 @@
 }
 
 void OneofDescriptorProto::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_OneofDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  options_ = nullptr;
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+options_ = nullptr;
 }
 
 OneofDescriptorProto::~OneofDescriptorProto() {
@@ -4227,11 +4071,6 @@
 void OneofDescriptorProto::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const OneofDescriptorProto& OneofDescriptorProto::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_OneofDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void OneofDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.OneofDescriptorProto)
@@ -4466,10 +4305,10 @@
 }
 
 void EnumDescriptorProto_EnumReservedRange::SharedCtor() {
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&start_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&end_) -
-      reinterpret_cast<char*>(&start_)) + sizeof(end_));
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&start_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&end_) -
+    reinterpret_cast<char*>(&start_)) + sizeof(end_));
 }
 
 EnumDescriptorProto_EnumReservedRange::~EnumDescriptorProto_EnumReservedRange() {
@@ -4491,11 +4330,6 @@
 void EnumDescriptorProto_EnumReservedRange::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const EnumDescriptorProto_EnumReservedRange& EnumDescriptorProto_EnumReservedRange::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_EnumDescriptorProto_EnumReservedRange_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void EnumDescriptorProto_EnumReservedRange::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumDescriptorProto.EnumReservedRange)
@@ -4738,9 +4572,8 @@
 }
 
 void EnumDescriptorProto::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_EnumDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  options_ = nullptr;
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+options_ = nullptr;
 }
 
 EnumDescriptorProto::~EnumDescriptorProto() {
@@ -4764,11 +4597,6 @@
 void EnumDescriptorProto::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const EnumDescriptorProto& EnumDescriptorProto::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_EnumDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void EnumDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumDescriptorProto)
@@ -5117,12 +4945,11 @@
 }
 
 void EnumValueDescriptorProto::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_EnumValueDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&options_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&number_) -
-      reinterpret_cast<char*>(&options_)) + sizeof(number_));
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&options_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&number_) -
+    reinterpret_cast<char*>(&options_)) + sizeof(number_));
 }
 
 EnumValueDescriptorProto::~EnumValueDescriptorProto() {
@@ -5146,11 +4973,6 @@
 void EnumValueDescriptorProto::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const EnumValueDescriptorProto& EnumValueDescriptorProto::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_EnumValueDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void EnumValueDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValueDescriptorProto)
@@ -5430,9 +5252,8 @@
 }
 
 void ServiceDescriptorProto::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_ServiceDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  options_ = nullptr;
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+options_ = nullptr;
 }
 
 ServiceDescriptorProto::~ServiceDescriptorProto() {
@@ -5456,11 +5277,6 @@
 void ServiceDescriptorProto::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const ServiceDescriptorProto& ServiceDescriptorProto::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_ServiceDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void ServiceDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.ServiceDescriptorProto)
@@ -5763,14 +5579,13 @@
 }
 
 void MethodDescriptorProto::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_MethodDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  input_type_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  output_type_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&options_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&server_streaming_) -
-      reinterpret_cast<char*>(&options_)) + sizeof(server_streaming_));
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+input_type_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+output_type_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&options_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&server_streaming_) -
+    reinterpret_cast<char*>(&options_)) + sizeof(server_streaming_));
 }
 
 MethodDescriptorProto::~MethodDescriptorProto() {
@@ -5796,11 +5611,6 @@
 void MethodDescriptorProto::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const MethodDescriptorProto& MethodDescriptorProto::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_MethodDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void MethodDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.MethodDescriptorProto)
@@ -6266,23 +6076,22 @@
 }
 
 void FileOptions::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_FileOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  java_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  java_outer_classname_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  go_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  objc_class_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  csharp_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  swift_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  php_class_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  php_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  php_metadata_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ruby_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&java_multiple_files_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&deprecated_) -
-      reinterpret_cast<char*>(&java_multiple_files_)) + sizeof(deprecated_));
-  optimize_for_ = 1;
-  cc_enable_arenas_ = true;
+java_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+java_outer_classname_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+go_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+objc_class_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+csharp_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+swift_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+php_class_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+php_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+php_metadata_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+ruby_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&java_multiple_files_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&deprecated_) -
+    reinterpret_cast<char*>(&java_multiple_files_)) + sizeof(deprecated_));
+optimize_for_ = 1;
+cc_enable_arenas_ = true;
 }
 
 FileOptions::~FileOptions() {
@@ -6314,11 +6123,6 @@
 void FileOptions::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const FileOptions& FileOptions::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_FileOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void FileOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FileOptions)
@@ -7153,11 +6957,10 @@
 }
 
 void MessageOptions::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_MessageOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&message_set_wire_format_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&map_entry_) -
-      reinterpret_cast<char*>(&message_set_wire_format_)) + sizeof(map_entry_));
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&message_set_wire_format_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&map_entry_) -
+    reinterpret_cast<char*>(&message_set_wire_format_)) + sizeof(map_entry_));
 }
 
 MessageOptions::~MessageOptions() {
@@ -7179,11 +6982,6 @@
 void MessageOptions::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const MessageOptions& MessageOptions::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_MessageOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void MessageOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.MessageOptions)
@@ -7511,11 +7309,10 @@
 }
 
 void FieldOptions::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_FieldOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&ctype_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&jstype_) -
-      reinterpret_cast<char*>(&ctype_)) + sizeof(jstype_));
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&ctype_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&jstype_) -
+    reinterpret_cast<char*>(&ctype_)) + sizeof(jstype_));
 }
 
 FieldOptions::~FieldOptions() {
@@ -7537,11 +7334,6 @@
 void FieldOptions::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const FieldOptions& FieldOptions::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_FieldOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void FieldOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FieldOptions)
@@ -7905,7 +7697,6 @@
 }
 
 void OneofOptions::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_OneofOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
 }
 
 OneofOptions::~OneofOptions() {
@@ -7927,11 +7718,6 @@
 void OneofOptions::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const OneofOptions& OneofOptions::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_OneofOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void OneofOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.OneofOptions)
@@ -8138,11 +7924,10 @@
 }
 
 void EnumOptions::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_EnumOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&allow_alias_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&deprecated_) -
-      reinterpret_cast<char*>(&allow_alias_)) + sizeof(deprecated_));
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&allow_alias_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&deprecated_) -
+    reinterpret_cast<char*>(&allow_alias_)) + sizeof(deprecated_));
 }
 
 EnumOptions::~EnumOptions() {
@@ -8164,11 +7949,6 @@
 void EnumOptions::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const EnumOptions& EnumOptions::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_EnumOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void EnumOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumOptions)
@@ -8435,8 +8215,7 @@
 }
 
 void EnumValueOptions::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_EnumValueOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  deprecated_ = false;
+deprecated_ = false;
 }
 
 EnumValueOptions::~EnumValueOptions() {
@@ -8458,11 +8237,6 @@
 void EnumValueOptions::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const EnumValueOptions& EnumValueOptions::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_EnumValueOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void EnumValueOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValueOptions)
@@ -8694,8 +8468,7 @@
 }
 
 void ServiceOptions::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_ServiceOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  deprecated_ = false;
+deprecated_ = false;
 }
 
 ServiceOptions::~ServiceOptions() {
@@ -8717,11 +8490,6 @@
 void ServiceOptions::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const ServiceOptions& ServiceOptions::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_ServiceOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void ServiceOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.ServiceOptions)
@@ -8958,11 +8726,10 @@
 }
 
 void MethodOptions::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_MethodOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&deprecated_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&idempotency_level_) -
-      reinterpret_cast<char*>(&deprecated_)) + sizeof(idempotency_level_));
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&deprecated_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&idempotency_level_) -
+    reinterpret_cast<char*>(&deprecated_)) + sizeof(idempotency_level_));
 }
 
 MethodOptions::~MethodOptions() {
@@ -8984,11 +8751,6 @@
 void MethodOptions::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const MethodOptions& MethodOptions::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_MethodOptions_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void MethodOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.MethodOptions)
@@ -9271,9 +9033,8 @@
 }
 
 void UninterpretedOption_NamePart::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_UninterpretedOption_NamePart_google_2fprotobuf_2fdescriptor_2eproto.base);
-  name_part_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  is_extension_ = false;
+name_part_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+is_extension_ = false;
 }
 
 UninterpretedOption_NamePart::~UninterpretedOption_NamePart() {
@@ -9296,11 +9057,6 @@
 void UninterpretedOption_NamePart::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const UninterpretedOption_NamePart& UninterpretedOption_NamePart::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_UninterpretedOption_NamePart_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void UninterpretedOption_NamePart::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.UninterpretedOption.NamePart)
@@ -9570,14 +9326,13 @@
 }
 
 void UninterpretedOption::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base);
-  identifier_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  aggregate_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&positive_int_value_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&double_value_) -
-      reinterpret_cast<char*>(&positive_int_value_)) + sizeof(double_value_));
+identifier_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+aggregate_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&positive_int_value_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&double_value_) -
+    reinterpret_cast<char*>(&positive_int_value_)) + sizeof(double_value_));
 }
 
 UninterpretedOption::~UninterpretedOption() {
@@ -9602,11 +9357,6 @@
 void UninterpretedOption::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const UninterpretedOption& UninterpretedOption::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void UninterpretedOption::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.UninterpretedOption)
@@ -9997,9 +9747,8 @@
 }
 
 void SourceCodeInfo_Location::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_SourceCodeInfo_Location_google_2fprotobuf_2fdescriptor_2eproto.base);
-  leading_comments_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  trailing_comments_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+leading_comments_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+trailing_comments_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
 SourceCodeInfo_Location::~SourceCodeInfo_Location() {
@@ -10023,11 +9772,6 @@
 void SourceCodeInfo_Location::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const SourceCodeInfo_Location& SourceCodeInfo_Location::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_SourceCodeInfo_Location_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void SourceCodeInfo_Location::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.SourceCodeInfo.Location)
@@ -10366,7 +10110,6 @@
 }
 
 void SourceCodeInfo::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_SourceCodeInfo_google_2fprotobuf_2fdescriptor_2eproto.base);
 }
 
 SourceCodeInfo::~SourceCodeInfo() {
@@ -10388,11 +10131,6 @@
 void SourceCodeInfo::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const SourceCodeInfo& SourceCodeInfo::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_SourceCodeInfo_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void SourceCodeInfo::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.SourceCodeInfo)
@@ -10585,12 +10323,11 @@
 }
 
 void GeneratedCodeInfo_Annotation::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_GeneratedCodeInfo_Annotation_google_2fprotobuf_2fdescriptor_2eproto.base);
-  source_file_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&begin_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&end_) -
-      reinterpret_cast<char*>(&begin_)) + sizeof(end_));
+source_file_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&begin_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&end_) -
+    reinterpret_cast<char*>(&begin_)) + sizeof(end_));
 }
 
 GeneratedCodeInfo_Annotation::~GeneratedCodeInfo_Annotation() {
@@ -10613,11 +10350,6 @@
 void GeneratedCodeInfo_Annotation::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const GeneratedCodeInfo_Annotation& GeneratedCodeInfo_Annotation::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_GeneratedCodeInfo_Annotation_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void GeneratedCodeInfo_Annotation::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.GeneratedCodeInfo.Annotation)
@@ -10905,7 +10637,6 @@
 }
 
 void GeneratedCodeInfo::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_GeneratedCodeInfo_google_2fprotobuf_2fdescriptor_2eproto.base);
 }
 
 GeneratedCodeInfo::~GeneratedCodeInfo() {
@@ -10927,11 +10658,6 @@
 void GeneratedCodeInfo::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const GeneratedCodeInfo& GeneratedCodeInfo::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_GeneratedCodeInfo_google_2fprotobuf_2fdescriptor_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void GeneratedCodeInfo::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.GeneratedCodeInfo)
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 381eede..cd4caa5 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -54,87 +54,88 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fdescriptor_2eproto;
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class DescriptorProto;
-class DescriptorProtoDefaultTypeInternal;
+struct DescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern DescriptorProtoDefaultTypeInternal _DescriptorProto_default_instance_;
 class DescriptorProto_ExtensionRange;
-class DescriptorProto_ExtensionRangeDefaultTypeInternal;
+struct DescriptorProto_ExtensionRangeDefaultTypeInternal;
 PROTOBUF_EXPORT extern DescriptorProto_ExtensionRangeDefaultTypeInternal _DescriptorProto_ExtensionRange_default_instance_;
 class DescriptorProto_ReservedRange;
-class DescriptorProto_ReservedRangeDefaultTypeInternal;
+struct DescriptorProto_ReservedRangeDefaultTypeInternal;
 PROTOBUF_EXPORT extern DescriptorProto_ReservedRangeDefaultTypeInternal _DescriptorProto_ReservedRange_default_instance_;
 class EnumDescriptorProto;
-class EnumDescriptorProtoDefaultTypeInternal;
+struct EnumDescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern EnumDescriptorProtoDefaultTypeInternal _EnumDescriptorProto_default_instance_;
 class EnumDescriptorProto_EnumReservedRange;
-class EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal;
+struct EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal;
 PROTOBUF_EXPORT extern EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal _EnumDescriptorProto_EnumReservedRange_default_instance_;
 class EnumOptions;
-class EnumOptionsDefaultTypeInternal;
+struct EnumOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern EnumOptionsDefaultTypeInternal _EnumOptions_default_instance_;
 class EnumValueDescriptorProto;
-class EnumValueDescriptorProtoDefaultTypeInternal;
+struct EnumValueDescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern EnumValueDescriptorProtoDefaultTypeInternal _EnumValueDescriptorProto_default_instance_;
 class EnumValueOptions;
-class EnumValueOptionsDefaultTypeInternal;
+struct EnumValueOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern EnumValueOptionsDefaultTypeInternal _EnumValueOptions_default_instance_;
 class ExtensionRangeOptions;
-class ExtensionRangeOptionsDefaultTypeInternal;
+struct ExtensionRangeOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern ExtensionRangeOptionsDefaultTypeInternal _ExtensionRangeOptions_default_instance_;
 class FieldDescriptorProto;
-class FieldDescriptorProtoDefaultTypeInternal;
+struct FieldDescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern FieldDescriptorProtoDefaultTypeInternal _FieldDescriptorProto_default_instance_;
 class FieldOptions;
-class FieldOptionsDefaultTypeInternal;
+struct FieldOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern FieldOptionsDefaultTypeInternal _FieldOptions_default_instance_;
 class FileDescriptorProto;
-class FileDescriptorProtoDefaultTypeInternal;
+struct FileDescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern FileDescriptorProtoDefaultTypeInternal _FileDescriptorProto_default_instance_;
 class FileDescriptorSet;
-class FileDescriptorSetDefaultTypeInternal;
+struct FileDescriptorSetDefaultTypeInternal;
 PROTOBUF_EXPORT extern FileDescriptorSetDefaultTypeInternal _FileDescriptorSet_default_instance_;
 class FileOptions;
-class FileOptionsDefaultTypeInternal;
+struct FileOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern FileOptionsDefaultTypeInternal _FileOptions_default_instance_;
 class GeneratedCodeInfo;
-class GeneratedCodeInfoDefaultTypeInternal;
+struct GeneratedCodeInfoDefaultTypeInternal;
 PROTOBUF_EXPORT extern GeneratedCodeInfoDefaultTypeInternal _GeneratedCodeInfo_default_instance_;
 class GeneratedCodeInfo_Annotation;
-class GeneratedCodeInfo_AnnotationDefaultTypeInternal;
+struct GeneratedCodeInfo_AnnotationDefaultTypeInternal;
 PROTOBUF_EXPORT extern GeneratedCodeInfo_AnnotationDefaultTypeInternal _GeneratedCodeInfo_Annotation_default_instance_;
 class MessageOptions;
-class MessageOptionsDefaultTypeInternal;
+struct MessageOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern MessageOptionsDefaultTypeInternal _MessageOptions_default_instance_;
 class MethodDescriptorProto;
-class MethodDescriptorProtoDefaultTypeInternal;
+struct MethodDescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern MethodDescriptorProtoDefaultTypeInternal _MethodDescriptorProto_default_instance_;
 class MethodOptions;
-class MethodOptionsDefaultTypeInternal;
+struct MethodOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern MethodOptionsDefaultTypeInternal _MethodOptions_default_instance_;
 class OneofDescriptorProto;
-class OneofDescriptorProtoDefaultTypeInternal;
+struct OneofDescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern OneofDescriptorProtoDefaultTypeInternal _OneofDescriptorProto_default_instance_;
 class OneofOptions;
-class OneofOptionsDefaultTypeInternal;
+struct OneofOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern OneofOptionsDefaultTypeInternal _OneofOptions_default_instance_;
 class ServiceDescriptorProto;
-class ServiceDescriptorProtoDefaultTypeInternal;
+struct ServiceDescriptorProtoDefaultTypeInternal;
 PROTOBUF_EXPORT extern ServiceDescriptorProtoDefaultTypeInternal _ServiceDescriptorProto_default_instance_;
 class ServiceOptions;
-class ServiceOptionsDefaultTypeInternal;
+struct ServiceOptionsDefaultTypeInternal;
 PROTOBUF_EXPORT extern ServiceOptionsDefaultTypeInternal _ServiceOptions_default_instance_;
 class SourceCodeInfo;
-class SourceCodeInfoDefaultTypeInternal;
+struct SourceCodeInfoDefaultTypeInternal;
 PROTOBUF_EXPORT extern SourceCodeInfoDefaultTypeInternal _SourceCodeInfo_default_instance_;
 class SourceCodeInfo_Location;
-class SourceCodeInfo_LocationDefaultTypeInternal;
+struct SourceCodeInfo_LocationDefaultTypeInternal;
 PROTOBUF_EXPORT extern SourceCodeInfo_LocationDefaultTypeInternal _SourceCodeInfo_Location_default_instance_;
 class UninterpretedOption;
-class UninterpretedOptionDefaultTypeInternal;
+struct UninterpretedOptionDefaultTypeInternal;
 PROTOBUF_EXPORT extern UninterpretedOptionDefaultTypeInternal _UninterpretedOption_default_instance_;
 class UninterpretedOption_NamePart;
-class UninterpretedOption_NamePartDefaultTypeInternal;
+struct UninterpretedOption_NamePartDefaultTypeInternal;
 PROTOBUF_EXPORT extern UninterpretedOption_NamePartDefaultTypeInternal _UninterpretedOption_NamePart_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -334,6 +335,7 @@
  public:
   inline FileDescriptorSet() : FileDescriptorSet(nullptr) {}
   virtual ~FileDescriptorSet();
+  explicit constexpr FileDescriptorSet(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FileDescriptorSet(const FileDescriptorSet& from);
   FileDescriptorSet(FileDescriptorSet&& from) noexcept
@@ -370,8 +372,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const FileDescriptorSet& default_instance();
-
+  static const FileDescriptorSet& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const FileDescriptorSet* internal_default_instance() {
     return reinterpret_cast<const FileDescriptorSet*>(
                &_FileDescriptorSet_default_instance_);
@@ -437,8 +440,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -486,6 +488,7 @@
  public:
   inline FileDescriptorProto() : FileDescriptorProto(nullptr) {}
   virtual ~FileDescriptorProto();
+  explicit constexpr FileDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FileDescriptorProto(const FileDescriptorProto& from);
   FileDescriptorProto(FileDescriptorProto&& from) noexcept
@@ -522,8 +525,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const FileDescriptorProto& default_instance();
-
+  static const FileDescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const FileDescriptorProto* internal_default_instance() {
     return reinterpret_cast<const FileDescriptorProto*>(
                &_FileDescriptorProto_default_instance_);
@@ -589,8 +593,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -879,6 +882,7 @@
  public:
   inline DescriptorProto_ExtensionRange() : DescriptorProto_ExtensionRange(nullptr) {}
   virtual ~DescriptorProto_ExtensionRange();
+  explicit constexpr DescriptorProto_ExtensionRange(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from);
   DescriptorProto_ExtensionRange(DescriptorProto_ExtensionRange&& from) noexcept
@@ -915,8 +919,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const DescriptorProto_ExtensionRange& default_instance();
-
+  static const DescriptorProto_ExtensionRange& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const DescriptorProto_ExtensionRange* internal_default_instance() {
     return reinterpret_cast<const DescriptorProto_ExtensionRange*>(
                &_DescriptorProto_ExtensionRange_default_instance_);
@@ -982,8 +987,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -1062,6 +1066,7 @@
  public:
   inline DescriptorProto_ReservedRange() : DescriptorProto_ReservedRange(nullptr) {}
   virtual ~DescriptorProto_ReservedRange();
+  explicit constexpr DescriptorProto_ReservedRange(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   DescriptorProto_ReservedRange(const DescriptorProto_ReservedRange& from);
   DescriptorProto_ReservedRange(DescriptorProto_ReservedRange&& from) noexcept
@@ -1098,8 +1103,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const DescriptorProto_ReservedRange& default_instance();
-
+  static const DescriptorProto_ReservedRange& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const DescriptorProto_ReservedRange* internal_default_instance() {
     return reinterpret_cast<const DescriptorProto_ReservedRange*>(
                &_DescriptorProto_ReservedRange_default_instance_);
@@ -1165,8 +1171,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -1225,6 +1230,7 @@
  public:
   inline DescriptorProto() : DescriptorProto(nullptr) {}
   virtual ~DescriptorProto();
+  explicit constexpr DescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   DescriptorProto(const DescriptorProto& from);
   DescriptorProto(DescriptorProto&& from) noexcept
@@ -1261,8 +1267,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const DescriptorProto& default_instance();
-
+  static const DescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const DescriptorProto* internal_default_instance() {
     return reinterpret_cast<const DescriptorProto*>(
                &_DescriptorProto_default_instance_);
@@ -1328,8 +1335,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -1569,6 +1575,7 @@
  public:
   inline ExtensionRangeOptions() : ExtensionRangeOptions(nullptr) {}
   virtual ~ExtensionRangeOptions();
+  explicit constexpr ExtensionRangeOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   ExtensionRangeOptions(const ExtensionRangeOptions& from);
   ExtensionRangeOptions(ExtensionRangeOptions&& from) noexcept
@@ -1605,8 +1612,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const ExtensionRangeOptions& default_instance();
-
+  static const ExtensionRangeOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const ExtensionRangeOptions* internal_default_instance() {
     return reinterpret_cast<const ExtensionRangeOptions*>(
                &_ExtensionRangeOptions_default_instance_);
@@ -1672,8 +1680,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -1724,6 +1731,7 @@
  public:
   inline FieldDescriptorProto() : FieldDescriptorProto(nullptr) {}
   virtual ~FieldDescriptorProto();
+  explicit constexpr FieldDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FieldDescriptorProto(const FieldDescriptorProto& from);
   FieldDescriptorProto(FieldDescriptorProto&& from) noexcept
@@ -1760,8 +1768,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const FieldDescriptorProto& default_instance();
-
+  static const FieldDescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const FieldDescriptorProto* internal_default_instance() {
     return reinterpret_cast<const FieldDescriptorProto*>(
                &_FieldDescriptorProto_default_instance_);
@@ -1827,8 +1836,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -2156,6 +2164,7 @@
  public:
   inline OneofDescriptorProto() : OneofDescriptorProto(nullptr) {}
   virtual ~OneofDescriptorProto();
+  explicit constexpr OneofDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   OneofDescriptorProto(const OneofDescriptorProto& from);
   OneofDescriptorProto(OneofDescriptorProto&& from) noexcept
@@ -2192,8 +2201,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const OneofDescriptorProto& default_instance();
-
+  static const OneofDescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const OneofDescriptorProto* internal_default_instance() {
     return reinterpret_cast<const OneofDescriptorProto*>(
                &_OneofDescriptorProto_default_instance_);
@@ -2259,8 +2269,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -2331,6 +2340,7 @@
  public:
   inline EnumDescriptorProto_EnumReservedRange() : EnumDescriptorProto_EnumReservedRange(nullptr) {}
   virtual ~EnumDescriptorProto_EnumReservedRange();
+  explicit constexpr EnumDescriptorProto_EnumReservedRange(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumDescriptorProto_EnumReservedRange(const EnumDescriptorProto_EnumReservedRange& from);
   EnumDescriptorProto_EnumReservedRange(EnumDescriptorProto_EnumReservedRange&& from) noexcept
@@ -2367,8 +2377,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const EnumDescriptorProto_EnumReservedRange& default_instance();
-
+  static const EnumDescriptorProto_EnumReservedRange& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const EnumDescriptorProto_EnumReservedRange* internal_default_instance() {
     return reinterpret_cast<const EnumDescriptorProto_EnumReservedRange*>(
                &_EnumDescriptorProto_EnumReservedRange_default_instance_);
@@ -2434,8 +2445,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -2494,6 +2504,7 @@
  public:
   inline EnumDescriptorProto() : EnumDescriptorProto(nullptr) {}
   virtual ~EnumDescriptorProto();
+  explicit constexpr EnumDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumDescriptorProto(const EnumDescriptorProto& from);
   EnumDescriptorProto(EnumDescriptorProto&& from) noexcept
@@ -2530,8 +2541,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const EnumDescriptorProto& default_instance();
-
+  static const EnumDescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const EnumDescriptorProto* internal_default_instance() {
     return reinterpret_cast<const EnumDescriptorProto*>(
                &_EnumDescriptorProto_default_instance_);
@@ -2597,8 +2609,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -2737,6 +2748,7 @@
  public:
   inline EnumValueDescriptorProto() : EnumValueDescriptorProto(nullptr) {}
   virtual ~EnumValueDescriptorProto();
+  explicit constexpr EnumValueDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumValueDescriptorProto(const EnumValueDescriptorProto& from);
   EnumValueDescriptorProto(EnumValueDescriptorProto&& from) noexcept
@@ -2773,8 +2785,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const EnumValueDescriptorProto& default_instance();
-
+  static const EnumValueDescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const EnumValueDescriptorProto* internal_default_instance() {
     return reinterpret_cast<const EnumValueDescriptorProto*>(
                &_EnumValueDescriptorProto_default_instance_);
@@ -2840,8 +2853,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -2927,6 +2939,7 @@
  public:
   inline ServiceDescriptorProto() : ServiceDescriptorProto(nullptr) {}
   virtual ~ServiceDescriptorProto();
+  explicit constexpr ServiceDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   ServiceDescriptorProto(const ServiceDescriptorProto& from);
   ServiceDescriptorProto(ServiceDescriptorProto&& from) noexcept
@@ -2963,8 +2976,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const ServiceDescriptorProto& default_instance();
-
+  static const ServiceDescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const ServiceDescriptorProto* internal_default_instance() {
     return reinterpret_cast<const ServiceDescriptorProto*>(
                &_ServiceDescriptorProto_default_instance_);
@@ -3030,8 +3044,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -3122,6 +3135,7 @@
  public:
   inline MethodDescriptorProto() : MethodDescriptorProto(nullptr) {}
   virtual ~MethodDescriptorProto();
+  explicit constexpr MethodDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   MethodDescriptorProto(const MethodDescriptorProto& from);
   MethodDescriptorProto(MethodDescriptorProto&& from) noexcept
@@ -3158,8 +3172,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const MethodDescriptorProto& default_instance();
-
+  static const MethodDescriptorProto& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const MethodDescriptorProto* internal_default_instance() {
     return reinterpret_cast<const MethodDescriptorProto*>(
                &_MethodDescriptorProto_default_instance_);
@@ -3225,8 +3240,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -3371,6 +3385,7 @@
  public:
   inline FileOptions() : FileOptions(nullptr) {}
   virtual ~FileOptions();
+  explicit constexpr FileOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FileOptions(const FileOptions& from);
   FileOptions(FileOptions&& from) noexcept
@@ -3407,8 +3422,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const FileOptions& default_instance();
-
+  static const FileOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const FileOptions* internal_default_instance() {
     return reinterpret_cast<const FileOptions*>(
                &_FileOptions_default_instance_);
@@ -3474,8 +3490,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -3929,6 +3944,7 @@
  public:
   inline MessageOptions() : MessageOptions(nullptr) {}
   virtual ~MessageOptions();
+  explicit constexpr MessageOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   MessageOptions(const MessageOptions& from);
   MessageOptions(MessageOptions&& from) noexcept
@@ -3965,8 +3981,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const MessageOptions& default_instance();
-
+  static const MessageOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const MessageOptions* internal_default_instance() {
     return reinterpret_cast<const MessageOptions*>(
                &_MessageOptions_default_instance_);
@@ -4032,8 +4049,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -4145,6 +4161,7 @@
  public:
   inline FieldOptions() : FieldOptions(nullptr) {}
   virtual ~FieldOptions();
+  explicit constexpr FieldOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FieldOptions(const FieldOptions& from);
   FieldOptions(FieldOptions&& from) noexcept
@@ -4181,8 +4198,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const FieldOptions& default_instance();
-
+  static const FieldOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const FieldOptions* internal_default_instance() {
     return reinterpret_cast<const FieldOptions*>(
                &_FieldOptions_default_instance_);
@@ -4248,8 +4266,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -4455,6 +4472,7 @@
  public:
   inline OneofOptions() : OneofOptions(nullptr) {}
   virtual ~OneofOptions();
+  explicit constexpr OneofOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   OneofOptions(const OneofOptions& from);
   OneofOptions(OneofOptions&& from) noexcept
@@ -4491,8 +4509,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const OneofOptions& default_instance();
-
+  static const OneofOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const OneofOptions* internal_default_instance() {
     return reinterpret_cast<const OneofOptions*>(
                &_OneofOptions_default_instance_);
@@ -4558,8 +4577,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -4610,6 +4628,7 @@
  public:
   inline EnumOptions() : EnumOptions(nullptr) {}
   virtual ~EnumOptions();
+  explicit constexpr EnumOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumOptions(const EnumOptions& from);
   EnumOptions(EnumOptions&& from) noexcept
@@ -4646,8 +4665,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const EnumOptions& default_instance();
-
+  static const EnumOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const EnumOptions* internal_default_instance() {
     return reinterpret_cast<const EnumOptions*>(
                &_EnumOptions_default_instance_);
@@ -4713,8 +4733,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -4796,6 +4815,7 @@
  public:
   inline EnumValueOptions() : EnumValueOptions(nullptr) {}
   virtual ~EnumValueOptions();
+  explicit constexpr EnumValueOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumValueOptions(const EnumValueOptions& from);
   EnumValueOptions(EnumValueOptions&& from) noexcept
@@ -4832,8 +4852,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const EnumValueOptions& default_instance();
-
+  static const EnumValueOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const EnumValueOptions* internal_default_instance() {
     return reinterpret_cast<const EnumValueOptions*>(
                &_EnumValueOptions_default_instance_);
@@ -4899,8 +4920,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -4967,6 +4987,7 @@
  public:
   inline ServiceOptions() : ServiceOptions(nullptr) {}
   virtual ~ServiceOptions();
+  explicit constexpr ServiceOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   ServiceOptions(const ServiceOptions& from);
   ServiceOptions(ServiceOptions&& from) noexcept
@@ -5003,8 +5024,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const ServiceOptions& default_instance();
-
+  static const ServiceOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const ServiceOptions* internal_default_instance() {
     return reinterpret_cast<const ServiceOptions*>(
                &_ServiceOptions_default_instance_);
@@ -5070,8 +5092,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -5138,6 +5159,7 @@
  public:
   inline MethodOptions() : MethodOptions(nullptr) {}
   virtual ~MethodOptions();
+  explicit constexpr MethodOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   MethodOptions(const MethodOptions& from);
   MethodOptions(MethodOptions&& from) noexcept
@@ -5174,8 +5196,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const MethodOptions& default_instance();
-
+  static const MethodOptions& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const MethodOptions* internal_default_instance() {
     return reinterpret_cast<const MethodOptions*>(
                &_MethodOptions_default_instance_);
@@ -5241,8 +5264,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -5356,6 +5378,7 @@
  public:
   inline UninterpretedOption_NamePart() : UninterpretedOption_NamePart(nullptr) {}
   virtual ~UninterpretedOption_NamePart();
+  explicit constexpr UninterpretedOption_NamePart(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from);
   UninterpretedOption_NamePart(UninterpretedOption_NamePart&& from) noexcept
@@ -5392,8 +5415,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const UninterpretedOption_NamePart& default_instance();
-
+  static const UninterpretedOption_NamePart& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const UninterpretedOption_NamePart* internal_default_instance() {
     return reinterpret_cast<const UninterpretedOption_NamePart*>(
                &_UninterpretedOption_NamePart_default_instance_);
@@ -5459,8 +5483,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -5529,6 +5552,7 @@
  public:
   inline UninterpretedOption() : UninterpretedOption(nullptr) {}
   virtual ~UninterpretedOption();
+  explicit constexpr UninterpretedOption(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   UninterpretedOption(const UninterpretedOption& from);
   UninterpretedOption(UninterpretedOption&& from) noexcept
@@ -5565,8 +5589,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const UninterpretedOption& default_instance();
-
+  static const UninterpretedOption& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const UninterpretedOption* internal_default_instance() {
     return reinterpret_cast<const UninterpretedOption*>(
                &_UninterpretedOption_default_instance_);
@@ -5632,8 +5657,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -5795,6 +5819,7 @@
  public:
   inline SourceCodeInfo_Location() : SourceCodeInfo_Location(nullptr) {}
   virtual ~SourceCodeInfo_Location();
+  explicit constexpr SourceCodeInfo_Location(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   SourceCodeInfo_Location(const SourceCodeInfo_Location& from);
   SourceCodeInfo_Location(SourceCodeInfo_Location&& from) noexcept
@@ -5831,8 +5856,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const SourceCodeInfo_Location& default_instance();
-
+  static const SourceCodeInfo_Location& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const SourceCodeInfo_Location* internal_default_instance() {
     return reinterpret_cast<const SourceCodeInfo_Location*>(
                &_SourceCodeInfo_Location_default_instance_);
@@ -5898,8 +5924,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -6048,6 +6073,7 @@
  public:
   inline SourceCodeInfo() : SourceCodeInfo(nullptr) {}
   virtual ~SourceCodeInfo();
+  explicit constexpr SourceCodeInfo(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   SourceCodeInfo(const SourceCodeInfo& from);
   SourceCodeInfo(SourceCodeInfo&& from) noexcept
@@ -6084,8 +6110,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const SourceCodeInfo& default_instance();
-
+  static const SourceCodeInfo& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const SourceCodeInfo* internal_default_instance() {
     return reinterpret_cast<const SourceCodeInfo*>(
                &_SourceCodeInfo_default_instance_);
@@ -6151,8 +6178,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -6202,6 +6228,7 @@
  public:
   inline GeneratedCodeInfo_Annotation() : GeneratedCodeInfo_Annotation(nullptr) {}
   virtual ~GeneratedCodeInfo_Annotation();
+  explicit constexpr GeneratedCodeInfo_Annotation(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   GeneratedCodeInfo_Annotation(const GeneratedCodeInfo_Annotation& from);
   GeneratedCodeInfo_Annotation(GeneratedCodeInfo_Annotation&& from) noexcept
@@ -6238,8 +6265,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const GeneratedCodeInfo_Annotation& default_instance();
-
+  static const GeneratedCodeInfo_Annotation& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const GeneratedCodeInfo_Annotation* internal_default_instance() {
     return reinterpret_cast<const GeneratedCodeInfo_Annotation*>(
                &_GeneratedCodeInfo_Annotation_default_instance_);
@@ -6305,8 +6333,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -6412,6 +6439,7 @@
  public:
   inline GeneratedCodeInfo() : GeneratedCodeInfo(nullptr) {}
   virtual ~GeneratedCodeInfo();
+  explicit constexpr GeneratedCodeInfo(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   GeneratedCodeInfo(const GeneratedCodeInfo& from);
   GeneratedCodeInfo(GeneratedCodeInfo&& from) noexcept
@@ -6448,8 +6476,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const GeneratedCodeInfo& default_instance();
-
+  static const GeneratedCodeInfo& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const GeneratedCodeInfo* internal_default_instance() {
     return reinterpret_cast<const GeneratedCodeInfo*>(
                &_GeneratedCodeInfo_default_instance_);
@@ -6515,8 +6544,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index 2521d92..b454ed5 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -3816,6 +3816,45 @@
       "foo.proto: foo.$: NAME: \"$\" is not a valid identifier.\n");
 }
 
+// 'str' is a static C-style string that may contain '\0'
+#define STATIC_STR(str) std::string((str), sizeof(str) - 1)
+
+TEST_F(ValidationErrorTest, NullCharSymbolName) {
+  BuildFileWithErrors(
+      "name: \"bar.proto\" "
+      "package: \"foo\""
+      "message_type { "
+      "  name: '\\000\\001\\013.Bar' "
+      "  field { name: \"foo\" number:  9 label:LABEL_OPTIONAL type:TYPE_INT32 "
+      "} "
+      "}",
+      STATIC_STR("bar.proto: foo.\0\x1\v.Bar: NAME: \"\0\x1\v.Bar\" is not a "
+                 "valid identifier.\nbar.proto: foo.\0\x1\v.Bar: NAME: "
+                 "\"\0\x1\v.Bar\" is not a valid identifier.\nbar.proto: "
+                 "foo.\0\x1\v.Bar: NAME: \"\0\x1\v.Bar\" is not a valid "
+                 "identifier.\nbar.proto: foo.\0\x1\v.Bar: NAME: "
+                 "\"\0\x1\v.Bar\" is not a valid identifier.\nbar.proto: "
+                 "foo.\0\x1\v.Bar.foo: NAME: \"foo.\0\x1\v.Bar.foo\" contains "
+                 "null character.\nbar.proto: foo.\0\x1\v.Bar: NAME: "
+                 "\"foo.\0\x1\v.Bar\" contains null character.\n"));
+}
+
+TEST_F(ValidationErrorTest, NullCharFileName) {
+  BuildFileWithErrors(
+      "name: \"bar\\000\\001\\013.proto\" "
+      "package: \"outer.foo\"",
+      STATIC_STR("bar\0\x1\v.proto: bar\0\x1\v.proto: NAME: "
+                 "\"bar\0\x1\v.proto\" contains null character.\n"));
+}
+
+TEST_F(ValidationErrorTest, NullCharPackageName) {
+  BuildFileWithErrors(
+      "name: \"bar.proto\" "
+      "package: \"\\000\\001\\013.\"",
+      STATIC_STR("bar.proto: \0\x1\v.: NAME: \"\0\x1\v.\" contains null "
+                 "character.\n"));
+}
+
 TEST_F(ValidationErrorTest, MissingFileName) {
   BuildFileWithErrors("",
 
@@ -4031,6 +4070,32 @@
       file->DebugString());
 }
 
+TEST_F(ValidationErrorTest, DebugStringReservedRangeMax) {
+  const FileDescriptor* file = BuildFile(strings::Substitute(
+      "name: \"foo.proto\" "
+      "enum_type { "
+      "  name: \"Bar\""
+      "  value { name:\"BAR\" number:1 }"
+      "  reserved_range { start: 5 end: $0 }"
+      "}"
+      "message_type {"
+      "  name: \"Foo\""
+      "  reserved_range { start: 5 end: $1 }"
+      "}",
+      std::numeric_limits<int>::max(), FieldDescriptor::kMaxNumber + 1));
+
+  ASSERT_EQ(
+      "syntax = \"proto2\";\n\n"
+      "enum Bar {\n"
+      "  BAR = 1;\n"
+      "  reserved 5 to max;\n"
+      "}\n\n"
+      "message Foo {\n"
+      "  reserved 5 to max;\n"
+      "}\n\n",
+      file->DebugString());
+}
+
 TEST_F(ValidationErrorTest, EnumReservedFieldError) {
   BuildFileWithErrors(
       "name: \"foo.proto\" "
diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc
index 87f54df..d7e4e00 100644
--- a/src/google/protobuf/duration.pb.cc
+++ b/src/google/protobuf/duration.pb.cc
@@ -17,24 +17,20 @@
 
 PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class DurationDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Duration> _instance;
-} _Duration_default_instance_;
+constexpr Duration::Duration(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : seconds_(PROTOBUF_LONGLONG(0))
+  , nanos_(0){}
+struct DurationDefaultTypeInternal {
+  constexpr DurationDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~DurationDefaultTypeInternal() {}
+  union {
+    Duration _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY DurationDefaultTypeInternal _Duration_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_Duration_google_2fprotobuf_2fduration_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Duration_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Duration();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Duration_google_2fprotobuf_2fduration_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Duration_google_2fprotobuf_2fduration_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fduration_2eproto[1];
 static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fduration_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fduration_2eproto = nullptr;
@@ -64,18 +60,18 @@
   "uf/types/known/durationpb\370\001\001\242\002\003GPB\252\002\036Goo"
   "gle.Protobuf.WellKnownTypesb\006proto3"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fduration_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fduration_2eproto_sccs[1] = {
-  &scc_info_Duration_google_2fprotobuf_2fduration_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fduration_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fduration_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fduration_2eproto, "google/protobuf/duration.proto", 235,
-  &descriptor_table_google_2fprotobuf_2fduration_2eproto_once, descriptor_table_google_2fprotobuf_2fduration_2eproto_sccs, descriptor_table_google_2fprotobuf_2fduration_2eproto_deps, 1, 0,
+  false, false, 235, descriptor_table_protodef_google_2fprotobuf_2fduration_2eproto, "google/protobuf/duration.proto", 
+  &descriptor_table_google_2fprotobuf_2fduration_2eproto_once, nullptr, 0, 1,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fduration_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fduration_2eproto, 1, file_level_enum_descriptors_google_2fprotobuf_2fduration_2eproto, file_level_service_descriptors_google_2fprotobuf_2fduration_2eproto,
+  file_level_metadata_google_2fprotobuf_2fduration_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fduration_2eproto, file_level_service_descriptors_google_2fprotobuf_2fduration_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
+descriptor_table_google_2fprotobuf_2fduration_2eproto_metadata_getter(int index) {
+  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fduration_2eproto);
+  return descriptor_table_google_2fprotobuf_2fduration_2eproto.file_level_metadata[index];
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
 PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fduration_2eproto(&descriptor_table_google_2fprotobuf_2fduration_2eproto);
@@ -103,10 +99,10 @@
 }
 
 void Duration::SharedCtor() {
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&seconds_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&nanos_) -
-      reinterpret_cast<char*>(&seconds_)) + sizeof(nanos_));
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&seconds_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&nanos_) -
+    reinterpret_cast<char*>(&seconds_)) + sizeof(nanos_));
 }
 
 Duration::~Duration() {
@@ -128,11 +124,6 @@
 void Duration::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Duration& Duration::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Duration_google_2fprotobuf_2fduration_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Duration::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Duration)
diff --git a/src/google/protobuf/duration.pb.h b/src/google/protobuf/duration.pb.h
index ec648a4..2065a85 100644
--- a/src/google/protobuf/duration.pb.h
+++ b/src/google/protobuf/duration.pb.h
@@ -53,9 +53,10 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fduration_2eproto;
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fduration_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class Duration;
-class DurationDefaultTypeInternal;
+struct DurationDefaultTypeInternal;
 PROTOBUF_EXPORT extern DurationDefaultTypeInternal _Duration_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -70,6 +71,7 @@
  public:
   inline Duration() : Duration(nullptr) {}
   virtual ~Duration();
+  explicit constexpr Duration(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Duration(const Duration& from);
   Duration(Duration&& from) noexcept
@@ -99,8 +101,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Duration& default_instance();
-
+  static const Duration& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Duration* internal_default_instance() {
     return reinterpret_cast<const Duration*>(
                &_Duration_default_instance_);
@@ -166,8 +169,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fduration_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fduration_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fduration_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
index 3a48494..0a52804 100644
--- a/src/google/protobuf/dynamic_message.cc
+++ b/src/google/protobuf/dynamic_message.cc
@@ -67,6 +67,7 @@
 #include <algorithm>
 #include <cstddef>
 #include <memory>
+#include <new>
 #include <unordered_map>
 
 #include <google/protobuf/descriptor.pb.h>
@@ -256,38 +257,10 @@
 
 class DynamicMessage : public Message {
  public:
-  struct TypeInfo {
-    int size;
-    int has_bits_offset;
-    int oneof_case_offset;
-    int extensions_offset;
-
-    // Not owned by the TypeInfo.
-    DynamicMessageFactory* factory;  // The factory that created this object.
-    const DescriptorPool* pool;      // The factory's DescriptorPool.
-    const Descriptor* type;          // Type of this DynamicMessage.
-
-    // Warning:  The order in which the following pointers are defined is
-    //   important (the prototype must be deleted *before* the offsets).
-    std::unique_ptr<uint32[]> offsets;
-    std::unique_ptr<uint32[]> has_bits_indices;
-    std::unique_ptr<const Reflection> reflection;
-    // Don't use a unique_ptr to hold the prototype: the destructor for
-    // DynamicMessage needs to know whether it is the prototype, and does so by
-    // looking back at this field. This would assume details about the
-    // implementation of unique_ptr.
-    const DynamicMessage* prototype;
-    int weak_field_map_offset;  // The offset for the weak_field_map;
-
-    TypeInfo() : prototype(NULL) {}
-
-    ~TypeInfo() { delete prototype; }
-  };
-
-  DynamicMessage(const TypeInfo* type_info);
+  explicit DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info);
 
   // This should only be used by GetPrototypeNoLock() to avoid dead lock.
-  DynamicMessage(TypeInfo* type_info, bool lock_factory);
+  DynamicMessage(DynamicMessageFactory::TypeInfo* type_info, bool lock_factory);
 
   ~DynamicMessage();
 
@@ -311,6 +284,9 @@
 
   Metadata GetMetadata() const override;
 
+#if defined(__cpp_lib_destroying_delete) && defined(__cpp_sized_deallocation)
+  static void operator delete(DynamicMessage* msg, std::destroying_delete_t);
+#else
   // We actually allocate more memory than sizeof(*this) when this
   // class's memory is allocated via the global operator new. Thus, we need to
   // manually call the global operator delete. Calling the destructor is taken
@@ -319,21 +295,18 @@
 #ifndef _MSC_VER
   static void operator delete(void* ptr) { ::operator delete(ptr); }
 #endif  // !_MSC_VER
+#endif
 
  private:
-  DynamicMessage(const TypeInfo* type_info, Arena* arena);
+  DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info,
+                 Arena* arena);
 
   void SharedCtor(bool lock_factory);
 
   // Needed to get the offset of the internal metadata member.
   friend class DynamicMessageFactory;
 
-  inline bool is_prototype() const {
-    return type_info_->prototype == this ||
-           // If type_info_->prototype is NULL, then we must be constructing
-           // the prototype now, which means we must be the prototype.
-           type_info_->prototype == NULL;
-  }
+  bool is_prototype() const;
 
   inline void* OffsetToPointer(int offset) {
     return reinterpret_cast<uint8*>(this) + offset;
@@ -342,24 +315,52 @@
     return reinterpret_cast<const uint8*>(this) + offset;
   }
 
-  const TypeInfo* type_info_;
+  const DynamicMessageFactory::TypeInfo* type_info_;
   mutable std::atomic<int> cached_byte_size_;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
 };
 
-DynamicMessage::DynamicMessage(const TypeInfo* type_info)
+struct DynamicMessageFactory::TypeInfo {
+  int size;
+  int has_bits_offset;
+  int oneof_case_offset;
+  int extensions_offset;
+
+  // Not owned by the TypeInfo.
+  DynamicMessageFactory* factory;  // The factory that created this object.
+  const DescriptorPool* pool;      // The factory's DescriptorPool.
+  const Descriptor* type;          // Type of this DynamicMessage.
+
+  // Warning:  The order in which the following pointers are defined is
+  //   important (the prototype must be deleted *before* the offsets).
+  std::unique_ptr<uint32[]> offsets;
+  std::unique_ptr<uint32[]> has_bits_indices;
+  std::unique_ptr<const Reflection> reflection;
+  // Don't use a unique_ptr to hold the prototype: the destructor for
+  // DynamicMessage needs to know whether it is the prototype, and does so by
+  // looking back at this field. This would assume details about the
+  // implementation of unique_ptr.
+  const DynamicMessage* prototype;
+  int weak_field_map_offset;  // The offset for the weak_field_map;
+
+  TypeInfo() : prototype(nullptr) {}
+
+  ~TypeInfo() { delete prototype; }
+};
+
+DynamicMessage::DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info)
     : type_info_(type_info), cached_byte_size_(0) {
   SharedCtor(true);
 }
 
-DynamicMessage::DynamicMessage(const TypeInfo* type_info, Arena* arena)
-    : Message(arena),
-      type_info_(type_info),
-      cached_byte_size_(0) {
+DynamicMessage::DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info,
+                               Arena* arena)
+    : Message(arena), type_info_(type_info), cached_byte_size_(0) {
   SharedCtor(true);
 }
 
-DynamicMessage::DynamicMessage(TypeInfo* type_info, bool lock_factory)
+DynamicMessage::DynamicMessage(DynamicMessageFactory::TypeInfo* type_info,
+                               bool lock_factory)
     : type_info_(type_info), cached_byte_size_(0) {
   // The prototype in type_info has to be set before creating the prototype
   // instance on memory. e.g., message Foo { map<int32, Foo> a = 1; }. When
@@ -484,6 +485,22 @@
   }
 }
 
+bool DynamicMessage::is_prototype() const {
+  return type_info_->prototype == this ||
+         // If type_info_->prototype is NULL, then we must be constructing
+         // the prototype now, which means we must be the prototype.
+         type_info_->prototype == nullptr;
+}
+
+#if defined(__cpp_lib_destroying_delete) && defined(__cpp_sized_deallocation)
+void DynamicMessage::operator delete(DynamicMessage* msg,
+                                     std::destroying_delete_t) {
+  const size_t size = msg->type_info_->size;
+  msg->~DynamicMessage();
+  ::operator delete(msg, size);
+}
+#endif
+
 DynamicMessage::~DynamicMessage() {
   const Descriptor* descriptor = type_info_->type;
 
@@ -517,11 +534,11 @@
           switch (field->options().ctype()) {
             default:
             case FieldOptions::STRING: {
-              const std::string* default_value =
-                  reinterpret_cast<const ArenaStringPtr*>(
-                      reinterpret_cast<const uint8*>(type_info_->prototype) +
-                      type_info_->offsets[i])
-                      ->GetPointer();
+              // Oneof string fields are never set as a default instance.
+              // We just need to pass some arbitrary default string to make it
+              // work. This allows us to not have the real default accessible
+              // from reflection.
+              const std::string* default_value = nullptr;
               reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(
                   default_value, NULL);
               break;
@@ -610,6 +627,7 @@
     const FieldDescriptor* field = descriptor->field(i);
     void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+        !field->options().weak() && !InRealOneof(field) &&
         !field->is_repeated()) {
       // For fields with message types, we need to cross-link with the
       // prototype for the field's type.
@@ -652,27 +670,14 @@
 
 // ===================================================================
 
-struct DynamicMessageFactory::PrototypeMap {
-  typedef std::unordered_map<const Descriptor*, const DynamicMessage::TypeInfo*>
-      Map;
-  Map map_;
-};
-
 DynamicMessageFactory::DynamicMessageFactory()
-    : pool_(NULL),
-      delegate_to_generated_factory_(false),
-      prototypes_(new PrototypeMap) {}
+    : pool_(nullptr), delegate_to_generated_factory_(false) {}
 
 DynamicMessageFactory::DynamicMessageFactory(const DescriptorPool* pool)
-    : pool_(pool),
-      delegate_to_generated_factory_(false),
-      prototypes_(new PrototypeMap) {}
+    : pool_(pool), delegate_to_generated_factory_(false) {}
 
 DynamicMessageFactory::~DynamicMessageFactory() {
-  for (PrototypeMap::Map::iterator iter = prototypes_->map_.begin();
-       iter != prototypes_->map_.end(); ++iter) {
-    DeleteDefaultOneofInstance(iter->second->type, iter->second->offsets.get(),
-                               iter->second->prototype);
+  for (auto iter = prototypes_.begin(); iter != prototypes_.end(); ++iter) {
     delete iter->second;
   }
 }
@@ -689,13 +694,13 @@
     return MessageFactory::generated_factory()->GetPrototype(type);
   }
 
-  const DynamicMessage::TypeInfo** target = &prototypes_->map_[type];
+  const TypeInfo** target = &prototypes_[type];
   if (*target != NULL) {
     // Already exists.
     return (*target)->prototype;
   }
 
-  DynamicMessage::TypeInfo* type_info = new DynamicMessage::TypeInfo;
+  TypeInfo* type_info = new TypeInfo;
   *target = type_info;
 
   type_info->type = type;
@@ -772,7 +777,6 @@
   // All the fields.
   //
   // TODO(b/31226269):  Optimize the order of fields to minimize padding.
-  int num_weak_fields = 0;
   for (int i = 0; i < type->field_count(); i++) {
     // Make sure field is aligned to avoid bus errors.
     // Oneof fields do not use any space.
@@ -807,14 +811,16 @@
     if (type->oneof_decl(i)->is_synthetic()) continue;
     for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
       const FieldDescriptor* field = type->oneof_decl(i)->field(j);
-      int field_size = OneofFieldSpaceUsed(field);
-      size = AlignTo(size, std::min(kSafeAlignment, field_size));
-      offsets[field->index()] = size;
-      size += field_size;
+      // oneof fields are not accessed through offsets, but we still have the
+      // entry from a legacy implementation. This should be removed at some
+      // point.
+      // Mark the field to prevent unintentional access through reflection.
+      // Don't use the top bit because that is for unused fields.
+      offsets[field->index()] = internal::kInvalidFieldOffsetTag;
     }
   }
-  size = AlignOffset(size);
-  // Allocate the prototype + oneof fields.
+
+  // Allocate the prototype fields.
   void* base = operator new(size);
   memset(base, 0, size);
 
@@ -822,12 +828,6 @@
   // of dynamic message to avoid dead lock.
   DynamicMessage* prototype = new (base) DynamicMessage(type_info, false);
 
-  if (real_oneof_count > 0 || num_weak_fields > 0) {
-    // Construct default oneof instance.
-    ConstructDefaultOneofInstance(type_info->type, type_info->offsets.get(),
-                                  prototype);
-  }
-
   internal::ReflectionSchema schema = {
       type_info->prototype,
       type_info->offsets.get(),
@@ -848,71 +848,6 @@
   return prototype;
 }
 
-void DynamicMessageFactory::ConstructDefaultOneofInstance(
-    const Descriptor* type, const uint32 offsets[],
-    void* default_oneof_or_weak_instance) {
-  for (int i = 0; i < type->oneof_decl_count(); i++) {
-    if (type->oneof_decl(i)->is_synthetic()) continue;
-    for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
-      const FieldDescriptor* field = type->oneof_decl(i)->field(j);
-      void* field_ptr =
-          reinterpret_cast<uint8*>(default_oneof_or_weak_instance) +
-          offsets[field->index()];
-      switch (field->cpp_type()) {
-#define HANDLE_TYPE(CPPTYPE, TYPE)                       \
-  case FieldDescriptor::CPPTYPE_##CPPTYPE:               \
-    new (field_ptr) TYPE(field->default_value_##TYPE()); \
-    break;
-
-        HANDLE_TYPE(INT32, int32);
-        HANDLE_TYPE(INT64, int64);
-        HANDLE_TYPE(UINT32, uint32);
-        HANDLE_TYPE(UINT64, uint64);
-        HANDLE_TYPE(DOUBLE, double);
-        HANDLE_TYPE(FLOAT, float);
-        HANDLE_TYPE(BOOL, bool);
-#undef HANDLE_TYPE
-
-        case FieldDescriptor::CPPTYPE_ENUM:
-          new (field_ptr) int(field->default_value_enum()->number());
-          break;
-        case FieldDescriptor::CPPTYPE_STRING:
-          switch (field->options().ctype()) {
-            default:
-            case FieldOptions::STRING:
-              ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr();
-              asp->UnsafeSetDefault(&field->default_value_string());
-              break;
-          }
-          break;
-
-        case FieldDescriptor::CPPTYPE_MESSAGE: {
-          new (field_ptr) Message*(NULL);
-          break;
-        }
-      }
-    }
-  }
-}
-
-void DynamicMessageFactory::DeleteDefaultOneofInstance(
-    const Descriptor* type, const uint32 offsets[],
-    const void* default_oneof_instance) {
-  for (int i = 0; i < type->oneof_decl_count(); i++) {
-    if (type->oneof_decl(i)->is_synthetic()) continue;
-    for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) {
-      const FieldDescriptor* field = type->oneof_decl(i)->field(j);
-      if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
-        switch (field->options().ctype()) {
-          default:
-          case FieldOptions::STRING:
-            break;
-        }
-      }
-    }
-  }
-}
-
 }  // namespace protobuf
 }  // namespace google
 
diff --git a/src/google/protobuf/dynamic_message.h b/src/google/protobuf/dynamic_message.h
index 9bd609f..b85e00f 100644
--- a/src/google/protobuf/dynamic_message.h
+++ b/src/google/protobuf/dynamic_message.h
@@ -40,6 +40,7 @@
 
 #include <algorithm>
 #include <memory>
+#include <unordered_map>
 #include <vector>
 
 #include <google/protobuf/stubs/common.h>
@@ -128,28 +129,13 @@
   const DescriptorPool* pool_;
   bool delegate_to_generated_factory_;
 
-  // This struct just contains a hash_map.  We can't #include <hash_map> from
-  // this header due to hacks needed for hash_map portability in the open source
-  // release.  Namely, stubs/hash.h, which defines hash_map portably, is not a
-  // public header (for good reason), but dynamic_message.h is, and public
-  // headers may only #include other public headers.
-  struct PrototypeMap;
-  std::unique_ptr<PrototypeMap> prototypes_;
+  struct TypeInfo;
+  std::unordered_map<const Descriptor*, const TypeInfo*> prototypes_;
   mutable internal::WrappedMutex prototypes_mutex_;
 
   friend class DynamicMessage;
   const Message* GetPrototypeNoLock(const Descriptor* type);
 
-  // Construct default oneof instance for reflection usage if oneof
-  // is defined.
-  static void ConstructDefaultOneofInstance(const Descriptor* type,
-                                            const uint32 offsets[],
-                                            void* default_oneof_instance);
-  // Delete default oneof instance. Called by ~DynamicMessageFactory.
-  static void DeleteDefaultOneofInstance(const Descriptor* type,
-                                         const uint32 offsets[],
-                                         const void* default_oneof_instance);
-
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessageFactory);
 };
 
diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc
index 2c6346d..22328bd 100644
--- a/src/google/protobuf/empty.pb.cc
+++ b/src/google/protobuf/empty.pb.cc
@@ -17,24 +17,18 @@
 
 PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class EmptyDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Empty> _instance;
-} _Empty_default_instance_;
+constexpr Empty::Empty(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized){}
+struct EmptyDefaultTypeInternal {
+  constexpr EmptyDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~EmptyDefaultTypeInternal() {}
+  union {
+    Empty _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY EmptyDefaultTypeInternal _Empty_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_Empty_google_2fprotobuf_2fempty_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Empty_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Empty();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Empty_google_2fprotobuf_2fempty_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Empty_google_2fprotobuf_2fempty_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fempty_2eproto[1];
 static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fempty_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fempty_2eproto = nullptr;
@@ -61,18 +55,18 @@
   "/types/known/emptypb\370\001\001\242\002\003GPB\252\002\036Google.P"
   "rotobuf.WellKnownTypesb\006proto3"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fempty_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fempty_2eproto_sccs[1] = {
-  &scc_info_Empty_google_2fprotobuf_2fempty_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fempty_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fempty_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fempty_2eproto, "google/protobuf/empty.proto", 190,
-  &descriptor_table_google_2fprotobuf_2fempty_2eproto_once, descriptor_table_google_2fprotobuf_2fempty_2eproto_sccs, descriptor_table_google_2fprotobuf_2fempty_2eproto_deps, 1, 0,
+  false, false, 190, descriptor_table_protodef_google_2fprotobuf_2fempty_2eproto, "google/protobuf/empty.proto", 
+  &descriptor_table_google_2fprotobuf_2fempty_2eproto_once, nullptr, 0, 1,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fempty_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fempty_2eproto, 1, file_level_enum_descriptors_google_2fprotobuf_2fempty_2eproto, file_level_service_descriptors_google_2fprotobuf_2fempty_2eproto,
+  file_level_metadata_google_2fprotobuf_2fempty_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fempty_2eproto, file_level_service_descriptors_google_2fprotobuf_2fempty_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
+descriptor_table_google_2fprotobuf_2fempty_2eproto_metadata_getter(int index) {
+  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fempty_2eproto);
+  return descriptor_table_google_2fprotobuf_2fempty_2eproto.file_level_metadata[index];
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
 PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fempty_2eproto(&descriptor_table_google_2fprotobuf_2fempty_2eproto);
@@ -118,11 +112,6 @@
 void Empty::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Empty& Empty::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Empty_google_2fprotobuf_2fempty_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Empty::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Empty)
diff --git a/src/google/protobuf/empty.pb.h b/src/google/protobuf/empty.pb.h
index 7308003..3b59d16 100644
--- a/src/google/protobuf/empty.pb.h
+++ b/src/google/protobuf/empty.pb.h
@@ -53,9 +53,10 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fempty_2eproto;
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fempty_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class Empty;
-class EmptyDefaultTypeInternal;
+struct EmptyDefaultTypeInternal;
 PROTOBUF_EXPORT extern EmptyDefaultTypeInternal _Empty_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -70,6 +71,7 @@
  public:
   inline Empty() : Empty(nullptr) {}
   virtual ~Empty();
+  explicit constexpr Empty(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Empty(const Empty& from);
   Empty(Empty&& from) noexcept
@@ -99,8 +101,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Empty& default_instance();
-
+  static const Empty& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Empty* internal_default_instance() {
     return reinterpret_cast<const Empty*>(
                &_Empty_default_instance_);
@@ -166,8 +169,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fempty_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fempty_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fempty_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc
index 08848c8..bc53480 100644
--- a/src/google/protobuf/extension_set.cc
+++ b/src/google/protobuf/extension_set.cc
@@ -1454,9 +1454,9 @@
   return ParseMessageSetLite(input, &finder, &skipper);
 }
 
-uint8* ExtensionSet::_InternalSerialize(int start_field_number,
-                                        int end_field_number, uint8* target,
-                                        io::EpsCopyOutputStream* stream) const {
+uint8* ExtensionSet::_InternalSerializeImpl(
+    int start_field_number, int end_field_number, uint8* target,
+    io::EpsCopyOutputStream* stream) const {
   if (PROTOBUF_PREDICT_FALSE(is_large())) {
     const auto& end = map_.large->end();
     for (auto it = map_.large->lower_bound(start_field_number);
@@ -1885,9 +1885,6 @@
   }
   flat_capacity_ = new_flat_capacity;
   map_ = new_map;
-  if (is_large()) {
-    flat_size_ = 0;
-  }
 }
 
 // static
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index a74d2a9..c4b845a 100644
--- a/src/google/protobuf/extension_set.h
+++ b/src/google/protobuf/extension_set.h
@@ -469,7 +469,14 @@
   // Returns a pointer past the last written byte.
   uint8* _InternalSerialize(int start_field_number, int end_field_number,
                             uint8* target,
-                            io::EpsCopyOutputStream* stream) const;
+                            io::EpsCopyOutputStream* stream) const {
+    if (flat_size_ == 0) {
+      assert(!is_large());
+      return target;
+    }
+    return _InternalSerializeImpl(start_field_number, end_field_number, target,
+                                  stream);
+  }
 
   // Like above but serializes in MessageSet format.
   void SerializeMessageSetWithCachedSizes(io::CodedOutputStream* output) const {
@@ -510,6 +517,10 @@
   int SpaceUsedExcludingSelf() const;
 
  private:
+  // Implementation of _InternalSerialize for non-empty map_.
+  uint8* _InternalSerializeImpl(int start_field_number, int end_field_number,
+                                uint8* target,
+                                io::EpsCopyOutputStream* stream) const;
   // Interface of a lazily parsed singular message extension.
   class PROTOBUF_EXPORT LazyMessageExtension {
    public:
diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc
index a3822ea..d1f5698 100644
--- a/src/google/protobuf/field_mask.pb.cc
+++ b/src/google/protobuf/field_mask.pb.cc
@@ -17,24 +17,19 @@
 
 PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class FieldMaskDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<FieldMask> _instance;
-} _FieldMask_default_instance_;
+constexpr FieldMask::FieldMask(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : paths_(){}
+struct FieldMaskDefaultTypeInternal {
+  constexpr FieldMaskDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~FieldMaskDefaultTypeInternal() {}
+  union {
+    FieldMask _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY FieldMaskDefaultTypeInternal _FieldMask_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_FieldMask_google_2fprotobuf_2ffield_5fmask_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_FieldMask_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::FieldMask();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_FieldMask_google_2fprotobuf_2ffield_5fmask_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_FieldMask_google_2fprotobuf_2ffield_5fmask_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2ffield_5fmask_2eproto[1];
 static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto = nullptr;
@@ -63,18 +58,18 @@
   "n/fieldmaskpb\370\001\001\242\002\003GPB\252\002\036Google.Protobuf"
   ".WellKnownTypesb\006proto3"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_sccs[1] = {
-  &scc_info_FieldMask_google_2fprotobuf_2ffield_5fmask_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2ffield_5fmask_2eproto, "google/protobuf/field_mask.proto", 223,
-  &descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_once, descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_sccs, descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_deps, 1, 0,
+  false, false, 223, descriptor_table_protodef_google_2fprotobuf_2ffield_5fmask_2eproto, "google/protobuf/field_mask.proto", 
+  &descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_once, nullptr, 0, 1,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2ffield_5fmask_2eproto, 1, file_level_enum_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto, file_level_service_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto,
+  file_level_metadata_google_2fprotobuf_2ffield_5fmask_2eproto, file_level_enum_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto, file_level_service_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
+descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_metadata_getter(int index) {
+  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto);
+  return descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto.file_level_metadata[index];
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
 PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2ffield_5fmask_2eproto(&descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto);
@@ -101,7 +96,6 @@
 }
 
 void FieldMask::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_FieldMask_google_2fprotobuf_2ffield_5fmask_2eproto.base);
 }
 
 FieldMask::~FieldMask() {
@@ -123,11 +117,6 @@
 void FieldMask::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const FieldMask& FieldMask::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_FieldMask_google_2fprotobuf_2ffield_5fmask_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void FieldMask::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FieldMask)
diff --git a/src/google/protobuf/field_mask.pb.h b/src/google/protobuf/field_mask.pb.h
index 0fa822f..e7668ba 100644
--- a/src/google/protobuf/field_mask.pb.h
+++ b/src/google/protobuf/field_mask.pb.h
@@ -53,9 +53,10 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto;
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class FieldMask;
-class FieldMaskDefaultTypeInternal;
+struct FieldMaskDefaultTypeInternal;
 PROTOBUF_EXPORT extern FieldMaskDefaultTypeInternal _FieldMask_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -70,6 +71,7 @@
  public:
   inline FieldMask() : FieldMask(nullptr) {}
   virtual ~FieldMask();
+  explicit constexpr FieldMask(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FieldMask(const FieldMask& from);
   FieldMask(FieldMask&& from) noexcept
@@ -99,8 +101,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const FieldMask& default_instance();
-
+  static const FieldMask& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const FieldMask* internal_default_instance() {
     return reinterpret_cast<const FieldMask*>(
                &_FieldMask_default_instance_);
@@ -166,8 +169,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index b81f583..b2ffe1f 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -2479,11 +2479,8 @@
 }
 
 void AddDescriptorsImpl(const DescriptorTable* table) {
-  // Reflection refers to the default instances so make sure they are
-  // initialized.
-  for (int i = 0; i < table->num_sccs; i++) {
-    internal::InitSCC(table->init_default_instances[i]);
-  }
+  // Reflection refers to the default fields so make sure they are initialized.
+  internal::InitProtobufDefaults();
 
   // Ensure all dependent descriptors are registered to the generated descriptor
   // pool and message factory.
diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h
index ff96bea..5916cb7 100644
--- a/src/google/protobuf/generated_message_reflection.h
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -253,25 +253,24 @@
   int object_size;
 };
 
-struct SCCInfoBase;
-
+// This struct tries to reduce unnecessary padding.
+// The num_xxx might not be close to their respective pointer, but this saves
+// padding.
 struct PROTOBUF_EXPORT DescriptorTable {
   mutable bool is_initialized;
   bool is_eager;
+  int size;  // of serialized descriptor
   const char* descriptor;
   const char* filename;
-  int size;  // of serialized descriptor
   once_flag* once;
-  SCCInfoBase* const* init_default_instances;
   const DescriptorTable* const* deps;
-  int num_sccs;
   int num_deps;
+  int num_messages;
   const MigrationSchema* schemas;
   const Message* const* default_instances;
   const uint32* offsets;
   // update the following descriptor arrays.
   Metadata* file_level_metadata;
-  int num_messages;
   const EnumDescriptor** file_level_enum_descriptors;
   const ServiceDescriptor** file_level_service_descriptors;
 };
diff --git a/src/google/protobuf/generated_message_table_driven.h b/src/google/protobuf/generated_message_table_driven.h
index 68d80dc..0f6309a 100644
--- a/src/google/protobuf/generated_message_table_driven.h
+++ b/src/google/protobuf/generated_message_table_driven.h
@@ -207,11 +207,15 @@
 static_assert(std::is_trivial<ParseTableField>::value, "");
 static_assert(std::is_standard_layout<AuxiliaryParseTableField>::value, "");
 static_assert(std::is_trivial<AuxiliaryParseTableField>::value, "");
-static_assert(std::is_standard_layout<AuxiliaryParseTableField::enum_aux>::value, "");
+static_assert(
+    std::is_standard_layout<AuxiliaryParseTableField::enum_aux>::value, "");
 static_assert(std::is_trivial<AuxiliaryParseTableField::enum_aux>::value, "");
-static_assert(std::is_standard_layout<AuxiliaryParseTableField::message_aux>::value, "");
-static_assert(std::is_trivial<AuxiliaryParseTableField::message_aux>::value, "");
-static_assert(std::is_standard_layout<AuxiliaryParseTableField::string_aux>::value, "");
+static_assert(
+    std::is_standard_layout<AuxiliaryParseTableField::message_aux>::value, "");
+static_assert(std::is_trivial<AuxiliaryParseTableField::message_aux>::value,
+              "");
+static_assert(
+    std::is_standard_layout<AuxiliaryParseTableField::string_aux>::value, "");
 static_assert(std::is_trivial<AuxiliaryParseTableField::string_aux>::value, "");
 static_assert(std::is_standard_layout<ParseTable>::value, "");
 static_assert(std::is_trivial<ParseTable>::value, "");
diff --git a/src/google/protobuf/generated_message_table_driven_lite.h b/src/google/protobuf/generated_message_table_driven_lite.h
index 9fc910a..6813d18 100644
--- a/src/google/protobuf/generated_message_table_driven_lite.h
+++ b/src/google/protobuf/generated_message_table_driven_lite.h
@@ -87,7 +87,7 @@
 
 template <typename Type>
 inline Type* AddField(MessageLite* msg, int64 offset) {
-  static_assert(std::is_standard_layout<Type>::value && std::is_trivial<Type>::value,
+  static_assert(std::is_pod<Type>::value,
                 "Do not assign");
 
   RepeatedField<Type>* repeated = Raw<RepeatedField<Type>>(msg, offset);
@@ -104,7 +104,7 @@
 
 template <typename Type>
 inline void AddField(MessageLite* msg, int64 offset, Type value) {
-  static_assert(std::is_standard_layout<Type>::value && std::is_trivial<Type>::value,
+  static_assert(std::is_pod<Type>::value,
                 "Do not assign");
   *AddField<Type>(msg, offset) = value;
 }
@@ -126,7 +126,7 @@
 template <typename Type>
 inline void SetField(MessageLite* msg, uint32* has_bits, uint32 has_bit_index,
                      int64 offset, Type value) {
-  static_assert(std::is_standard_layout<Type>::value && std::is_trivial<Type>::value,
+  static_assert(std::is_pod<Type>::value,
                 "Do not assign");
   *MutableField<Type>(msg, has_bits, has_bit_index, offset) = value;
 }
diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc
index 8f86f60..bc79365 100644
--- a/src/google/protobuf/generated_message_util.cc
+++ b/src/google/protobuf/generated_message_util.cc
@@ -34,14 +34,8 @@
 
 #include <google/protobuf/generated_message_util.h>
 
+#include <atomic>
 #include <limits>
-
-#ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-// We're only using this as a standard way for getting the thread id.
-// We're not using any thread functionality.
-#include <thread>  // NOLINT
-#endif             // #ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-
 #include <vector>
 
 #include <google/protobuf/io/coded_stream.h>
@@ -51,7 +45,6 @@
 #include <google/protobuf/generated_message_table_driven.h>
 #include <google/protobuf/message_lite.h>
 #include <google/protobuf/metadata_lite.h>
-#include <google/protobuf/stubs/mutex.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/wire_format_lite.h>
 
@@ -73,19 +66,15 @@
 }
 
 PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
-    PROTOBUF_ATTRIBUTE_INIT_PRIORITY EmptyString
-        fixed_address_empty_string;  // NOLINT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY ExplicitlyConstructed<std::string>
+        fixed_address_empty_string{};  // NOLINT
 
 
 PROTOBUF_CONSTINIT std::atomic<bool> init_protobuf_defaults_state{false};
 static bool InitProtobufDefaultsImpl() {
-  ::new (static_cast<void*>(&fixed_address_empty_string.value)) std::string();
-  OnShutdownDestroyString(&fixed_address_empty_string.value);
+  fixed_address_empty_string.DefaultConstruct();
+  OnShutdownDestroyString(fixed_address_empty_string.get_mutable());
 
-  // Verify that we can indeed get the address during constant evaluation.
-  PROTOBUF_CONSTINIT static const std::string& fixed_address_empty_string_test =
-      GetEmptyStringAlreadyInited();
-  (void)fixed_address_empty_string_test;
 
   init_protobuf_defaults_state.store(true, std::memory_order_release);
   return true;
@@ -741,74 +730,6 @@
   }
 }
 
-namespace {
-
-void InitSCC_DFS(SCCInfoBase* scc) {
-  if (scc->visit_status.load(std::memory_order_relaxed) !=
-      SCCInfoBase::kUninitialized)
-    return;
-  scc->visit_status.store(SCCInfoBase::kRunning, std::memory_order_relaxed);
-  // Each base is followed by an array of void*, containing first pointers to
-  // SCCInfoBase and then pointers-to-pointers to SCCInfoBase.
-  auto deps = reinterpret_cast<void**>(scc + 1);
-  auto strong_deps = reinterpret_cast<SCCInfoBase* const*>(deps);
-  for (int i = 0; i < scc->num_deps; ++i) {
-    if (strong_deps[i]) InitSCC_DFS(strong_deps[i]);
-  }
-  auto implicit_weak_deps =
-      reinterpret_cast<SCCInfoBase** const*>(deps + scc->num_deps);
-  for (int i = 0; i < scc->num_implicit_weak_deps; ++i) {
-    if (*implicit_weak_deps[i]) {
-      InitSCC_DFS(*implicit_weak_deps[i]);
-    }
-  }
-  scc->init_func();
-  // Mark done (note we use memory order release here), other threads could
-  // now see this as initialized and thus the initialization must have happened
-  // before.
-  scc->visit_status.store(SCCInfoBase::kInitialized, std::memory_order_release);
-}
-
-}  // namespace
-
-void InitSCCImpl(SCCInfoBase* scc) {
-  static WrappedMutex mu{GOOGLE_PROTOBUF_LINKER_INITIALIZED};
-  // Either the default in case no initialization is running or the id of the
-  // thread that is currently initializing.
-#ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-  static std::atomic<std::thread::id> runner;
-  auto me = std::this_thread::get_id();
-#else
-  // This is a lightweight replacement for std::thread::id. std::thread does not
-  // work on Windows XP SP2 with the latest VC++ libraries, because it utilizes
-  // the Concurrency Runtime that is only supported on Windows XP SP3 and above.
-  static std::atomic_llong runner(-1);
-  auto me = ::GetCurrentThreadId();
-#endif  // #ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-
-  // This will only happen because the constructor will call InitSCC while
-  // constructing the default instance.
-  if (runner.load(std::memory_order_relaxed) == me) {
-    // Because we're in the process of constructing the default instance.
-    // We can be assured that we're already exploring this SCC.
-    GOOGLE_CHECK_EQ(scc->visit_status.load(std::memory_order_relaxed),
-             SCCInfoBase::kRunning);
-    return;
-  }
-  InitProtobufDefaults();
-  mu.Lock();
-  runner.store(me, std::memory_order_relaxed);
-  InitSCC_DFS(scc);
-
-#ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-  runner.store(std::thread::id{}, std::memory_order_relaxed);
-#else
-  runner.store(-1, std::memory_order_relaxed);
-#endif  // #ifndef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-
-  mu.Unlock();
-}
-
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h
index bae0c1f..94c6c29 100644
--- a/src/google/protobuf/generated_message_util.h
+++ b/src/google/protobuf/generated_message_util.h
@@ -192,64 +192,6 @@
   std::atomic<int> size_{0};
 };
 
-// SCCInfo represents information of a strongly connected component of
-// mutual dependent messages.
-struct PROTOBUF_EXPORT SCCInfoBase {
-  // We use 0 for the Initialized state, because test eax,eax, jnz is smaller
-  // and is subject to macro fusion.
-  enum {
-    kInitialized = 0,  // final state
-    kRunning = 1,
-    kUninitialized = -1,  // initial state
-  };
-#if defined(_MSC_VER) && !defined(__clang__)
-  // MSVC doesn't make std::atomic constant initialized. This union trick
-  // makes it so.
-  union {
-    int visit_status_to_make_linker_init;
-    std::atomic<int> visit_status;
-  };
-#else
-  std::atomic<int> visit_status;
-#endif
-  int num_deps;
-  int num_implicit_weak_deps;
-  void (*init_func)();
-  // This is followed by an array  of num_deps
-  // const SCCInfoBase* deps[];
-};
-
-// Zero-length arrays are a language extension available in GCC and Clang but
-// not MSVC.
-#ifdef __GNUC__
-#define PROTOBUF_ARRAY_SIZE(n) (n)
-#else
-#define PROTOBUF_ARRAY_SIZE(n) ((n) ? (n) : 1)
-#endif
-
-template <int N>
-struct SCCInfo {
-  SCCInfoBase base;
-  // Semantically this is const SCCInfo<T>* which is is a templated type.
-  // The obvious inheriting from SCCInfoBase mucks with struct initialization.
-  // Attempts showed the compiler was generating dynamic initialization code.
-  // This deps array consists of base.num_deps pointers to SCCInfoBase followed
-  // by base.num_implicit_weak_deps pointers to SCCInfoBase*. We need the extra
-  // pointer indirection for implicit weak fields. We cannot use a union type
-  // here, since that would prevent the array from being linker-initialized.
-  void* deps[PROTOBUF_ARRAY_SIZE(N)];
-};
-
-#undef PROTOBUF_ARRAY_SIZE
-
-PROTOBUF_EXPORT void InitSCCImpl(SCCInfoBase* scc);
-
-inline void InitSCC(SCCInfoBase* scc) {
-  auto status = scc->visit_status.load(std::memory_order_acquire);
-  if (PROTOBUF_PREDICT_FALSE(status != SCCInfoBase::kInitialized))
-    InitSCCImpl(scc);
-}
-
 PROTOBUF_EXPORT void DestroyMessage(const void* message);
 PROTOBUF_EXPORT void DestroyString(const void* s);
 // Destroy (not delete) the message
diff --git a/src/google/protobuf/has_bits.h b/src/google/protobuf/has_bits.h
index 1144b9f..7fd9234 100644
--- a/src/google/protobuf/has_bits.h
+++ b/src/google/protobuf/has_bits.h
@@ -47,17 +47,17 @@
 template <size_t doublewords>
 class HasBits {
  public:
-  constexpr HasBits() PROTOBUF_ALWAYS_INLINE : has_bits_{} {}
+  constexpr HasBits() PROTOBUF_NDEBUG_INLINE : has_bits_{} {}
 
-  void Clear() PROTOBUF_ALWAYS_INLINE {
+  void Clear() PROTOBUF_NDEBUG_INLINE {
     memset(has_bits_, 0, sizeof(has_bits_));
   }
 
-  uint32& operator[](int index) PROTOBUF_ALWAYS_INLINE {
+  uint32& operator[](int index) PROTOBUF_NDEBUG_INLINE {
     return has_bits_[index];
   }
 
-  const uint32& operator[](int index) const PROTOBUF_ALWAYS_INLINE {
+  const uint32& operator[](int index) const PROTOBUF_NDEBUG_INLINE {
     return has_bits_[index];
   }
 
diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h
index 744d751..e718790 100644
--- a/src/google/protobuf/map_type_handler.h
+++ b/src/google/protobuf/map_type_handler.h
@@ -586,7 +586,7 @@
   constexpr auto                                                              \
   MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Constinit()         \
       ->TypeOnMemory {                                                        \
-    return TypeOnMemory(&internal::GetEmptyStringAlreadyInited());            \
+    return TypeOnMemory(&internal::fixed_address_empty_string);               \
   }                                                                           \
   template <typename Type>                                                    \
   inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType,            \
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index 259fde8..1a5c775 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -178,7 +178,7 @@
 #define STR_HASH_FXN hash<::google::protobuf::StringPiece>
 
 
-class GeneratedMessageFactory : public MessageFactory {
+class GeneratedMessageFactory final : public MessageFactory {
  public:
   static GeneratedMessageFactory* singleton();
 
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index e20b162..52e6a1d 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -231,7 +231,7 @@
 // the internal library are allowed to create subclasses.
 class PROTOBUF_EXPORT Message : public MessageLite {
  public:
-  constexpr Message() = default;
+  constexpr Message() {}
 
   // Basic Operations ------------------------------------------------
 
diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h
index 87e9d2b..dcc6e24 100644
--- a/src/google/protobuf/message_lite.h
+++ b/src/google/protobuf/message_lite.h
@@ -83,6 +83,7 @@
 // See parse_context.h for explanation
 class ParseContext;
 
+class Proto3ArenaTestHelper;
 class RepeatedPtrFieldBase;
 class WireFormatLite;
 class WeakFieldMap;
@@ -151,25 +152,14 @@
   } union_;
 };
 
-// We need a publicly accessible `value` object to allow constexpr
-// support in C++11.
-// A constexpr accessor does not work portably.
-union EmptyString {
-  constexpr EmptyString() : dummy{} {}
-  ~EmptyString() {}
-
-  // We need a dummy object for constant initialization.
-  std::false_type dummy;
-  std::string value;
-};
-
 // Default empty string object. Don't use this directly. Instead, call
 // GetEmptyString() to get the reference.
-PROTOBUF_EXPORT extern EmptyString fixed_address_empty_string;
+PROTOBUF_EXPORT extern ExplicitlyConstructed<std::string>
+    fixed_address_empty_string;
 
 
 PROTOBUF_EXPORT constexpr const std::string& GetEmptyStringAlreadyInited() {
-  return fixed_address_empty_string.value;
+  return fixed_address_empty_string.get();
 }
 
 PROTOBUF_EXPORT size_t StringSpaceUsedExcludingSelfLong(const std::string& str);
@@ -204,7 +194,7 @@
 // the internal library are allowed to create subclasses.
 class PROTOBUF_EXPORT MessageLite {
  public:
-  constexpr MessageLite() = default;
+  constexpr MessageLite() {}
   virtual ~MessageLite() = default;
 
   // Basic Operations ------------------------------------------------
@@ -220,11 +210,11 @@
   // if arena is a NULL. Default implementation for backwards compatibility.
   virtual MessageLite* New(Arena* arena) const;
 
-  // Get the arena, if any, associated with this message. Virtual method
-  // required for generic operations but most arena-related operations should
-  // use the GetArena() generated-code method. Default implementation
-  // to reduce code size by avoiding the need for per-type implementations
-  // when types do not implement arena support.
+  // Get the arena for allocating submessages, if any, associated with this
+  // message. Virtual method required for generic operations but most
+  // arena-related operations should use the GetArena() generated-code method.
+  // Default implementation to reduce code size by avoiding the need for
+  // per-type implementations when types do not implement arena support.
   Arena* GetArena() const { return _internal_metadata_.arena(); }
 
   // Get a pointer that may be equal to this message's arena, or may not be.
@@ -513,8 +503,18 @@
   // TODO(gerbens) make this a pure abstract function
   virtual const void* InternalGetTable() const { return NULL; }
 
+  // Get the arena that owns this message.
+  Arena* GetOwningArena() const { return _internal_metadata_.GetOwningArena(); }
+
+  // Set the owning arena to the given one.
+  void SetOwningArena(Arena* arena) {
+    _internal_metadata_.SetOwningArena(arena);
+  }
+
+  friend class Arena;
   friend class internal::WireFormatLite;
   friend class Message;
+  friend class internal::Proto3ArenaTestHelper;
   friend class internal::WeakFieldMap;
 
   void LogInitializationErrorMessage() const;
diff --git a/src/google/protobuf/metadata_lite.h b/src/google/protobuf/metadata_lite.h
index ec5f923..9f16180 100644
--- a/src/google/protobuf/metadata_lite.h
+++ b/src/google/protobuf/metadata_lite.h
@@ -47,15 +47,18 @@
 namespace internal {
 
 // This is the representation for messages that support arena allocation. It
-// uses a tagged pointer to either store the Arena pointer, if there are no
-// unknown fields, or a pointer to a block of memory with both the Arena pointer
-// and the UnknownFieldSet, if there are unknown fields. This optimization
-// allows for "zero-overhead" storage of the Arena pointer, relative to the
-// above baseline implementation.
+// uses a tagged pointer to either store the owning Arena pointer, if there are
+// no unknown fields, or a pointer to a block of memory with both the owning
+// Arena pointer and the UnknownFieldSet, if there are unknown fields. Besides,
+// it also uses the tag to distinguish whether the owning Arena pointer is also
+// used by sub-structure allocation. This optimization allows for
+// "zero-overhead" storage of the Arena pointer, relative to the above baseline
+// implementation.
 //
-// The tagged pointer uses the LSB to disambiguate cases, and uses bit 0 == 0 to
-// indicate an arena pointer and bit 0 == 1 to indicate a UFS+Arena-container
-// pointer.
+// The tagged pointer uses the least two significant bits to disambiguate cases.
+// It uses bit 0 == 0 to indicate an arena pointer and bit 0 == 1 to indicate a
+// UFS+Arena-container pointer. Besides it uses bit 1 == 0 to indicate arena
+// allocation and bit 1 == 1 to indicate heap allocation.
 class InternalMetadata {
  public:
   constexpr InternalMetadata() : ptr_(nullptr) {}
@@ -69,22 +72,24 @@
     }
   }
 
-  PROTOBUF_ALWAYS_INLINE Arena* arena() const {
-    if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) {
-      return PtrValue<ContainerBase>()->arena;
-    } else {
+  PROTOBUF_NDEBUG_INLINE Arena* arena() const {
+    if (PROTOBUF_PREDICT_TRUE(!has_tag())) {
       return PtrValue<Arena>();
+    } else if (is_heap_allocating()) {
+      return nullptr;
+    } else {
+      return PtrValue<ContainerBase>()->arena;
     }
   }
 
-  PROTOBUF_ALWAYS_INLINE bool have_unknown_fields() const {
-    return PtrTag() == kTagContainer;
+  PROTOBUF_NDEBUG_INLINE bool have_unknown_fields() const {
+    return UnknownTag() == kUnknownTagMask;
   }
 
-  PROTOBUF_ALWAYS_INLINE void* raw_arena_ptr() const { return ptr_; }
+  PROTOBUF_NDEBUG_INLINE void* raw_arena_ptr() const { return ptr_; }
 
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE const T& unknown_fields(
+  PROTOBUF_NDEBUG_INLINE const T& unknown_fields(
       const T& (*default_instance)()) const {
     if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) {
       return PtrValue<Container<T>>()->unknown_fields;
@@ -94,7 +99,7 @@
   }
 
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE T* mutable_unknown_fields() {
+  PROTOBUF_NDEBUG_INLINE T* mutable_unknown_fields() {
     if (PROTOBUF_PREDICT_TRUE(have_unknown_fields())) {
       return &PtrValue<Container<T>>()->unknown_fields;
     } else {
@@ -103,7 +108,7 @@
   }
 
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE void Swap(InternalMetadata* other) {
+  PROTOBUF_NDEBUG_INLINE void Swap(InternalMetadata* other) {
     // Semantics here are that we swap only the unknown fields, not the arena
     // pointer. We cannot simply swap ptr_ with other->ptr_ because we need to
     // maintain our own arena ptr. Also, our ptr_ and other's ptr_ may be in
@@ -116,36 +121,69 @@
   }
 
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE void MergeFrom(const InternalMetadata& other) {
+  PROTOBUF_NDEBUG_INLINE void MergeFrom(const InternalMetadata& other) {
     if (other.have_unknown_fields()) {
       DoMergeFrom<T>(other.unknown_fields<T>(nullptr));
     }
   }
 
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE void Clear() {
+  PROTOBUF_NDEBUG_INLINE void Clear() {
     if (have_unknown_fields()) {
       DoClear<T>();
     }
   }
 
+  PROTOBUF_ALWAYS_INLINE Arena* GetOwningArena() const {
+    if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) {
+      return PtrValue<ContainerBase>()->arena;
+    } else {
+      return PtrValue<Arena>();
+    }
+  }
+
+  PROTOBUF_ALWAYS_INLINE void SetOwningArena(Arena* arena) {
+    Arena* owning_arena = GetOwningArena();
+    GOOGLE_DCHECK(arena != nullptr);         // Heap can't own.
+    GOOGLE_DCHECK(owning_arena == nullptr);  // Only heap can be owned.
+
+    if (have_unknown_fields()) {
+      ContainerBase* container = PtrValue<ContainerBase>();
+      container->arena = arena;
+      ptr_ = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(ptr_) |
+                                     kHeapAllocatingTagMask);
+    } else {
+      ptr_ = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(arena) |
+                                     kHeapAllocatingTagMask);
+    }
+  }
+
  private:
   void* ptr_;
 
   // Tagged pointer implementation.
-  enum {
-    // ptr_ is an Arena*.
-    kTagArena = 0,
-    // ptr_ is a Container*.
-    kTagContainer = 1,
-  };
-  static constexpr intptr_t kPtrTagMask = 1;
+  static constexpr intptr_t kUnknownTagMask = 1;
+  static constexpr intptr_t kHeapAllocatingTagMask = 2;
+  static constexpr intptr_t kPtrTagMask =
+      kUnknownTagMask | kHeapAllocatingTagMask;
   static constexpr intptr_t kPtrValueMask = ~kPtrTagMask;
 
   // Accessors for pointer tag and pointer value.
-  PROTOBUF_ALWAYS_INLINE int PtrTag() const {
+  PROTOBUF_NDEBUG_INLINE int PtrTag() const {
     return reinterpret_cast<intptr_t>(ptr_) & kPtrTagMask;
   }
+  PROTOBUF_ALWAYS_INLINE int UnknownTag() const {
+    return reinterpret_cast<intptr_t>(ptr_) & kUnknownTagMask;
+  }
+  PROTOBUF_ALWAYS_INLINE int HeapAllocatingTag() const {
+    return reinterpret_cast<intptr_t>(ptr_) & kHeapAllocatingTagMask;
+  }
+  PROTOBUF_ALWAYS_INLINE bool has_tag() const {
+    return (reinterpret_cast<intptr_t>(ptr_) & kPtrTagMask) != 0;
+  }
+  PROTOBUF_ALWAYS_INLINE bool is_heap_allocating() const {
+    return HeapAllocatingTag() == kHeapAllocatingTagMask;
+  }
 
   template <typename U>
   U* PtrValue() const {
@@ -153,7 +191,8 @@
                                 kPtrValueMask);
   }
 
-  // If ptr_'s tag is kTagContainer, it points to an instance of this struct.
+  // If ptr_'s tag is kUnknownTagMask, it points to an instance of this
+  // struct.
   struct ContainerBase {
     Arena* arena;
   };
@@ -166,13 +205,16 @@
   template <typename T>
   PROTOBUF_NOINLINE T* mutable_unknown_fields_slow() {
     Arena* my_arena = arena();
+    Arena* owning_arena = GetOwningArena();
     Container<T>* container = Arena::Create<Container<T>>(my_arena);
     // Two-step assignment works around a bug in clang's static analyzer:
     // https://bugs.llvm.org/show_bug.cgi?id=34198.
+    intptr_t allocating_tag =
+        reinterpret_cast<intptr_t>(ptr_) & kHeapAllocatingTagMask;
     ptr_ = container;
     ptr_ = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(ptr_) |
-                                   kTagContainer);
-    container->arena = my_arena;
+                                   kUnknownTagMask | allocating_tag);
+    container->arena = owning_arena;
     return &(container->unknown_fields);
   }
 
diff --git a/src/google/protobuf/parse_context.h b/src/google/protobuf/parse_context.h
index 3a3df68..7966d99 100644
--- a/src/google/protobuf/parse_context.h
+++ b/src/google/protobuf/parse_context.h
@@ -348,7 +348,7 @@
     if (ptr - buffer_end_ > limit_) return nullptr;
     while (limit_ > kSlopBytes) {
       size_t chunk_size = buffer_end_ + kSlopBytes - ptr;
-      GOOGLE_DCHECK_GE(chunk_size, 0);
+      GOOGLE_DCHECK_GE(chunk_size, static_cast<size_t>(0));
       append(ptr, chunk_size);
       ptr = Next();
       if (ptr == nullptr) return limit_end_;
@@ -401,7 +401,7 @@
   const char* ParseMessage(Message* msg, const char* ptr);
 
   template <typename T>
-  PROTOBUF_MUST_USE_RESULT PROTOBUF_ALWAYS_INLINE const char* ParseGroup(
+  PROTOBUF_MUST_USE_RESULT PROTOBUF_NDEBUG_INLINE const char* ParseGroup(
       T* msg, const char* ptr, uint32 tag) {
     if (--depth_ < 0) return nullptr;
     group_depth_++;
diff --git a/src/google/protobuf/port_def.inc b/src/google/protobuf/port_def.inc
index e6e8a4b..d15073a 100644
--- a/src/google/protobuf/port_def.inc
+++ b/src/google/protobuf/port_def.inc
@@ -61,6 +61,9 @@
 #ifdef PROTOBUF_ALWAYS_INLINE
 #error PROTOBUF_ALWAYS_INLINE was previously defined
 #endif
+#ifdef PROTOBUF_NDEBUG_INLINE
+#error PROTOBUF_NDEBUG_INLINE was previously defined
+#endif
 #ifdef PROTOBUF_COLD
 #error PROTOBUF_COLD was previously defined
 #endif
@@ -154,6 +157,9 @@
 #ifdef PROTOBUF_PRAGMA_INIT_SEG
 #error PROTOBUF_PRAGMA_INIT_SEG was previously defined
 #endif
+#ifdef PROTOBUF_ATTRIBUTE_WEAK
+#error PROTOBUF_ATTRIBUTE_WEAK was previously defined
+#endif
 
 
 #define PROTOBUF_NAMESPACE "google::protobuf"
@@ -170,13 +176,13 @@
 #define PROTOBUF_DEPRECATED_ENUM __attribute__((deprecated))
 #define PROTOBUF_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
 #elif defined(__GNUC__)
-#  define PROTOBUF_DEPRECATED __attribute__((deprecated))
-#  define PROTOBUF_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
-# if __GNUC__ >= 6
-#  define PROTOBUF_DEPRECATED_ENUM __attribute__((deprecated))
-# else
-#  define PROTOBUF_DEPRECATED_ENUM
-# endif
+#define PROTOBUF_DEPRECATED __attribute__((deprecated))
+#define PROTOBUF_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
+#if __GNUC__ >= 6
+#define PROTOBUF_DEPRECATED_ENUM __attribute__((deprecated))
+#else
+#define PROTOBUF_DEPRECATED_ENUM
+#endif
 #elif defined(_MSC_VER)
 #define PROTOBUF_DEPRECATED __declspec(deprecated)
 #define PROTOBUF_DEPRECATED_ENUM
@@ -194,15 +200,18 @@
 
 #ifdef GOOGLE_ATTRIBUTE_ALWAYS_INLINE
 #define PROTOBUF_ALWAYS_INLINE GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+#define PROTOBUF_NDEBUG_INLINE GOOGLE_ATTRIBUTE_ALWAYS_INLINE
 #else
 #if defined(__GNUC__) && \
     (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
 // For functions we want to force inline.
 // Introduced in gcc 3.1.
 #define PROTOBUF_ALWAYS_INLINE __attribute__((always_inline))
+#define PROTOBUF_NDEBUG_INLINE __attribute__((always_inline))
 #else
 // Other compilers will have to figure it out for themselves.
 #define PROTOBUF_ALWAYS_INLINE
+#define PROTOBUF_NDEBUG_INLINE
 #endif
 #endif
 
@@ -606,6 +615,15 @@
 #define PROTOBUF_PRAGMA_INIT_SEG
 #endif
 
+#if defined(__has_attribute)
+#if __has_attribute(weak)
+#define PROTOBUF_ATTRIBUTE_WEAK __attribute__((weak))
+#endif
+#endif
+#if !defined(PROTOBUF_ATTRIBUTE_WEAK)
+#define PROTOBUF_ATTRIBUTE_WEAK
+#endif
+
 // Silence some MSVC warnings in all our code.
 #if _MSC_VER
 #pragma warning(push)
diff --git a/src/google/protobuf/port_undef.inc b/src/google/protobuf/port_undef.inc
index 17cf837..daef09b 100644
--- a/src/google/protobuf/port_undef.inc
+++ b/src/google/protobuf/port_undef.inc
@@ -37,6 +37,7 @@
 #undef PROTOBUF_NAMESPACE
 #undef PROTOBUF_NAMESPACE_ID
 #undef PROTOBUF_ALWAYS_INLINE
+#undef PROTOBUF_NDEBUG_INLINE
 #undef PROTOBUF_COLD
 #undef PROTOBUF_NOINLINE
 #undef PROTOBUF_SECTION_VARIABLE
@@ -72,9 +73,8 @@
 #undef PROTOBUF_FINAL
 #undef PROTOBUF_THREAD_LOCAL
 #undef PROTOBUF_MESSAGE_OWNED_ARENA_EXPERIMENT
-#undef PROTOBUF_DISABLE_MSVC_UNION_WARNING
-#undef PROTOBUF_ENABLE_MSVC_UNION_WARNING
 #undef PROTOBUF_CONSTINIT
+#undef PROTOBUF_ATTRIBUTE_WEAK
 #undef PROTOBUF_ATTRIBUTE_NO_DESTROY
 #undef PROTOBUF_ATTRIBUTE_INIT_PRIORITY
 #undef PROTOBUF_PRAGMA_INIT_SEG
diff --git a/src/google/protobuf/proto3_arena_unittest.cc b/src/google/protobuf/proto3_arena_unittest.cc
index b253f70..7731b28 100644
--- a/src/google/protobuf/proto3_arena_unittest.cc
+++ b/src/google/protobuf/proto3_arena_unittest.cc
@@ -42,10 +42,24 @@
 #include <gtest/gtest.h>
 #include <google/protobuf/stubs/strutil.h>
 
+using proto3_arena_unittest::ForeignMessage;
 using proto3_arena_unittest::TestAllTypes;
 
 namespace google {
 namespace protobuf {
+
+namespace internal {
+
+class Proto3ArenaTestHelper {
+ public:
+  template <typename T>
+  static Arena* GetOwningArena(const T& msg) {
+    return msg.GetOwningArena();
+  }
+};
+
+}  // namespace internal
+
 namespace {
 // We selectively set/check a few representative fields rather than all fields
 // as this test is only expected to cover the basics of arena support.
@@ -143,6 +157,79 @@
       arena_message->GetReflection()->GetUnknownFields(*arena_message).empty());
 }
 
+TEST(Proto3ArenaTest, GetArena) {
+  Arena arena;
+
+  // Tests arena-allocated message and submessages.
+  auto* arena_message1 = Arena::CreateMessage<TestAllTypes>(&arena);
+  auto* arena_submessage1 = arena_message1->mutable_optional_foreign_message();
+  auto* arena_repeated_submessage1 =
+      arena_message1->add_repeated_foreign_message();
+  EXPECT_EQ(&arena, arena_message1->GetArena());
+  EXPECT_EQ(&arena,
+            internal::Proto3ArenaTestHelper::GetOwningArena(*arena_message1));
+  EXPECT_EQ(&arena, arena_submessage1->GetArena());
+  EXPECT_EQ(&arena, arena_repeated_submessage1->GetArena());
+
+  // Tests attached heap-allocated messages.
+  auto* arena_message2 = Arena::CreateMessage<TestAllTypes>(&arena);
+  arena_message2->set_allocated_optional_foreign_message(new ForeignMessage());
+  arena_message2->mutable_repeated_foreign_message()->AddAllocated(
+      new ForeignMessage());
+  const auto& submessage2 = arena_message2->optional_foreign_message();
+  const auto& repeated_submessage2 =
+      arena_message2->repeated_foreign_message(0);
+  EXPECT_EQ(nullptr, submessage2.GetArena());
+  EXPECT_EQ(&arena,
+            internal::Proto3ArenaTestHelper::GetOwningArena(submessage2));
+  EXPECT_EQ(nullptr, repeated_submessage2.GetArena());
+  EXPECT_EQ(&arena, internal::Proto3ArenaTestHelper::GetOwningArena(
+                        repeated_submessage2));
+
+  // Tests message created by Arena::Create.
+  auto* arena_message3 = Arena::Create<TestAllTypes>(&arena);
+  EXPECT_EQ(nullptr, arena_message3->GetArena());
+  EXPECT_EQ(&arena,
+            internal::Proto3ArenaTestHelper::GetOwningArena(*arena_message3));
+}
+
+TEST(Proto3ArenaTest, GetArenaWithUnknown) {
+  Arena arena;
+
+  // Tests arena-allocated message and submessages.
+  auto* arena_message1 = Arena::CreateMessage<TestAllTypes>(&arena);
+  arena_message1->GetReflection()->MutableUnknownFields(arena_message1);
+  auto* arena_submessage1 = arena_message1->mutable_optional_foreign_message();
+  arena_submessage1->GetReflection()->MutableUnknownFields(arena_submessage1);
+  auto* arena_repeated_submessage1 =
+      arena_message1->add_repeated_foreign_message();
+  arena_repeated_submessage1->GetReflection()->MutableUnknownFields(
+      arena_repeated_submessage1);
+  EXPECT_EQ(&arena, arena_message1->GetArena());
+  EXPECT_EQ(&arena,
+            internal::Proto3ArenaTestHelper::GetOwningArena(*arena_message1));
+  EXPECT_EQ(&arena, arena_submessage1->GetArena());
+  EXPECT_EQ(&arena, arena_repeated_submessage1->GetArena());
+
+  // Tests attached heap-allocated messages.
+  auto* arena_message2 = Arena::CreateMessage<TestAllTypes>(&arena);
+  arena_message2->set_allocated_optional_foreign_message(new ForeignMessage());
+  arena_message2->mutable_repeated_foreign_message()->AddAllocated(
+      new ForeignMessage());
+  auto* submessage2 = arena_message2->mutable_optional_foreign_message();
+  submessage2->GetReflection()->MutableUnknownFields(submessage2);
+  auto* repeated_submessage2 =
+      arena_message2->mutable_repeated_foreign_message(0);
+  repeated_submessage2->GetReflection()->MutableUnknownFields(
+      repeated_submessage2);
+  EXPECT_EQ(nullptr, submessage2->GetArena());
+  EXPECT_EQ(&arena,
+            internal::Proto3ArenaTestHelper::GetOwningArena(*submessage2));
+  EXPECT_EQ(nullptr, repeated_submessage2->GetArena());
+  EXPECT_EQ(&arena, internal::Proto3ArenaTestHelper::GetOwningArena(
+                        *repeated_submessage2));
+}
+
 TEST(Proto3ArenaTest, Swap) {
   Arena arena1;
   Arena arena2;
diff --git a/src/google/protobuf/proto3_lite_unittest.inc b/src/google/protobuf/proto3_lite_unittest.inc
index 4cf9cf8..85f428a 100644
--- a/src/google/protobuf/proto3_lite_unittest.inc
+++ b/src/google/protobuf/proto3_lite_unittest.inc
@@ -130,6 +130,17 @@
   EXPECT_EQ(msg1.ByteSize(), msg2.ByteSize() + 1);
 }
 
+TEST(LITE_TEST_NAME, OneofHazzers) {
+  TestAllTypes msg;
+  msg.set_oneof_uint32(1);
+  msg.set_oneof_string("test");
+
+  EXPECT_EQ(true, msg.has_oneof_string());
+  EXPECT_EQ(false, msg.has_oneof_uint32());
+  EXPECT_EQ(false, msg.has_oneof_bytes());
+  EXPECT_EQ(false, msg.has_oneof_nested_message());
+}
+
 }  // namespace
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index 89f1474..840b80d 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -501,7 +501,7 @@
 // effectively.
 template <typename Element,
           bool HasTrivialCopy =
-              std::is_standard_layout<Element>::value && std::is_trivial<Element>::value>
+              std::is_pod<Element>::value>
 struct ElementCopier {
   void operator()(Element* to, const Element* from, int array_size);
 };
@@ -657,7 +657,7 @@
   const typename TypeHandler::Type* const* data() const;
 
   template <typename TypeHandler>
-  PROTOBUF_ALWAYS_INLINE void Swap(RepeatedPtrFieldBase* other);
+  PROTOBUF_NDEBUG_INLINE void Swap(RepeatedPtrFieldBase* other);
 
   void SwapElements(int index1, int index2);
 
diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc
index fbd1804..3d84017 100644
--- a/src/google/protobuf/source_context.pb.cc
+++ b/src/google/protobuf/source_context.pb.cc
@@ -17,24 +17,19 @@
 
 PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class SourceContextDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<SourceContext> _instance;
-} _SourceContext_default_instance_;
+constexpr SourceContext::SourceContext(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : file_name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string){}
+struct SourceContextDefaultTypeInternal {
+  constexpr SourceContextDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~SourceContextDefaultTypeInternal() {}
+  union {
+    SourceContext _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY SourceContextDefaultTypeInternal _SourceContext_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::SourceContext();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fsource_5fcontext_2eproto[1];
 static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto = nullptr;
@@ -63,18 +58,18 @@
   "tobuf/types/known/sourcecontextpb\242\002\003GPB\252"
   "\002\036Google.Protobuf.WellKnownTypesb\006proto3"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_sccs[1] = {
-  &scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fsource_5fcontext_2eproto, "google/protobuf/source_context.proto", 240,
-  &descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_once, descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_sccs, descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_deps, 1, 0,
+  false, false, 240, descriptor_table_protodef_google_2fprotobuf_2fsource_5fcontext_2eproto, "google/protobuf/source_context.proto", 
+  &descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_once, nullptr, 0, 1,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fsource_5fcontext_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fsource_5fcontext_2eproto, 1, file_level_enum_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto, file_level_service_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto,
+  file_level_metadata_google_2fprotobuf_2fsource_5fcontext_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto, file_level_service_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
+descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_metadata_getter(int index) {
+  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto);
+  return descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto.file_level_metadata[index];
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
 PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fsource_5fcontext_2eproto(&descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto);
@@ -104,8 +99,7 @@
 }
 
 void SourceContext::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto.base);
-  file_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+file_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
 SourceContext::~SourceContext() {
@@ -128,11 +122,6 @@
 void SourceContext::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const SourceContext& SourceContext::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void SourceContext::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.SourceContext)
diff --git a/src/google/protobuf/source_context.pb.h b/src/google/protobuf/source_context.pb.h
index b27ef5a..12d4655 100644
--- a/src/google/protobuf/source_context.pb.h
+++ b/src/google/protobuf/source_context.pb.h
@@ -53,9 +53,10 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto;
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class SourceContext;
-class SourceContextDefaultTypeInternal;
+struct SourceContextDefaultTypeInternal;
 PROTOBUF_EXPORT extern SourceContextDefaultTypeInternal _SourceContext_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -70,6 +71,7 @@
  public:
   inline SourceContext() : SourceContext(nullptr) {}
   virtual ~SourceContext();
+  explicit constexpr SourceContext(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   SourceContext(const SourceContext& from);
   SourceContext(SourceContext&& from) noexcept
@@ -99,8 +101,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const SourceContext& default_instance();
-
+  static const SourceContext& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const SourceContext* internal_default_instance() {
     return reinterpret_cast<const SourceContext*>(
                &_SourceContext_default_instance_);
@@ -166,8 +169,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc
index 396654c..1458a9b 100644
--- a/src/google/protobuf/struct.pb.cc
+++ b/src/google/protobuf/struct.pb.cc
@@ -16,52 +16,55 @@
 #include <google/protobuf/port_def.inc>
 
 PROTOBUF_PRAGMA_INIT_SEG
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fstruct_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_ListValue_google_2fprotobuf_2fstruct_2eproto;
 PROTOBUF_NAMESPACE_OPEN
-class Struct_FieldsEntry_DoNotUseDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Struct_FieldsEntry_DoNotUse> _instance;
-} _Struct_FieldsEntry_DoNotUse_default_instance_;
-class StructDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Struct> _instance;
-} _Struct_default_instance_;
-class ValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Value> _instance;
-} _Value_default_instance_;
-class ListValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<ListValue> _instance;
-} _ListValue_default_instance_;
+constexpr Struct_FieldsEntry_DoNotUse::Struct_FieldsEntry_DoNotUse(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized){}
+struct Struct_FieldsEntry_DoNotUseDefaultTypeInternal {
+  constexpr Struct_FieldsEntry_DoNotUseDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~Struct_FieldsEntry_DoNotUseDefaultTypeInternal() {}
+  union {
+    Struct_FieldsEntry_DoNotUse _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY Struct_FieldsEntry_DoNotUseDefaultTypeInternal _Struct_FieldsEntry_DoNotUse_default_instance_;
+constexpr Struct::Struct(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : fields_(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}){}
+struct StructDefaultTypeInternal {
+  constexpr StructDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~StructDefaultTypeInternal() {}
+  union {
+    Struct _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY StructDefaultTypeInternal _Struct_default_instance_;
+constexpr Value::Value(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : _oneof_case_{}{}
+struct ValueDefaultTypeInternal {
+  constexpr ValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~ValueDefaultTypeInternal() {}
+  union {
+    Value _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY ValueDefaultTypeInternal _Value_default_instance_;
+constexpr ListValue::ListValue(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : values_(){}
+struct ListValueDefaultTypeInternal {
+  constexpr ListValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~ListValueDefaultTypeInternal() {}
+  union {
+    ListValue _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY ListValueDefaultTypeInternal _ListValue_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_ListValue_google_2fprotobuf_2fstruct_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Struct_FieldsEntry_DoNotUse_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse();
-  }
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Struct_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Struct();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Value_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Value();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_ListValue_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::ListValue();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_ListValue_google_2fprotobuf_2fstruct_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_ListValue_google_2fprotobuf_2fstruct_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fstruct_2eproto[4];
 static const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fstruct_2eproto[1];
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fstruct_2eproto = nullptr;
@@ -133,18 +136,18 @@
   "rotobuf/types/known/structpb\370\001\001\242\002\003GPB\252\002\036"
   "Google.Protobuf.WellKnownTypesb\006proto3"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fstruct_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fstruct_2eproto_sccs[1] = {
-  &scc_info_ListValue_google_2fprotobuf_2fstruct_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fstruct_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fstruct_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fstruct_2eproto, "google/protobuf/struct.proto", 638,
-  &descriptor_table_google_2fprotobuf_2fstruct_2eproto_once, descriptor_table_google_2fprotobuf_2fstruct_2eproto_sccs, descriptor_table_google_2fprotobuf_2fstruct_2eproto_deps, 1, 0,
+  false, false, 638, descriptor_table_protodef_google_2fprotobuf_2fstruct_2eproto, "google/protobuf/struct.proto", 
+  &descriptor_table_google_2fprotobuf_2fstruct_2eproto_once, nullptr, 0, 4,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fstruct_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fstruct_2eproto, 4, file_level_enum_descriptors_google_2fprotobuf_2fstruct_2eproto, file_level_service_descriptors_google_2fprotobuf_2fstruct_2eproto,
+  file_level_metadata_google_2fprotobuf_2fstruct_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fstruct_2eproto, file_level_service_descriptors_google_2fprotobuf_2fstruct_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
+descriptor_table_google_2fprotobuf_2fstruct_2eproto_metadata_getter(int index) {
+  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fstruct_2eproto);
+  return descriptor_table_google_2fprotobuf_2fstruct_2eproto.file_level_metadata[index];
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
 PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fstruct_2eproto(&descriptor_table_google_2fprotobuf_2fstruct_2eproto);
@@ -201,7 +204,6 @@
 }
 
 void Struct::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_ListValue_google_2fprotobuf_2fstruct_2eproto.base);
 }
 
 Struct::~Struct() {
@@ -223,11 +225,6 @@
 void Struct::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Struct& Struct::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_ListValue_google_2fprotobuf_2fstruct_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Struct::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Struct)
@@ -504,8 +501,7 @@
 }
 
 void Value::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_ListValue_google_2fprotobuf_2fstruct_2eproto.base);
-  clear_has_kind();
+clear_has_kind();
 }
 
 Value::~Value() {
@@ -530,11 +526,6 @@
 void Value::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Value& Value::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_ListValue_google_2fprotobuf_2fstruct_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Value::clear_kind() {
 // @@protoc_insertion_point(one_of_clear_start:google.protobuf.Value)
@@ -881,7 +872,6 @@
 }
 
 void ListValue::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_ListValue_google_2fprotobuf_2fstruct_2eproto.base);
 }
 
 ListValue::~ListValue() {
@@ -903,11 +893,6 @@
 void ListValue::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const ListValue& ListValue::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_ListValue_google_2fprotobuf_2fstruct_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void ListValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.ListValue)
diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h
index 4fda4f3..315c473 100644
--- a/src/google/protobuf/struct.pb.h
+++ b/src/google/protobuf/struct.pb.h
@@ -57,18 +57,19 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fstruct_2eproto;
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fstruct_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class ListValue;
-class ListValueDefaultTypeInternal;
+struct ListValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern ListValueDefaultTypeInternal _ListValue_default_instance_;
 class Struct;
-class StructDefaultTypeInternal;
+struct StructDefaultTypeInternal;
 PROTOBUF_EXPORT extern StructDefaultTypeInternal _Struct_default_instance_;
 class Struct_FieldsEntry_DoNotUse;
-class Struct_FieldsEntry_DoNotUseDefaultTypeInternal;
+struct Struct_FieldsEntry_DoNotUseDefaultTypeInternal;
 PROTOBUF_EXPORT extern Struct_FieldsEntry_DoNotUseDefaultTypeInternal _Struct_FieldsEntry_DoNotUse_default_instance_;
 class Value;
-class ValueDefaultTypeInternal;
+struct ValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern ValueDefaultTypeInternal _Value_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -115,6 +116,8 @@
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_STRING,
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_MESSAGE> SuperType;
   Struct_FieldsEntry_DoNotUse();
+  explicit constexpr Struct_FieldsEntry_DoNotUse(
+      ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
   explicit Struct_FieldsEntry_DoNotUse(::PROTOBUF_NAMESPACE_ID::Arena* arena);
   void MergeFrom(const Struct_FieldsEntry_DoNotUse& other);
   static const Struct_FieldsEntry_DoNotUse* internal_default_instance() { return reinterpret_cast<const Struct_FieldsEntry_DoNotUse*>(&_Struct_FieldsEntry_DoNotUse_default_instance_); }
@@ -140,6 +143,7 @@
  public:
   inline Struct() : Struct(nullptr) {}
   virtual ~Struct();
+  explicit constexpr Struct(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Struct(const Struct& from);
   Struct(Struct&& from) noexcept
@@ -169,8 +173,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Struct& default_instance();
-
+  static const Struct& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Struct* internal_default_instance() {
     return reinterpret_cast<const Struct*>(
                &_Struct_default_instance_);
@@ -236,8 +241,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fstruct_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fstruct_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fstruct_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -289,6 +293,7 @@
  public:
   inline Value() : Value(nullptr) {}
   virtual ~Value();
+  explicit constexpr Value(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Value(const Value& from);
   Value(Value&& from) noexcept
@@ -318,8 +323,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Value& default_instance();
-
+  static const Value& default_instance() {
+    return *internal_default_instance();
+  }
   enum KindCase {
     kNullValue = 1,
     kNumberValue = 2,
@@ -395,8 +401,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fstruct_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fstruct_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fstruct_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -414,6 +419,7 @@
     kListValueFieldNumber = 6,
   };
   // .google.protobuf.NullValue null_value = 1;
+  bool has_null_value() const;
   private:
   bool _internal_has_null_value() const;
   public:
@@ -426,6 +432,7 @@
   public:
 
   // double number_value = 2;
+  bool has_number_value() const;
   private:
   bool _internal_has_number_value() const;
   public:
@@ -438,6 +445,7 @@
   public:
 
   // string string_value = 3;
+  bool has_string_value() const;
   private:
   bool _internal_has_string_value() const;
   public:
@@ -457,6 +465,7 @@
   public:
 
   // bool bool_value = 4;
+  bool has_bool_value() const;
   private:
   bool _internal_has_bool_value() const;
   public:
@@ -523,7 +532,8 @@
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   union KindUnion {
-    KindUnion() {}
+    constexpr KindUnion() : _constinit_{} {}
+      ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized _constinit_;
     int null_value_;
     double number_value_;
     ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr string_value_;
@@ -543,6 +553,7 @@
  public:
   inline ListValue() : ListValue(nullptr) {}
   virtual ~ListValue();
+  explicit constexpr ListValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   ListValue(const ListValue& from);
   ListValue(ListValue&& from) noexcept
@@ -572,8 +583,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const ListValue& default_instance();
-
+  static const ListValue& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const ListValue* internal_default_instance() {
     return reinterpret_cast<const ListValue*>(
                &_ListValue_default_instance_);
@@ -639,8 +651,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fstruct_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fstruct_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fstruct_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -731,6 +742,9 @@
 inline bool Value::_internal_has_null_value() const {
   return kind_case() == kNullValue;
 }
+inline bool Value::has_null_value() const {
+  return _internal_has_null_value();
+}
 inline void Value::set_has_null_value() {
   _oneof_case_[0] = kNullValue;
 }
@@ -766,6 +780,9 @@
 inline bool Value::_internal_has_number_value() const {
   return kind_case() == kNumberValue;
 }
+inline bool Value::has_number_value() const {
+  return _internal_has_number_value();
+}
 inline void Value::set_has_number_value() {
   _oneof_case_[0] = kNumberValue;
 }
@@ -801,6 +818,9 @@
 inline bool Value::_internal_has_string_value() const {
   return kind_case() == kStringValue;
 }
+inline bool Value::has_string_value() const {
+  return _internal_has_string_value();
+}
 inline void Value::set_has_string_value() {
   _oneof_case_[0] = kStringValue;
 }
@@ -908,6 +928,9 @@
 inline bool Value::_internal_has_bool_value() const {
   return kind_case() == kBoolValue;
 }
+inline bool Value::has_bool_value() const {
+  return _internal_has_bool_value();
+}
 inline void Value::set_has_bool_value() {
   _oneof_case_[0] = kBoolValue;
 }
diff --git a/src/google/protobuf/stubs/mutex.h b/src/google/protobuf/stubs/mutex.h
index 5c16c7e..23f315f 100644
--- a/src/google/protobuf/stubs/mutex.h
+++ b/src/google/protobuf/stubs/mutex.h
@@ -125,11 +125,11 @@
 
  private:
 #if defined(GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP)
-  CallOnceInitializedMutex<CriticalSectionLock> mu_ {};
+  CallOnceInitializedMutex<CriticalSectionLock> mu_{};
 #elif defined(_MSC_VER)
-  CallOnceInitializedMutex<std::mutex> mu_ {};
+  CallOnceInitializedMutex<std::mutex> mu_{};
 #else
-  std::mutex mu_ {};
+  std::mutex mu_{};
 #endif
 };
 
diff --git a/src/google/protobuf/stubs/port.h b/src/google/protobuf/stubs/port.h
index 120ab7e..b7aab40 100644
--- a/src/google/protobuf/stubs/port.h
+++ b/src/google/protobuf/stubs/port.h
@@ -57,17 +57,17 @@
 #pragma runtime_checks("c", off)
 #endif
 #else
-  #ifdef __APPLE__
-    #include <machine/endian.h>  // __BYTE_ORDER
-  #else
-    #include <endian.h>  // __BYTE_ORDER
-  #endif
-  #if ((defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \
-         (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) || \
-         (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN)) && \
-      !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
-    #define PROTOBUF_LITTLE_ENDIAN 1
-  #endif
+#ifdef __APPLE__
+#include <machine/endian.h>  // __BYTE_ORDER
+#else
+#include <endian.h>  // __BYTE_ORDER
+#endif
+#if ((defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) ||   \
+     (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) || \
+     (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN)) &&      \
+    !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
+#define PROTOBUF_LITTLE_ENDIAN 1
+#endif
 #endif
 
 // These #includes are for the byte swap functions declared later on.
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index 1af250d..2abd927 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -2130,7 +2130,7 @@
   // DynamicMapSorter::Sort cannot be used because it enfores syncing with
   // repeated field.
   static bool SortMap(const Message& message, const Reflection* reflection,
-                      const FieldDescriptor* field, MessageFactory* factory,
+                      const FieldDescriptor* field,
                       std::vector<const Message*>* sorted_map_field);
   static void CopyKey(const MapKey& key, Message* message,
                       const FieldDescriptor* field_desc);
@@ -2141,7 +2141,7 @@
 // Returns true if elements contained in sorted_map_field need to be released.
 bool MapFieldPrinterHelper::SortMap(
     const Message& message, const Reflection* reflection,
-    const FieldDescriptor* field, MessageFactory* factory,
+    const FieldDescriptor* field,
     std::vector<const Message*>* sorted_map_field) {
   bool need_release = false;
   const MapFieldBase& base = *reflection->GetMapData(message, field);
@@ -2157,7 +2157,8 @@
     // TODO(teboring): For performance, instead of creating map entry message
     // for each element, just store map keys and sort them.
     const Descriptor* map_entry_desc = field->message_type();
-    const Message* prototype = factory->GetPrototype(map_entry_desc);
+    const Message* prototype =
+        reflection->GetMessageFactory()->GetPrototype(map_entry_desc);
     for (MapIterator iter =
              reflection->MapBegin(const_cast<Message*>(&message), field);
          iter != reflection->MapEnd(const_cast<Message*>(&message), field);
@@ -2270,13 +2271,12 @@
     count = 1;
   }
 
-  DynamicMessageFactory factory;
   std::vector<const Message*> sorted_map_field;
   bool need_release = false;
   bool is_map = field->is_map();
   if (is_map) {
     need_release = internal::MapFieldPrinterHelper::SortMap(
-        message, reflection, field, &factory, &sorted_map_field);
+        message, reflection, field, &sorted_map_field);
   }
 
   for (int j = 0; j < count; ++j) {
diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc
index 24b8ee9..2c81eb4 100644
--- a/src/google/protobuf/timestamp.pb.cc
+++ b/src/google/protobuf/timestamp.pb.cc
@@ -17,24 +17,20 @@
 
 PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class TimestampDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Timestamp> _instance;
-} _Timestamp_default_instance_;
+constexpr Timestamp::Timestamp(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : seconds_(PROTOBUF_LONGLONG(0))
+  , nanos_(0){}
+struct TimestampDefaultTypeInternal {
+  constexpr TimestampDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~TimestampDefaultTypeInternal() {}
+  union {
+    Timestamp _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY TimestampDefaultTypeInternal _Timestamp_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Timestamp_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Timestamp();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2ftimestamp_2eproto[1];
 static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2ftimestamp_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2ftimestamp_2eproto = nullptr;
@@ -64,18 +60,18 @@
   "tobuf/types/known/timestamppb\370\001\001\242\002\003GPB\252\002"
   "\036Google.Protobuf.WellKnownTypesb\006proto3"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_sccs[1] = {
-  &scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ftimestamp_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2ftimestamp_2eproto, "google/protobuf/timestamp.proto", 239,
-  &descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_once, descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_sccs, descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_deps, 1, 0,
+  false, false, 239, descriptor_table_protodef_google_2fprotobuf_2ftimestamp_2eproto, "google/protobuf/timestamp.proto", 
+  &descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_once, nullptr, 0, 1,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2ftimestamp_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2ftimestamp_2eproto, 1, file_level_enum_descriptors_google_2fprotobuf_2ftimestamp_2eproto, file_level_service_descriptors_google_2fprotobuf_2ftimestamp_2eproto,
+  file_level_metadata_google_2fprotobuf_2ftimestamp_2eproto, file_level_enum_descriptors_google_2fprotobuf_2ftimestamp_2eproto, file_level_service_descriptors_google_2fprotobuf_2ftimestamp_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
+descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_metadata_getter(int index) {
+  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2ftimestamp_2eproto);
+  return descriptor_table_google_2fprotobuf_2ftimestamp_2eproto.file_level_metadata[index];
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
 PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2ftimestamp_2eproto(&descriptor_table_google_2fprotobuf_2ftimestamp_2eproto);
@@ -103,10 +99,10 @@
 }
 
 void Timestamp::SharedCtor() {
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&seconds_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&nanos_) -
-      reinterpret_cast<char*>(&seconds_)) + sizeof(nanos_));
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&seconds_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&nanos_) -
+    reinterpret_cast<char*>(&seconds_)) + sizeof(nanos_));
 }
 
 Timestamp::~Timestamp() {
@@ -128,11 +124,6 @@
 void Timestamp::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Timestamp& Timestamp::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Timestamp::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Timestamp)
diff --git a/src/google/protobuf/timestamp.pb.h b/src/google/protobuf/timestamp.pb.h
index 4d2947a..1105edb 100644
--- a/src/google/protobuf/timestamp.pb.h
+++ b/src/google/protobuf/timestamp.pb.h
@@ -53,9 +53,10 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ftimestamp_2eproto;
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class Timestamp;
-class TimestampDefaultTypeInternal;
+struct TimestampDefaultTypeInternal;
 PROTOBUF_EXPORT extern TimestampDefaultTypeInternal _Timestamp_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -70,6 +71,7 @@
  public:
   inline Timestamp() : Timestamp(nullptr) {}
   virtual ~Timestamp();
+  explicit constexpr Timestamp(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Timestamp(const Timestamp& from);
   Timestamp(Timestamp&& from) noexcept
@@ -99,8 +101,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Timestamp& default_instance();
-
+  static const Timestamp& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Timestamp* internal_default_instance() {
     return reinterpret_cast<const Timestamp*>(
                &_Timestamp_default_instance_);
@@ -166,8 +169,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2ftimestamp_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2ftimestamp_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc
index 5c94072..a4a3c27 100644
--- a/src/google/protobuf/type.pb.cc
+++ b/src/google/protobuf/type.pb.cc
@@ -16,107 +16,93 @@
 #include <google/protobuf/port_def.inc>
 
 PROTOBUF_PRAGMA_INIT_SEG
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fany_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Any_google_2fprotobuf_2fany_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftype_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_EnumValue_google_2fprotobuf_2ftype_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftype_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Field_google_2fprotobuf_2ftype_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftype_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Option_google_2fprotobuf_2ftype_2eproto;
-extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fsource_5fcontext_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto;
 PROTOBUF_NAMESPACE_OPEN
-class TypeDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Type> _instance;
-} _Type_default_instance_;
-class FieldDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Field> _instance;
-} _Field_default_instance_;
-class EnumDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Enum> _instance;
-} _Enum_default_instance_;
-class EnumValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<EnumValue> _instance;
-} _EnumValue_default_instance_;
-class OptionDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Option> _instance;
-} _Option_default_instance_;
+constexpr Type::Type(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : fields_()
+  , oneofs_()
+  , options_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , source_context_(nullptr)
+  , syntax_(0)
+{}
+struct TypeDefaultTypeInternal {
+  constexpr TypeDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~TypeDefaultTypeInternal() {}
+  union {
+    Type _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY TypeDefaultTypeInternal _Type_default_instance_;
+constexpr Field::Field(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : options_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , type_url_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , json_name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , default_value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , kind_(0)
+
+  , cardinality_(0)
+
+  , number_(0)
+  , oneof_index_(0)
+  , packed_(false){}
+struct FieldDefaultTypeInternal {
+  constexpr FieldDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~FieldDefaultTypeInternal() {}
+  union {
+    Field _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY FieldDefaultTypeInternal _Field_default_instance_;
+constexpr Enum::Enum(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : enumvalue_()
+  , options_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , source_context_(nullptr)
+  , syntax_(0)
+{}
+struct EnumDefaultTypeInternal {
+  constexpr EnumDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~EnumDefaultTypeInternal() {}
+  union {
+    Enum _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY EnumDefaultTypeInternal _Enum_default_instance_;
+constexpr EnumValue::EnumValue(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : options_()
+  , name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , number_(0){}
+struct EnumValueDefaultTypeInternal {
+  constexpr EnumValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~EnumValueDefaultTypeInternal() {}
+  union {
+    EnumValue _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY EnumValueDefaultTypeInternal _EnumValue_default_instance_;
+constexpr Option::Option(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string)
+  , value_(nullptr){}
+struct OptionDefaultTypeInternal {
+  constexpr OptionDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~OptionDefaultTypeInternal() {}
+  union {
+    Option _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY OptionDefaultTypeInternal _Option_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_Enum_google_2fprotobuf_2ftype_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Enum_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Enum();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<3> scc_info_Enum_google_2fprotobuf_2ftype_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 3, 0, InitDefaultsscc_info_Enum_google_2fprotobuf_2ftype_2eproto}, {
-      &scc_info_EnumValue_google_2fprotobuf_2ftype_2eproto.base,
-      &scc_info_Option_google_2fprotobuf_2ftype_2eproto.base,
-      &scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto.base,}};
-
-static void InitDefaultsscc_info_EnumValue_google_2fprotobuf_2ftype_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_EnumValue_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::EnumValue();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_EnumValue_google_2fprotobuf_2ftype_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_EnumValue_google_2fprotobuf_2ftype_2eproto}, {
-      &scc_info_Option_google_2fprotobuf_2ftype_2eproto.base,}};
-
-static void InitDefaultsscc_info_Field_google_2fprotobuf_2ftype_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Field_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Field();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Field_google_2fprotobuf_2ftype_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_Field_google_2fprotobuf_2ftype_2eproto}, {
-      &scc_info_Option_google_2fprotobuf_2ftype_2eproto.base,}};
-
-static void InitDefaultsscc_info_Option_google_2fprotobuf_2ftype_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Option_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Option();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Option_google_2fprotobuf_2ftype_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_Option_google_2fprotobuf_2ftype_2eproto}, {
-      &scc_info_Any_google_2fprotobuf_2fany_2eproto.base,}};
-
-static void InitDefaultsscc_info_Type_google_2fprotobuf_2ftype_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Type_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Type();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<3> scc_info_Type_google_2fprotobuf_2ftype_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 3, 0, InitDefaultsscc_info_Type_google_2fprotobuf_2ftype_2eproto}, {
-      &scc_info_Field_google_2fprotobuf_2ftype_2eproto.base,
-      &scc_info_Option_google_2fprotobuf_2ftype_2eproto.base,
-      &scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto.base,}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2ftype_2eproto[5];
 static const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2ftype_2eproto[3];
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2ftype_2eproto = nullptr;
@@ -236,20 +222,18 @@
   &::descriptor_table_google_2fprotobuf_2fany_2eproto,
   &::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto,
 };
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2ftype_2eproto_sccs[5] = {
-  &scc_info_Enum_google_2fprotobuf_2ftype_2eproto.base,
-  &scc_info_EnumValue_google_2fprotobuf_2ftype_2eproto.base,
-  &scc_info_Field_google_2fprotobuf_2ftype_2eproto.base,
-  &scc_info_Option_google_2fprotobuf_2ftype_2eproto.base,
-  &scc_info_Type_google_2fprotobuf_2ftype_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2ftype_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ftype_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2ftype_2eproto, "google/protobuf/type.proto", 1592,
-  &descriptor_table_google_2fprotobuf_2ftype_2eproto_once, descriptor_table_google_2fprotobuf_2ftype_2eproto_sccs, descriptor_table_google_2fprotobuf_2ftype_2eproto_deps, 5, 2,
+  false, false, 1592, descriptor_table_protodef_google_2fprotobuf_2ftype_2eproto, "google/protobuf/type.proto", 
+  &descriptor_table_google_2fprotobuf_2ftype_2eproto_once, descriptor_table_google_2fprotobuf_2ftype_2eproto_deps, 2, 5,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2ftype_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2ftype_2eproto, 5, file_level_enum_descriptors_google_2fprotobuf_2ftype_2eproto, file_level_service_descriptors_google_2fprotobuf_2ftype_2eproto,
+  file_level_metadata_google_2fprotobuf_2ftype_2eproto, file_level_enum_descriptors_google_2fprotobuf_2ftype_2eproto, file_level_service_descriptors_google_2fprotobuf_2ftype_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
+descriptor_table_google_2fprotobuf_2ftype_2eproto_metadata_getter(int index) {
+  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2ftype_2eproto);
+  return descriptor_table_google_2fprotobuf_2ftype_2eproto.file_level_metadata[index];
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
 PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2ftype_2eproto(&descriptor_table_google_2fprotobuf_2ftype_2eproto);
@@ -396,12 +380,11 @@
 }
 
 void Type::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Type_google_2fprotobuf_2ftype_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&source_context_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&syntax_) -
-      reinterpret_cast<char*>(&source_context_)) + sizeof(syntax_));
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&source_context_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&syntax_) -
+    reinterpret_cast<char*>(&source_context_)) + sizeof(syntax_));
 }
 
 Type::~Type() {
@@ -425,11 +408,6 @@
 void Type::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Type& Type::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Type_google_2fprotobuf_2ftype_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Type::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Type)
@@ -782,15 +760,14 @@
 }
 
 void Field::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Field_google_2fprotobuf_2ftype_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  json_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  default_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&kind_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&packed_) -
-      reinterpret_cast<char*>(&kind_)) + sizeof(packed_));
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+json_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+default_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&kind_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&packed_) -
+    reinterpret_cast<char*>(&kind_)) + sizeof(packed_));
 }
 
 Field::~Field() {
@@ -816,11 +793,6 @@
 void Field::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Field& Field::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Field_google_2fprotobuf_2ftype_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Field::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Field)
@@ -1266,12 +1238,11 @@
 }
 
 void Enum::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Enum_google_2fprotobuf_2ftype_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
-      reinterpret_cast<char*>(&source_context_) - reinterpret_cast<char*>(this)),
-      0, static_cast<size_t>(reinterpret_cast<char*>(&syntax_) -
-      reinterpret_cast<char*>(&source_context_)) + sizeof(syntax_));
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+    reinterpret_cast<char*>(&source_context_) - reinterpret_cast<char*>(this)),
+    0, static_cast<size_t>(reinterpret_cast<char*>(&syntax_) -
+    reinterpret_cast<char*>(&source_context_)) + sizeof(syntax_));
 }
 
 Enum::~Enum() {
@@ -1295,11 +1266,6 @@
 void Enum::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Enum& Enum::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Enum_google_2fprotobuf_2ftype_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Enum::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Enum)
@@ -1600,9 +1566,8 @@
 }
 
 void EnumValue::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_EnumValue_google_2fprotobuf_2ftype_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  number_ = 0;
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+number_ = 0;
 }
 
 EnumValue::~EnumValue() {
@@ -1625,11 +1590,6 @@
 void EnumValue::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const EnumValue& EnumValue::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_EnumValue_google_2fprotobuf_2ftype_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void EnumValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValue)
@@ -1878,9 +1838,8 @@
 }
 
 void Option::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Option_google_2fprotobuf_2ftype_2eproto.base);
-  name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  value_ = nullptr;
+name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+value_ = nullptr;
 }
 
 Option::~Option() {
@@ -1904,11 +1863,6 @@
 void Option::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Option& Option::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Option_google_2fprotobuf_2ftype_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Option::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Option)
diff --git a/src/google/protobuf/type.pb.h b/src/google/protobuf/type.pb.h
index 66b2d37..a47a5fb 100644
--- a/src/google/protobuf/type.pb.h
+++ b/src/google/protobuf/type.pb.h
@@ -56,21 +56,22 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ftype_2eproto;
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2ftype_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class Enum;
-class EnumDefaultTypeInternal;
+struct EnumDefaultTypeInternal;
 PROTOBUF_EXPORT extern EnumDefaultTypeInternal _Enum_default_instance_;
 class EnumValue;
-class EnumValueDefaultTypeInternal;
+struct EnumValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern EnumValueDefaultTypeInternal _EnumValue_default_instance_;
 class Field;
-class FieldDefaultTypeInternal;
+struct FieldDefaultTypeInternal;
 PROTOBUF_EXPORT extern FieldDefaultTypeInternal _Field_default_instance_;
 class Option;
-class OptionDefaultTypeInternal;
+struct OptionDefaultTypeInternal;
 PROTOBUF_EXPORT extern OptionDefaultTypeInternal _Option_default_instance_;
 class Type;
-class TypeDefaultTypeInternal;
+struct TypeDefaultTypeInternal;
 PROTOBUF_EXPORT extern TypeDefaultTypeInternal _Type_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -183,6 +184,7 @@
  public:
   inline Type() : Type(nullptr) {}
   virtual ~Type();
+  explicit constexpr Type(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Type(const Type& from);
   Type(Type&& from) noexcept
@@ -212,8 +214,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Type& default_instance();
-
+  static const Type& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Type* internal_default_instance() {
     return reinterpret_cast<const Type*>(
                &_Type_default_instance_);
@@ -279,8 +282,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2ftype_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2ftype_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2ftype_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -423,6 +425,7 @@
  public:
   inline Field() : Field(nullptr) {}
   virtual ~Field();
+  explicit constexpr Field(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Field(const Field& from);
   Field(Field&& from) noexcept
@@ -452,8 +455,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Field& default_instance();
-
+  static const Field& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Field* internal_default_instance() {
     return reinterpret_cast<const Field*>(
                &_Field_default_instance_);
@@ -519,8 +523,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2ftype_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2ftype_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2ftype_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -793,6 +796,7 @@
  public:
   inline Enum() : Enum(nullptr) {}
   virtual ~Enum();
+  explicit constexpr Enum(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Enum(const Enum& from);
   Enum(Enum&& from) noexcept
@@ -822,8 +826,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Enum& default_instance();
-
+  static const Enum& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Enum* internal_default_instance() {
     return reinterpret_cast<const Enum*>(
                &_Enum_default_instance_);
@@ -889,8 +894,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2ftype_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2ftype_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2ftype_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -1007,6 +1011,7 @@
  public:
   inline EnumValue() : EnumValue(nullptr) {}
   virtual ~EnumValue();
+  explicit constexpr EnumValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumValue(const EnumValue& from);
   EnumValue(EnumValue&& from) noexcept
@@ -1036,8 +1041,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const EnumValue& default_instance();
-
+  static const EnumValue& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const EnumValue* internal_default_instance() {
     return reinterpret_cast<const EnumValue*>(
                &_EnumValue_default_instance_);
@@ -1103,8 +1109,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2ftype_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2ftype_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2ftype_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -1181,6 +1186,7 @@
  public:
   inline Option() : Option(nullptr) {}
   virtual ~Option();
+  explicit constexpr Option(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Option(const Option& from);
   Option(Option&& from) noexcept
@@ -1210,8 +1216,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Option& default_instance();
-
+  static const Option& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Option* internal_default_instance() {
     return reinterpret_cast<const Option*>(
                &_Option_default_instance_);
@@ -1277,8 +1284,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2ftype_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2ftype_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2ftype_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
diff --git a/src/google/protobuf/util/internal/datapiece.h b/src/google/protobuf/util/internal/datapiece.h
index 38ced17..03ea128 100644
--- a/src/google/protobuf/util/internal/datapiece.h
+++ b/src/google/protobuf/util/internal/datapiece.h
@@ -36,8 +36,8 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/type.pb.h>
-#include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/statusor.h>
+#include <google/protobuf/stubs/strutil.h>
 
 #include <google/protobuf/port_def.inc>
 
diff --git a/src/google/protobuf/util/internal/json_stream_parser.h b/src/google/protobuf/util/internal/json_stream_parser.h
index 2eb3532..5a9eac8 100644
--- a/src/google/protobuf/util/internal/json_stream_parser.h
+++ b/src/google/protobuf/util/internal/json_stream_parser.h
@@ -35,6 +35,7 @@
 #include <string>
 
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/status.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/status.h>
 
@@ -165,7 +166,7 @@
 
   // Parse a number as double into a NumberResult.
   util::Status ParseDoubleHelper(const std::string& number,
-                                   NumberResult* result);
+                                 NumberResult* result);
 
   // Handles a { during parsing of a value.
   util::Status HandleBeginObject();
diff --git a/src/google/protobuf/util/internal/object_source.h b/src/google/protobuf/util/internal/object_source.h
index 28b1aae..de548c1 100644
--- a/src/google/protobuf/util/internal/object_source.h
+++ b/src/google/protobuf/util/internal/object_source.h
@@ -32,6 +32,7 @@
 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_SOURCE_H__
 
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/status.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/status.h>
 
@@ -64,7 +65,7 @@
   // This is useful when you chain ObjectSource together by embedding one
   // within another.
   virtual util::Status NamedWriteTo(StringPiece name,
-                                      ObjectWriter* ow) const = 0;
+                                    ObjectWriter* ow) const = 0;
 
  protected:
   ObjectSource() {}
diff --git a/src/google/protobuf/util/internal/proto_writer.cc b/src/google/protobuf/util/internal/proto_writer.cc
index 24a7142..a082964 100644
--- a/src/google/protobuf/util/internal/proto_writer.cc
+++ b/src/google/protobuf/util/internal/proto_writer.cc
@@ -40,9 +40,9 @@
 #include <google/protobuf/util/internal/constants.h>
 #include <google/protobuf/util/internal/utility.h>
 #include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/statusor.h>
 #include <google/protobuf/stubs/time.h>
 #include <google/protobuf/stubs/map_util.h>
-#include <google/protobuf/stubs/statusor.h>
 
 
 #include <google/protobuf/port_def.inc>
diff --git a/src/google/protobuf/util/internal/proto_writer.h b/src/google/protobuf/util/internal/proto_writer.h
index 8149ed3..a98c5d8 100644
--- a/src/google/protobuf/util/internal/proto_writer.h
+++ b/src/google/protobuf/util/internal/proto_writer.h
@@ -46,6 +46,7 @@
 #include <google/protobuf/util/internal/structured_objectwriter.h>
 #include <google/protobuf/util/type_resolver.h>
 #include <google/protobuf/stubs/bytestream.h>
+#include <google/protobuf/stubs/status.h>
 #include <google/protobuf/stubs/hash.h>
 #include <google/protobuf/stubs/status.h>
 
@@ -314,11 +315,11 @@
  private:
   // Writes an ENUM field, including tag, to the stream.
   static util::Status WriteEnum(int field_number, const DataPiece& data,
-                                  const google::protobuf::Enum* enum_type,
-                                  io::CodedOutputStream* stream,
-                                  bool use_lower_camel_for_enums,
-                                  bool case_insensitive_enum_parsing,
-                                  bool ignore_unknown_values);
+                                const google::protobuf::Enum* enum_type,
+                                io::CodedOutputStream* stream,
+                                bool use_lower_camel_for_enums,
+                                bool case_insensitive_enum_parsing,
+                                bool ignore_unknown_values);
 
   // Variables for describing the structure of the input tree:
   // master_type_: descriptor for the whole protobuf message.
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc
index a941aa0..37811b3 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource.cc
@@ -114,41 +114,27 @@
 
 ProtoStreamObjectSource::ProtoStreamObjectSource(
     io::CodedInputStream* stream, TypeResolver* type_resolver,
-    const google::protobuf::Type& type)
+    const google::protobuf::Type& type, const RenderOptions& render_options)
     : stream_(stream),
       typeinfo_(TypeInfo::NewTypeInfo(type_resolver)),
       own_typeinfo_(true),
       type_(type),
-      use_lower_camel_for_enums_(false),
-      use_ints_for_enums_(false),
-      preserve_proto_field_names_(false),
+      render_options_(render_options),
       recursion_depth_(0),
-      max_recursion_depth_(kDefaultMaxRecursionDepth),
-      render_unknown_fields_(false),
-      render_unknown_enum_values_(true),
-      add_trailing_zeros_for_timestamp_and_duration_(false),
-      suppress_empty_object_(false),
-      use_legacy_json_map_format_(false) {
+      max_recursion_depth_(kDefaultMaxRecursionDepth) {
   GOOGLE_LOG_IF(DFATAL, stream == nullptr) << "Input stream is nullptr.";
 }
 
 ProtoStreamObjectSource::ProtoStreamObjectSource(
     io::CodedInputStream* stream, const TypeInfo* typeinfo,
-    const google::protobuf::Type& type)
+    const google::protobuf::Type& type, const RenderOptions& render_options)
     : stream_(stream),
       typeinfo_(typeinfo),
       own_typeinfo_(false),
       type_(type),
-      use_lower_camel_for_enums_(false),
-      use_ints_for_enums_(false),
-      preserve_proto_field_names_(false),
+      render_options_(render_options),
       recursion_depth_(0),
-      max_recursion_depth_(kDefaultMaxRecursionDepth),
-      render_unknown_fields_(false),
-      render_unknown_enum_values_(true),
-      add_trailing_zeros_for_timestamp_and_duration_(false),
-      suppress_empty_object_(false),
-      use_legacy_json_map_format_(false) {
+      max_recursion_depth_(kDefaultMaxRecursionDepth) {
   GOOGLE_LOG_IF(DFATAL, stream == nullptr) << "Input stream is nullptr.";
 }
 
@@ -198,9 +184,6 @@
   uint32 tag = stream_->ReadTag(), last_tag = tag + 1;
   UnknownFieldSet unknown_fields;
 
-  if (!name.empty() && tag == end_tag && suppress_empty_object_) {
-    return util::Status();
-  }
 
   if (include_start_and_end) {
     ow->StartObject(name);
@@ -210,7 +193,7 @@
       last_tag = tag;
       field = FindAndVerifyField(type, tag);
       if (field != nullptr) {
-        if (preserve_proto_field_names_) {
+        if (render_options_.preserve_proto_field_names) {
           field_name = field->name();
         } else {
           field_name = field->json_name();
@@ -220,8 +203,9 @@
     if (field == nullptr) {
       // If we didn't find a field, skip this unknown tag.
       // TODO(wpoon): Check return boolean value.
-      WireFormat::SkipField(stream_, tag,
-                            render_unknown_fields_ ? &unknown_fields : nullptr);
+      WireFormat::SkipField(
+          stream_, tag,
+                                                nullptr);
       tag = stream_->ReadTag();
       continue;
     }
@@ -390,7 +374,10 @@
   }
   std::string formatted_duration = StringPrintf(
       "%s%lld%ss", sign.c_str(), static_cast<long long>(seconds),  // NOLINT
-      FormatNanos(nanos, os->add_trailing_zeros_for_timestamp_and_duration_)
+      FormatNanos(
+          nanos,
+          false
+          )
           .c_str());
   ow->RenderString(field_name, formatted_duration);
   return util::Status();
@@ -646,14 +633,8 @@
   io::CodedInputStream in_stream(&zero_copy_stream);
   // We know the type so we can render it. Recursively parse the nested stream
   // using a nested ProtoStreamObjectSource using our nested type information.
-  ProtoStreamObjectSource nested_os(&in_stream, os->typeinfo_, *nested_type);
-
-  // TODO(htuch): This is somewhat fragile, since new options may be omitted.
-  // We should probably do this via the constructor or some object grouping
-  // options.
-  nested_os.set_use_lower_camel_for_enums(os->use_lower_camel_for_enums_);
-  nested_os.set_use_ints_for_enums(os->use_ints_for_enums_);
-  nested_os.set_preserve_proto_field_names(os->preserve_proto_field_names_);
+  ProtoStreamObjectSource nested_os(&in_stream, os->typeinfo_, *nested_type,
+                                    os->render_options_);
 
   // We manually call start and end object here so we can inject the @type.
   ow->StartObject(field_name);
@@ -888,19 +869,19 @@
         const google::protobuf::EnumValue* enum_value =
             FindEnumValueByNumber(*en, buffer32);
         if (enum_value != nullptr) {
-          if (use_ints_for_enums_) {
+          if (render_options_.use_ints_for_enums) {
             ow->RenderInt32(field_name, buffer32);
-          } else if (use_lower_camel_for_enums_) {
+          } else if (render_options_.use_lower_camel_for_enums) {
             ow->RenderString(field_name,
                              EnumValueNameToLowerCamelCase(enum_value->name()));
           } else {
             ow->RenderString(field_name, enum_value->name());
           }
-        } else if (render_unknown_enum_values_) {
-          ow->RenderInt32(field_name, buffer32);
+        } else {
+            ow->RenderInt32(field_name, buffer32);
         }
-      } else if (render_unknown_enum_values_) {
-        ow->RenderInt32(field_name, buffer32);
+      } else {
+          ow->RenderInt32(field_name, buffer32);
       }
       break;
     }
@@ -1130,8 +1111,9 @@
     return with_trailing_zeros ? ".000" : "";
   }
 
-  const char* format =
-      (nanos % 1000 != 0) ? "%.9f" : (nanos % 1000000 != 0) ? "%.6f" : "%.3f";
+  const char* format = (nanos % 1000 != 0)      ? "%.9f"
+                       : (nanos % 1000000 != 0) ? "%.6f"
+                                                : "%.3f";
   std::string formatted =
       StringPrintf(format, static_cast<double>(nanos) / kNanosPerSecond);
   // remove the leading 0 before decimal.
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h
index 9dce118..7d98b4e 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.h
+++ b/src/google/protobuf/util/internal/protostream_objectsource.h
@@ -35,16 +35,18 @@
 #include <string>
 #include <unordered_map>
 
+#include <google/protobuf/stubs/status.h>
+
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/type.pb.h>
 #include <google/protobuf/util/internal/type_info.h>
 #include <google/protobuf/util/internal/object_source.h>
 #include <google/protobuf/util/internal/object_writer.h>
 #include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/stubs/statusor.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/hash.h>
 #include <google/protobuf/stubs/status.h>
-#include <google/protobuf/stubs/statusor.h>
 
 
 #include <google/protobuf/port_def.inc>
@@ -71,14 +73,30 @@
 //   Status status = os.WriteTo(<some ObjectWriter>);
 class PROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
  public:
+  struct RenderOptions {
+    RenderOptions() {}
+    RenderOptions(const RenderOptions&) = default;
+
+    // whether to render enums using lowercamelcase.
+    bool use_lower_camel_for_enums = false;
+
+    // whether to render enums as ints always. defaults to false.
+    bool use_ints_for_enums = false;
+
+    // whether to preserve proto field names
+    bool preserve_proto_field_names = false;
+
+  };
+
   ProtoStreamObjectSource(io::CodedInputStream* stream,
                           TypeResolver* type_resolver,
-                          const google::protobuf::Type& type);
+                          const google::protobuf::Type& type,
+                          const RenderOptions& render_options = {});
 
   ~ProtoStreamObjectSource() override;
 
   util::Status NamedWriteTo(StringPiece name,
-                              ObjectWriter* ow) const override;
+                            ObjectWriter* ow) const override;
 
   // Sets whether or not to use lowerCamelCase casing for enum values. If set to
   // false, enum values are output without any case conversions.
@@ -105,16 +123,18 @@
   //   ...
   // }
   void set_use_lower_camel_for_enums(bool value) {
-    use_lower_camel_for_enums_ = value;
+    render_options_.use_lower_camel_for_enums = value;
   }
 
   // Sets whether to always output enums as ints, by default this is off, and
   // enums are rendered as strings.
-  void set_use_ints_for_enums(bool value) { use_ints_for_enums_ = value; }
+  void set_use_ints_for_enums(bool value) {
+    render_options_.use_ints_for_enums = value;
+  }
 
   // Sets whether to use original proto field names
   void set_preserve_proto_field_names(bool value) {
-    preserve_proto_field_names_ = value;
+    render_options_.preserve_proto_field_names = value;
   }
 
   // Sets the max recursion depth of proto message to be deserialized. Proto
@@ -132,10 +152,10 @@
   // The include_start_and_end parameter allows this method to be called when
   // already inside of an object, and skip calling StartObject and EndObject.
   virtual util::Status WriteMessage(const google::protobuf::Type& type,
-                                      StringPiece name,
-                                      const uint32 end_tag,
-                                      bool include_start_and_end,
-                                      ObjectWriter* ow) const;
+                                    StringPiece name,
+                                    const uint32 end_tag,
+                                    bool include_start_and_end,
+                                    ObjectWriter* ow) const;
 
   // Renders a repeating field (packed or unpacked).  Returns the next tag after
   // reading all sequential repeating elements. The caller should use this tag
@@ -150,8 +170,8 @@
 
   // Renders a field value to the ObjectWriter.
   virtual util::Status RenderField(const google::protobuf::Field* field,
-                                     StringPiece field_name,
-                                     ObjectWriter* ow) const;
+                                   StringPiece field_name,
+                                   ObjectWriter* ow) const;
 
   // Reads field value according to Field spec in 'field' and returns the read
   // value as string. This only works for primitive datatypes (no message
@@ -166,11 +186,12 @@
  private:
   ProtoStreamObjectSource(io::CodedInputStream* stream,
                           const TypeInfo* typeinfo,
-                          const google::protobuf::Type& type);
+                          const google::protobuf::Type& type,
+                          const RenderOptions& render_options);
   // Function that renders a well known type with a modified behavior.
   typedef util::Status (*TypeRenderer)(const ProtoStreamObjectSource*,
-                                         const google::protobuf::Type&,
-                                         StringPiece, ObjectWriter*);
+                                       const google::protobuf::Type&,
+                                       StringPiece, ObjectWriter*);
 
   // TODO(skarvaje): Mark these methods as non-const as they modify internal
   // state (stream_).
@@ -186,77 +207,75 @@
   // {tag length item1 item2 item3} instead of the less efficient
   // {tag item1 tag item2 tag item3}.
   util::Status RenderPacked(const google::protobuf::Field* field,
-                              ObjectWriter* ow) const;
+                            ObjectWriter* ow) const;
 
   // Renders a google.protobuf.Timestamp value to ObjectWriter
   static util::Status RenderTimestamp(const ProtoStreamObjectSource* os,
-                                        const google::protobuf::Type& type,
-                                        StringPiece name,
-                                        ObjectWriter* ow);
+                                      const google::protobuf::Type& type,
+                                      StringPiece name, ObjectWriter* ow);
 
   // Renders a google.protobuf.Duration value to ObjectWriter
   static util::Status RenderDuration(const ProtoStreamObjectSource* os,
-                                       const google::protobuf::Type& type,
-                                       StringPiece name,
-                                       ObjectWriter* ow);
+                                     const google::protobuf::Type& type,
+                                     StringPiece name, ObjectWriter* ow);
 
   // Following RenderTYPE functions render well known types in
   // google/protobuf/wrappers.proto corresponding to TYPE.
   static util::Status RenderDouble(const ProtoStreamObjectSource* os,
-                                     const google::protobuf::Type& type,
-                                     StringPiece name, ObjectWriter* ow);
-  static util::Status RenderFloat(const ProtoStreamObjectSource* os,
-                                    const google::protobuf::Type& type,
-                                    StringPiece name, ObjectWriter* ow);
-  static util::Status RenderInt64(const ProtoStreamObjectSource* os,
-                                    const google::protobuf::Type& type,
-                                    StringPiece name, ObjectWriter* ow);
-  static util::Status RenderUInt64(const ProtoStreamObjectSource* os,
-                                     const google::protobuf::Type& type,
-                                     StringPiece name, ObjectWriter* ow);
-  static util::Status RenderInt32(const ProtoStreamObjectSource* os,
-                                    const google::protobuf::Type& type,
-                                    StringPiece name, ObjectWriter* ow);
-  static util::Status RenderUInt32(const ProtoStreamObjectSource* os,
-                                     const google::protobuf::Type& type,
-                                     StringPiece name, ObjectWriter* ow);
-  static util::Status RenderBool(const ProtoStreamObjectSource* os,
                                    const google::protobuf::Type& type,
                                    StringPiece name, ObjectWriter* ow);
+  static util::Status RenderFloat(const ProtoStreamObjectSource* os,
+                                  const google::protobuf::Type& type,
+                                  StringPiece name, ObjectWriter* ow);
+  static util::Status RenderInt64(const ProtoStreamObjectSource* os,
+                                  const google::protobuf::Type& type,
+                                  StringPiece name, ObjectWriter* ow);
+  static util::Status RenderUInt64(const ProtoStreamObjectSource* os,
+                                   const google::protobuf::Type& type,
+                                   StringPiece name, ObjectWriter* ow);
+  static util::Status RenderInt32(const ProtoStreamObjectSource* os,
+                                  const google::protobuf::Type& type,
+                                  StringPiece name, ObjectWriter* ow);
+  static util::Status RenderUInt32(const ProtoStreamObjectSource* os,
+                                   const google::protobuf::Type& type,
+                                   StringPiece name, ObjectWriter* ow);
+  static util::Status RenderBool(const ProtoStreamObjectSource* os,
+                                 const google::protobuf::Type& type,
+                                 StringPiece name, ObjectWriter* ow);
   static util::Status RenderString(const ProtoStreamObjectSource* os,
-                                     const google::protobuf::Type& type,
-                                     StringPiece name, ObjectWriter* ow);
+                                   const google::protobuf::Type& type,
+                                   StringPiece name, ObjectWriter* ow);
   static util::Status RenderBytes(const ProtoStreamObjectSource* os,
-                                    const google::protobuf::Type& type,
-                                    StringPiece name, ObjectWriter* ow);
-
-  // Renders a google.protobuf.Struct to ObjectWriter.
-  static util::Status RenderStruct(const ProtoStreamObjectSource* os,
-                                     const google::protobuf::Type& type,
-                                     StringPiece name, ObjectWriter* ow);
-
-  // Helper to render google.protobuf.Struct's Value fields to ObjectWriter.
-  static util::Status RenderStructValue(const ProtoStreamObjectSource* os,
-                                          const google::protobuf::Type& type,
-                                          StringPiece name,
-                                          ObjectWriter* ow);
-
-  // Helper to render google.protobuf.Struct's ListValue fields to ObjectWriter.
-  static util::Status RenderStructListValue(
-      const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
-      StringPiece name, ObjectWriter* ow);
-
-  // Render the "Any" type.
-  static util::Status RenderAny(const ProtoStreamObjectSource* os,
                                   const google::protobuf::Type& type,
                                   StringPiece name, ObjectWriter* ow);
 
-  // Render the "FieldMask" type.
-  static util::Status RenderFieldMask(const ProtoStreamObjectSource* os,
+  // Renders a google.protobuf.Struct to ObjectWriter.
+  static util::Status RenderStruct(const ProtoStreamObjectSource* os,
+                                   const google::protobuf::Type& type,
+                                   StringPiece name, ObjectWriter* ow);
+
+  // Helper to render google.protobuf.Struct's Value fields to ObjectWriter.
+  static util::Status RenderStructValue(const ProtoStreamObjectSource* os,
                                         const google::protobuf::Type& type,
                                         StringPiece name,
                                         ObjectWriter* ow);
 
+  // Helper to render google.protobuf.Struct's ListValue fields to ObjectWriter.
+  static util::Status RenderStructListValue(const ProtoStreamObjectSource* os,
+                                            const google::protobuf::Type& type,
+                                            StringPiece name,
+                                            ObjectWriter* ow);
+
+  // Render the "Any" type.
+  static util::Status RenderAny(const ProtoStreamObjectSource* os,
+                                const google::protobuf::Type& type,
+                                StringPiece name, ObjectWriter* ow);
+
+  // Render the "FieldMask" type.
+  static util::Status RenderFieldMask(const ProtoStreamObjectSource* os,
+                                      const google::protobuf::Type& type,
+                                      StringPiece name, ObjectWriter* ow);
+
   static std::unordered_map<std::string, TypeRenderer>* renderers_;
   static void InitRendererMap();
   static void DeleteRendererMap();
@@ -265,8 +284,8 @@
   // Same as above but renders all non-message field types. Callers don't call
   // this function directly. They just use RenderField.
   util::Status RenderNonMessageField(const google::protobuf::Field* field,
-                                       StringPiece field_name,
-                                       ObjectWriter* ow) const;
+                                     StringPiece field_name,
+                                     ObjectWriter* ow) const;
 
 
   // Utility function to detect proto maps. The 'field' MUST be repeated.
@@ -281,7 +300,7 @@
   // Status::OK if the current depth is allowed. Otherwise an error is returned.
   // type_name and field_name are used for error reporting.
   util::Status IncrementRecursionDepth(StringPiece type_name,
-                                         StringPiece field_name) const;
+                                       StringPiece field_name) const;
 
   // Input stream to read from. Ownership rests with the caller.
   mutable io::CodedInputStream* stream_;
@@ -298,14 +317,7 @@
   const google::protobuf::Type& type_;
 
 
-  // Whether to render enums using lowerCamelCase. Defaults to false.
-  bool use_lower_camel_for_enums_;
-
-  // Whether to render enums as ints always. Defaults to false.
-  bool use_ints_for_enums_;
-
-  // Whether to preserve proto field names
-  bool preserve_proto_field_names_;
+  RenderOptions render_options_;
 
   // Tracks current recursion depth.
   mutable int recursion_depth_;
@@ -313,22 +325,6 @@
   // Maximum allowed recursion depth.
   int max_recursion_depth_;
 
-  // Whether to render unknown fields.
-  bool render_unknown_fields_;
-
-  // Whether to render unknown enum values.
-  bool render_unknown_enum_values_;
-
-  // Whether to add trailing zeros for timestamp and duration.
-  bool add_trailing_zeros_for_timestamp_and_duration_;
-
-  // Whether output the empty object or not. If false, output JSON string like:
-  // "'objectName' : {}". If true, then no outputs. This only happens when all
-  // the fields of the message are filtered out by field mask.
-  bool suppress_empty_object_;
-
-  bool use_legacy_json_map_format_;
-
   GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectSource);
 };
 
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc
index ace209a..bccea1f 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc
@@ -43,9 +43,9 @@
 #include <google/protobuf/util/internal/utility.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/statusor.h>
 #include <google/protobuf/stubs/time.h>
 #include <google/protobuf/stubs/map_util.h>
-#include <google/protobuf/stubs/statusor.h>
 
 
 #include <google/protobuf/port_def.inc>
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h
index a5bea40..be810ed 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.h
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.h
@@ -48,6 +48,7 @@
 #include <google/protobuf/util/internal/structured_objectwriter.h>
 #include <google/protobuf/util/type_resolver.h>
 #include <google/protobuf/stubs/bytestream.h>
+#include <google/protobuf/stubs/status.h>
 #include <google/protobuf/stubs/hash.h>
 
 #include <google/protobuf/port_def.inc>
@@ -156,7 +157,7 @@
  protected:
   // Function that renders a well known type with modified behavior.
   typedef util::Status (*TypeRenderer)(ProtoStreamObjectWriter*,
-                                         const DataPiece&);
+                                       const DataPiece&);
 
   // Handles writing Anys out using nested object writers and the like.
   class PROTOBUF_EXPORT AnyWriter {
@@ -365,24 +366,24 @@
   // Renders google.protobuf.Value in struct.proto. It picks the right oneof
   // type based on value's type.
   static util::Status RenderStructValue(ProtoStreamObjectWriter* ow,
-                                          const DataPiece& data);
+                                        const DataPiece& data);
 
   // Renders google.protobuf.Timestamp value.
   static util::Status RenderTimestamp(ProtoStreamObjectWriter* ow,
-                                        const DataPiece& data);
+                                      const DataPiece& data);
 
   // Renders google.protobuf.FieldMask value.
   static util::Status RenderFieldMask(ProtoStreamObjectWriter* ow,
-                                        const DataPiece& data);
+                                      const DataPiece& data);
 
   // Renders google.protobuf.Duration value.
   static util::Status RenderDuration(ProtoStreamObjectWriter* ow,
-                                       const DataPiece& data);
+                                     const DataPiece& data);
 
   // Renders wrapper message types for primitive types in
   // google/protobuf/wrappers.proto.
   static util::Status RenderWrapperType(ProtoStreamObjectWriter* ow,
-                                          const DataPiece& data);
+                                        const DataPiece& data);
 
   static void InitRendererMap();
   static void DeleteRendererMap();
diff --git a/src/google/protobuf/util/internal/testdata/anys.proto b/src/google/protobuf/util/internal/testdata/anys.proto
index 64b9f9d..b6fc3f6 100644
--- a/src/google/protobuf/util/internal/testdata/anys.proto
+++ b/src/google/protobuf/util/internal/testdata/anys.proto
@@ -34,6 +34,7 @@
 
 import "google/protobuf/any.proto";
 import "google/protobuf/duration.proto";
+import "google/protobuf/empty.proto";
 import "google/protobuf/struct.proto";
 import "google/protobuf/timestamp.proto";
 import "google/protobuf/wrappers.proto";
@@ -59,6 +60,8 @@
   AnyWrapper recursive_any_with_type_field_at_end = 15;
   AnyWrapper repeated_any = 16;
   AnyWrapper empty_any_with_null_type_url = 17;
+  AnyWrapper any_with_empty = 18;
+  AnyWrapper any_with_default_timestamp = 19;
 
   google.protobuf.Any top_level_any = 50;
   google.protobuf.Any top_level_any_with_type_field_at_end = 51;
@@ -79,6 +82,7 @@
   google.protobuf.Timestamp timestamp = 3;
   google.protobuf.Duration duration = 4;
   google.protobuf.Int32Value i32 = 5;
+  google.protobuf.Empty empty = 6;
   Data data = 100;
 }
 
diff --git a/src/google/protobuf/util/internal/type_info.cc b/src/google/protobuf/util/internal/type_info.cc
index e91afa0..aaa37d1 100644
--- a/src/google/protobuf/util/internal/type_info.cc
+++ b/src/google/protobuf/util/internal/type_info.cc
@@ -37,10 +37,10 @@
 #include <google/protobuf/type.pb.h>
 #include <google/protobuf/util/internal/utility.h>
 #include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/statusor.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/map_util.h>
 #include <google/protobuf/stubs/status.h>
-#include <google/protobuf/stubs/statusor.h>
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/util/internal/type_info.h b/src/google/protobuf/util/internal/type_info.h
index eb5c857..d8d679e 100644
--- a/src/google/protobuf/util/internal/type_info.h
+++ b/src/google/protobuf/util/internal/type_info.h
@@ -34,9 +34,9 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/type.pb.h>
 #include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/stubs/statusor.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/status.h>
-#include <google/protobuf/stubs/statusor.h>
 
 // Must be included last.
 #include <google/protobuf/port_def.inc>
diff --git a/src/google/protobuf/util/internal/utility.h b/src/google/protobuf/util/internal/utility.h
index d92e41e..965579a 100644
--- a/src/google/protobuf/util/internal/utility.h
+++ b/src/google/protobuf/util/internal/utility.h
@@ -41,8 +41,8 @@
 #include <google/protobuf/type.pb.h>
 #include <google/protobuf/repeated_field.h>
 #include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/status.h>
 #include <google/protobuf/stubs/statusor.h>
+#include <google/protobuf/stubs/status.h>
 
 // Must be included last.
 #include <google/protobuf/port_def.inc>
diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc
index 6ced27c..4cf720e 100644
--- a/src/google/protobuf/util/json_util.cc
+++ b/src/google/protobuf/util/json_util.cc
@@ -43,10 +43,13 @@
 #include <google/protobuf/util/type_resolver.h>
 #include <google/protobuf/util/type_resolver_util.h>
 #include <google/protobuf/stubs/bytestream.h>
+#include <google/protobuf/stubs/status.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/status_macros.h>
 
+// clang-format off
 #include <google/protobuf/port_def.inc>
+// clang-format on
 
 namespace google {
 namespace protobuf {
@@ -82,10 +85,10 @@
 }  // namespace internal
 
 util::Status BinaryToJsonStream(TypeResolver* resolver,
-                                  const std::string& type_url,
-                                  io::ZeroCopyInputStream* binary_input,
-                                  io::ZeroCopyOutputStream* json_output,
-                                  const JsonPrintOptions& options) {
+                                const std::string& type_url,
+                                io::ZeroCopyInputStream* binary_input,
+                                io::ZeroCopyOutputStream* json_output,
+                                const JsonPrintOptions& options) {
   io::CodedInputStream in_stream(binary_input);
   google::protobuf::Type type;
   RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type));
@@ -110,10 +113,10 @@
 }
 
 util::Status BinaryToJsonString(TypeResolver* resolver,
-                                  const std::string& type_url,
-                                  const std::string& binary_input,
-                                  std::string* json_output,
-                                  const JsonPrintOptions& options) {
+                                const std::string& type_url,
+                                const std::string& binary_input,
+                                std::string* json_output,
+                                const JsonPrintOptions& options) {
   io::ArrayInputStream input_stream(binary_input.data(), binary_input.size());
   io::StringOutputStream output_stream(json_output);
   return BinaryToJsonStream(resolver, type_url, &input_stream, &output_stream,
@@ -137,7 +140,7 @@
     }
     status_ =
         util::Status(util::error::INVALID_ARGUMENT,
-                       StrCat(loc_string, unknown_name, ": ", message));
+                     StrCat(loc_string, unknown_name, ": ", message));
   }
 
   void InvalidValue(const converter::LocationTrackerInterface& loc,
@@ -152,8 +155,8 @@
   void MissingField(const converter::LocationTrackerInterface& loc,
                     StringPiece missing_name) override {
     status_ = util::Status(util::error::INVALID_ARGUMENT,
-                             StrCat(GetLocString(loc), ": missing field ",
-                                          std::string(missing_name)));
+                           StrCat(GetLocString(loc), ": missing field ",
+                                        std::string(missing_name)));
   }
 
  private:
@@ -173,10 +176,10 @@
 }  // namespace
 
 util::Status JsonToBinaryStream(TypeResolver* resolver,
-                                  const std::string& type_url,
-                                  io::ZeroCopyInputStream* json_input,
-                                  io::ZeroCopyOutputStream* binary_output,
-                                  const JsonParseOptions& options) {
+                                const std::string& type_url,
+                                io::ZeroCopyInputStream* json_input,
+                                io::ZeroCopyOutputStream* binary_output,
+                                const JsonParseOptions& options) {
   google::protobuf::Type type;
   RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type));
   internal::ZeroCopyStreamByteSink sink(binary_output);
@@ -204,10 +207,10 @@
 }
 
 util::Status JsonToBinaryString(TypeResolver* resolver,
-                                  const std::string& type_url,
-                                  StringPiece json_input,
-                                  std::string* binary_output,
-                                  const JsonParseOptions& options) {
+                                const std::string& type_url,
+                                StringPiece json_input,
+                                std::string* binary_output,
+                                const JsonParseOptions& options) {
   io::ArrayInputStream input_stream(json_input.data(), json_input.size());
   io::StringOutputStream output_stream(binary_output);
   return JsonToBinaryStream(resolver, type_url, &input_stream, &output_stream,
@@ -240,7 +243,7 @@
 }  // namespace
 
 util::Status MessageToJsonString(const Message& message, std::string* output,
-                                   const JsonOptions& options) {
+                                 const JsonOptions& options) {
   const DescriptorPool* pool = message.GetDescriptor()->file()->pool();
   TypeResolver* resolver =
       pool == DescriptorPool::generated_pool()
@@ -256,7 +259,7 @@
 }
 
 util::Status JsonStringToMessage(StringPiece input, Message* message,
-                                   const JsonParseOptions& options) {
+                                 const JsonParseOptions& options) {
   const DescriptorPool* pool = message->GetDescriptor()->file()->pool();
   TypeResolver* resolver =
       pool == DescriptorPool::generated_pool()
@@ -264,11 +267,10 @@
           : NewTypeResolverForDescriptorPool(kTypeUrlPrefix, pool);
   std::string binary;
   util::Status result = JsonToBinaryString(resolver, GetTypeUrl(*message),
-                                             input, &binary, options);
+                                           input, &binary, options);
   if (result.ok() && !message->ParseFromString(binary)) {
-    result =
-        util::Status(util::error::INVALID_ARGUMENT,
-                       "JSON transcoder produced invalid protobuf output.");
+    result = util::Status(util::error::INVALID_ARGUMENT,
+                          "JSON transcoder produced invalid protobuf output.");
   }
   if (pool != DescriptorPool::generated_pool()) {
     delete resolver;
diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc
index 68af4d1..bf016e4 100644
--- a/src/google/protobuf/util/message_differencer.cc
+++ b/src/google/protobuf/util/message_differencer.cc
@@ -35,6 +35,7 @@
 #include <google/protobuf/util/message_differencer.h>
 
 #include <algorithm>
+#include <cstddef>
 #include <functional>
 #include <memory>
 #include <utility>
@@ -46,8 +47,11 @@
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
 #include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/generated_enum_reflection.h>
 #include <google/protobuf/map_field.h>
+#include <google/protobuf/message.h>
 #include <google/protobuf/text_format.h>
 #include <google/protobuf/util/field_comparator.h>
 #include <google/protobuf/stubs/strutil.h>
@@ -184,8 +188,8 @@
 // element. The optimal solution requires to use //util/diff/lcs.h, which is
 // not open sourced yet. Overwrite this method if you want to have that.
 // TODO(ykzhu): change to use LCS once it is open sourced.
-void MatchIndicesPostProcessorForSmartList(
-    std::vector<int>* match_list1, std::vector<int>* match_list2) {
+void MatchIndicesPostProcessorForSmartList(std::vector<int>* match_list1,
+                                           std::vector<int>* match_list2) {
   int last_matched_index = -1;
   for (size_t i = 0; i < match_list1->size(); ++i) {
     if (match_list1->at(i) < 0) {
@@ -485,18 +489,17 @@
   std::vector<SpecificField> parent_fields;
 
   bool result = false;
-
   // Setup the internal reporter if need be.
   if (output_string_) {
     io::StringOutputStream output_stream(output_string_);
     StreamReporter reporter(&output_stream);
+    reporter.SetMessages(message1, message2);
     reporter_ = &reporter;
     result = Compare(message1, message2, &parent_fields);
     reporter_ = NULL;
   } else {
     result = Compare(message1, message2, &parent_fields);
   }
-
   return result;
 }
 
@@ -556,11 +559,13 @@
                 << descriptor2->full_name();
     return false;
   }
+
   // Expand google.protobuf.Any payload if possible.
   if (descriptor1->full_name() == internal::kAnyFullTypeName) {
     std::unique_ptr<Message> data1;
     std::unique_ptr<Message> data2;
-    if (UnpackAny(message1, &data1) && UnpackAny(message2, &data2)) {
+    if (unpack_any_field_.UnpackAny(message1, &data1) &&
+        unpack_any_field_.UnpackAny(message2, &data2)) {
       // Avoid DFATAL for different descriptors in google.protobuf.Any payloads.
       if (data1->GetDescriptor() != data2->GetDescriptor()) {
         return false;
@@ -590,10 +595,10 @@
   FieldDescriptorArray message1_fields = RetrieveFields(message1, true);
   FieldDescriptorArray message2_fields = RetrieveFields(message2, false);
 
-  return CompareRequestedFieldsUsingSettings(
-      message1, message2,
-      message1_fields, message2_fields,
-      parent_fields) && unknown_compare_result;
+  return CompareRequestedFieldsUsingSettings(message1, message2,
+                                             message1_fields, message2_fields,
+                                             parent_fields) &&
+         unknown_compare_result;
 }
 
 FieldDescriptorArray MessageDifferencer::RetrieveFields(const Message& message,
@@ -733,7 +738,6 @@
         if (reporter_ != NULL) {
           SpecificField specific_field;
           specific_field.field = field1;
-
           parent_fields->push_back(specific_field);
           if (report_ignores_) {
             reporter_->ReportIgnored(message1, message2, *parent_fields);
@@ -775,7 +779,6 @@
         if (reporter_ != NULL) {
           SpecificField specific_field;
           specific_field.field = field2;
-
           parent_fields->push_back(specific_field);
           if (report_ignores_) {
             reporter_->ReportIgnored(message1, message2, *parent_fields);
@@ -818,7 +821,6 @@
       if (reporter_ != NULL) {
         SpecificField specific_field;
         specific_field.field = field1;
-
         parent_fields->push_back(specific_field);
         if (report_ignores_) {
           reporter_->ReportIgnored(message1, message2, *parent_fields);
@@ -1336,8 +1338,8 @@
 
 }  // namespace
 
-bool MessageDifferencer::UnpackAny(const Message& any,
-                                   std::unique_ptr<Message>* data) {
+bool MessageDifferencer::UnpackAnyField::UnpackAny(
+    const Message& any, std::unique_ptr<Message>* data) {
   const Reflection* reflection = any.GetReflection();
   const FieldDescriptor* type_url_field;
   const FieldDescriptor* value_field;
@@ -1870,12 +1872,16 @@
     io::ZeroCopyOutputStream* output)
     : printer_(new io::Printer(output, '$')),
       delete_printer_(true),
-      report_modified_aggregates_(false) {}
+      report_modified_aggregates_(false),
+      message1_(nullptr),
+      message2_(nullptr) {}
 
 MessageDifferencer::StreamReporter::StreamReporter(io::Printer* printer)
     : printer_(printer),
       delete_printer_(false),
-      report_modified_aggregates_(false) {}
+      report_modified_aggregates_(false),
+      message1_(nullptr),
+      message2_(nullptr) {}
 
 MessageDifferencer::StreamReporter::~StreamReporter() {
   if (delete_printer_) delete printer_;
@@ -1884,20 +1890,28 @@
 void MessageDifferencer::StreamReporter::PrintPath(
     const std::vector<SpecificField>& field_path, bool left_side) {
   for (size_t i = 0; i < field_path.size(); ++i) {
+    SpecificField specific_field = field_path[i];
+
+    if (specific_field.field != nullptr &&
+        specific_field.field->name() == "value") {
+      // check to see if this the value label of a map value.  If so, skip it
+      // because it isn't meaningful
+      if (i > 0 && field_path[i - 1].field->is_map()) {
+        continue;
+      }
+    }
     if (i > 0) {
       printer_->Print(".");
     }
-
-    SpecificField specific_field = field_path[i];
-
     if (specific_field.field != NULL) {
       if (specific_field.field->is_extension()) {
         printer_->Print("($name$)", "name", specific_field.field->full_name());
       } else {
         printer_->PrintRaw(specific_field.field->name());
       }
+
       if (specific_field.field->is_map()) {
-        // Don't print index in a map field; they are semantically unordered.
+        PrintMapKey(field_path, left_side, specific_field, i);
         continue;
       }
     } else {
@@ -1933,11 +1947,29 @@
           field->is_repeated()
               ? reflection->GetRepeatedMessage(message, field, index)
               : reflection->GetMessage(message, field);
-      output = field_message.ShortDebugString();
+      const FieldDescriptor* fd = nullptr;
+
+      if (field->is_map() && message1_ != nullptr && message2_ != nullptr) {
+        fd = field_message.GetDescriptor()->field(1);
+        if (fd->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+          output = field_message.GetReflection()
+                       ->GetMessage(field_message, fd)
+                       .ShortDebugString();
+        } else {
+          TextFormat::PrintFieldValueToString(field_message, fd, -1, &output);
+        }
+      } else {
+        output = field_message.ShortDebugString();
+      }
       if (output.empty()) {
         printer_->Print("{ }");
       } else {
-        printer_->Print("{ $name$ }", "name", output);
+        if ((fd != nullptr) &&
+            (fd->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)) {
+          printer_->PrintRaw(output);
+        } else {
+          printer_->Print("{ $name$ }", "name", output);
+        }
       }
     } else {
       TextFormat::PrintFieldValueToString(message, field, index, &output);
@@ -1989,6 +2021,81 @@
   printer_->Print(str.c_str());
 }
 
+void MessageDifferencer::StreamReporter::PrintMapKey(
+    const std::vector<SpecificField>& field_path, bool left_side,
+    const SpecificField& specific_field, size_t target_field_index) {
+  if (message1_ == nullptr || message2_ == nullptr) {
+    GOOGLE_LOG(WARNING) << "PrintPath cannot log map keys; "
+                    "use SetMessages to provide the messages "
+                    "being compared prior to any processing.";
+    return;
+  }
+  auto get_target_message = [=](const SpecificField& specific_field,
+                                const Reflection* reflection,
+                                const Message* message) {
+    return &(
+        specific_field.field->is_repeated()
+            ? reflection->GetRepeatedMessage(
+                  *message, specific_field.field,
+                  left_side ? specific_field.index : specific_field.new_index)
+            : reflection->GetMessage(*message, specific_field.field));
+  };
+
+  std::unique_ptr<Message> deserialized_msg;  // used for protobuf.Any case
+  std::unique_ptr<DynamicMessageFactory> dynamic_message_factory;
+  const Message* found_message = left_side ? message1_ : message2_;
+  for (size_t j = 0; j <= target_field_index;
+       j++) {  // iterate until we find target field
+    if (specific_field.field->is_repeated()) {
+      int index = left_side ? specific_field.index : specific_field.new_index;
+      if (index < 0) {
+        // Filtered messages fall in this case
+        GOOGLE_LOG(WARNING) << "Invalid index " << index << " for map.\n";
+        found_message = nullptr;
+        break;
+      }
+    }
+    if (found_message->GetTypeName() == "google.protobuf.Any") {
+      if (!unpack_any_field_.UnpackAny(*found_message, &deserialized_msg)) {
+        GOOGLE_LOG(ERROR) << "Cannot print Any message map key due to "
+                      "unpacking error\n";
+        found_message = nullptr;
+        break;
+      }
+
+      found_message =
+          get_target_message(field_path[j], deserialized_msg->GetReflection(),
+                             deserialized_msg.get());
+
+    } else {
+      found_message = get_target_message(
+          field_path[j], found_message->GetReflection(), found_message);
+    }
+  }
+
+  std::string key_string = "";
+  if (found_message != nullptr) {
+    // NB: the map key is always the first field
+    const FieldDescriptor* fd = found_message->GetDescriptor()->field(0);
+    if (fd->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      key_string = found_message->GetReflection()
+                       ->GetMessage(*found_message, fd)
+                       .ShortDebugString();
+    } else if (fd->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+      // Not using PrintFieldValueToString for strings to avoid extra
+      // characters
+      key_string = found_message->GetReflection()->GetString(
+          *found_message, found_message->GetDescriptor()->field(0));
+    } else {
+      TextFormat::PrintFieldValueToString(*found_message, fd, -1, &key_string);
+    }
+    if (key_string.empty()) {
+      key_string = "''";
+    }
+    printer_->PrintRaw(StrCat("[", key_string, "]"));
+  }
+}
+
 void MessageDifferencer::StreamReporter::ReportAdded(
     const Message& message1, const Message& message2,
     const std::vector<SpecificField>& field_path) {
@@ -2076,6 +2183,12 @@
   printer_->Print("\n");  // Print for newlines.
 }
 
+void MessageDifferencer::StreamReporter::SetMessages(const Message& message1,
+                                                     const Message& message2) {
+  message1_ = &message1;
+  message2_ = &message2;
+}
+
 void MessageDifferencer::StreamReporter::ReportUnknownFieldIgnored(
     const Message& message1, const Message& message2,
     const std::vector<SpecificField>& field_path) {
diff --git a/src/google/protobuf/util/message_differencer.h b/src/google/protobuf/util/message_differencer.h
index 2384e51..5889a9a 100644
--- a/src/google/protobuf/util/message_differencer.h
+++ b/src/google/protobuf/util/message_differencer.h
@@ -37,13 +37,15 @@
 //
 // Aug. 2008: Added Unknown Fields Comparison for messages.
 // Aug. 2009: Added different options to compare repeated fields.
-// Apr. 2010: Moved field comparison to FieldComparator.
+// Apr. 2010: Moved field comparison to FieldComparator
+// Sep. 2020: Added option to output map keys in path
 
 #ifndef GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
 #define GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
 
 #include <functional>
 #include <map>
+#include <memory>
 #include <set>
 #include <string>
 #include <vector>
@@ -206,6 +208,20 @@
     int unknown_field_index2 = -1;
   };
 
+  // Class for processing Any deserialization.  This logic is used by both the
+  // MessageDifferencer and StreamReporter classes.
+  class UnpackAnyField {
+   private:
+    std::unique_ptr<DynamicMessageFactory> dynamic_message_factory_;
+
+   public:
+    UnpackAnyField() = default;
+    ~UnpackAnyField() = default;
+    // If "any" is of type google.protobuf.Any, extract its payload using
+    // DynamicMessageFactory and store in "data".
+    bool UnpackAny(const Message& any, std::unique_ptr<Message>* data);
+  };
+
   // Abstract base class from which all MessageDifferencer
   // reporters derive. The five Report* methods below will be called when
   // a field has been added, deleted, modified, moved, or matched. The third
@@ -652,6 +668,10 @@
         const Message& message1, const Message& message2,
         const std::vector<SpecificField>& field_path) override;
 
+    // Messages that are being compared must be provided to StreamReporter prior
+    // to processing
+    void SetMessages(const Message& message1, const Message& message2);
+
    protected:
     // Prints the specified path of fields to the buffer.  message is used to
     // print map keys.
@@ -677,11 +697,18 @@
     // Just print a string
     void Print(const std::string& str);
 
+    // helper function for PrintPath that contains logic for printing maps
+    void PrintMapKey(const std::vector<SpecificField>& field_path,
+                     bool left_side, const SpecificField& specific_field,
+                     size_t target_field_index);
+
    private:
     io::Printer* printer_;
     bool delete_printer_;
     bool report_modified_aggregates_;
-
+    const Message* message1_;
+    const Message* message2_;
+    MessageDifferencer::UnpackAnyField unpack_any_field_;
     GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StreamReporter);
   };
 
@@ -848,10 +875,6 @@
       const std::vector<SpecificField>& parent_fields,
       std::vector<int>* match_list1, std::vector<int>* match_list2);
 
-  // If "any" is of type google.protobuf.Any, extract its payload using
-  // DynamicMessageFactory and store in "data".
-  bool UnpackAny(const Message& any, std::unique_ptr<Message>* data);
-
   // Checks if index is equal to new_index in all the specific fields.
   static bool CheckPathChanged(const std::vector<SpecificField>& parent_fields);
 
@@ -904,7 +927,7 @@
   std::function<void(std::vector<int>*, std::vector<int>*)>
       match_indices_for_smart_list_callback_;
 
-  std::unique_ptr<DynamicMessageFactory> dynamic_message_factory_;
+  MessageDifferencer::UnpackAnyField unpack_any_field_;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageDifferencer);
 };
 
diff --git a/src/google/protobuf/util/message_differencer_unittest.cc b/src/google/protobuf/util/message_differencer_unittest.cc
index 3d36e85..5a333b3 100644
--- a/src/google/protobuf/util/message_differencer_unittest.cc
+++ b/src/google/protobuf/util/message_differencer_unittest.cc
@@ -39,8 +39,11 @@
 #include <string>
 #include <vector>
 
+#include <google/protobuf/stubs/common.h>
+
 #include <google/protobuf/stubs/strutil.h>
 
+#include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/any_test.pb.h>
 #include <google/protobuf/map_test_util.h>
 #include <google/protobuf/map_unittest.pb.h>
@@ -53,9 +56,6 @@
 #include <google/protobuf/util/message_differencer_unittest.pb.h>
 #include <google/protobuf/util/field_comparator.h>
 #include <google/protobuf/util/message_differencer.h>
-
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 
@@ -1783,6 +1783,43 @@
       output);
 }
 
+TEST(MessageDifferencerTest, PrintMapKeysTest) {
+  // Note that because map is unordered, the comparison
+  // output string for test evaluation cannot assume order of
+  // output of fields (IOW if two fields are deleted
+  // one cannot assume which deleted field log will be printed first).
+  // Test currently just has a single record per operation to address this.
+  // This should only be a limitation for EXPECT_EQ evaluation.
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+  protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+  item->mutable_mp()->insert({{"key_a", 1}, {"key_b", 2}, {"key_c", 3}});
+  item = msg2.add_item();
+  item->mutable_mp()->insert({{"key_a", 1}, {"key_b", 3}, {"key_d", 4}});
+
+  util::MessageDifferencer differencer;
+  std::string diff;
+  differencer.ReportDifferencesToString(&diff);
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+  EXPECT_EQ(
+      "modified: item[0].mp[key_b]: 2 -> 3\n"
+      "added: item[0].mp[key_d]: 4\n"
+      "deleted: item[0].mp[key_c]: 3\n",
+      diff);
+
+  google::protobuf::Any any1, any2;
+  any1.PackFrom(msg1);
+  any2.PackFrom(msg2);
+  std::string diff_with_any;
+  differencer.ReportDifferencesToString(&diff_with_any);
+  EXPECT_FALSE(differencer.Compare(any1, any2));
+  EXPECT_EQ(
+      "modified: item[0].mp[key_b]: 2 -> 3\n"
+      "added: item[0].mp[key_d]: 4\n"
+      "deleted: item[0].mp[key_c]: 3\n",
+      diff_with_any);
+}
+
 static const char* const kIgnoredFields[] = {"rm.b", "rm.m.b"};
 
 class TestIgnorer : public util::MessageDifferencer::IgnoreCriteria {
@@ -3232,7 +3269,7 @@
   map2["key2"] = "2";
   map2["key1"] = "1";
 
-  EXPECT_EQ("modified: map_string_string.value: \"3\" -> \"0\"\n",
+  EXPECT_EQ("modified: map_string_string[key3]: \"3\" -> \"0\"\n",
             Run(map_proto1_, map_proto2_));
 }
 
@@ -3285,7 +3322,7 @@
   ASSERT_TRUE(parser.ParseFromString(
       "map_int32_foreign_message { key: 1 value { c: 2 }}", &map2));
   EXPECT_FALSE(differencer.Compare(map1, map2));
-  EXPECT_EQ("modified: map_int32_foreign_message.value.c: 1 -> 2\n", output);
+  EXPECT_EQ("modified: map_int32_foreign_message[1].c: 1 -> 2\n", output);
 
   ASSERT_TRUE(
       parser.ParseFromString("map_int32_foreign_message { key: 1 }", &map1));
@@ -3358,13 +3395,14 @@
   // equal.  However, in value comparison, all fields of the message are taken
   // into consideration, so they are reported as different.
   EXPECT_FALSE(differencer.Compare(msg1, msg2));
-  EXPECT_EQ("modified: map_string_foreign_message.key: \"key1\" -> \"key2\"\n",
-            output);
+  EXPECT_EQ(
+      "modified: map_string_foreign_message[key1].key: \"key1\" -> \"key2\"\n",
+      output);
   differencer.IgnoreField(
       GetFieldDescriptor(msg1, "map_string_foreign_message.key"));
   output.clear();
   EXPECT_TRUE(differencer.Compare(msg1, msg2));
-  EXPECT_EQ("ignored: map_string_foreign_message.key\n", output);
+  EXPECT_EQ("ignored: map_string_foreign_message[key1].key\n", output);
 }
 
 class MatchingTest : public testing::Test {
diff --git a/src/google/protobuf/util/message_differencer_unittest.proto b/src/google/protobuf/util/message_differencer_unittest.proto
index cbc36fa..0ad6792 100644
--- a/src/google/protobuf/util/message_differencer_unittest.proto
+++ b/src/google/protobuf/util/message_differencer_unittest.proto
@@ -33,6 +33,7 @@
 //  Sanjay Ghemawat, Jeff Dean, and others.
 //
 // This file contains messages for testing repeated field comparison
+// LINT: ALLOW_GROUPS
 
 syntax = "proto2";
 
@@ -63,6 +64,7 @@
     optional TestField m = 6;   // Test TreatAsMap when key is a message
     repeated TestField rm = 7;  // Test TreatAsMap when key is a repeated
                                 // message
+    map<string, int32> mp = 8;  // Test for map comparisons
   }
 
   optional int32 v = 13 [deprecated = true];
@@ -73,6 +75,5 @@
   repeated TestField rm = 12 [deprecated = true];  // Test for combinations
   repeated google.protobuf.Any rany =
       16;  // Test for repeated Any type resolution
-
   extensions 100 to 199;
 }
diff --git a/src/google/protobuf/util/time_util.cc b/src/google/protobuf/util/time_util.cc
index 4b80e7c..08c6e9c 100644
--- a/src/google/protobuf/util/time_util.cc
+++ b/src/google/protobuf/util/time_util.cc
@@ -209,7 +209,7 @@
   // Parse the duration value as two integers rather than a float value
   // to avoid precision loss.
   std::string seconds_part, nanos_part;
-  size_t pos = value.find_last_of(".");
+  size_t pos = value.find_last_of('.');
   if (pos == std::string::npos) {
     seconds_part = value.substr(sign_length, value.length() - 1 - sign_length);
     nanos_part = "0";
diff --git a/src/google/protobuf/util/type_resolver_util.cc b/src/google/protobuf/util/type_resolver_util.cc
index e906d58..cf2f318 100644
--- a/src/google/protobuf/util/type_resolver_util.cc
+++ b/src/google/protobuf/util/type_resolver_util.cc
@@ -38,6 +38,7 @@
 #include <google/protobuf/util/type_resolver.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/status.h>
 
 // clang-format off
 #include <google/protobuf/port_def.inc>
@@ -73,37 +74,38 @@
                              const DescriptorPool* pool)
       : url_prefix_(url_prefix), pool_(pool) {}
 
-  Status ResolveMessageType(const std::string& type_url, Type* type) override {
+  util::Status ResolveMessageType(const std::string& type_url,
+                                  Type* type) override {
     std::string type_name;
-    Status status = ParseTypeUrl(type_url, &type_name);
+    util::Status status = ParseTypeUrl(type_url, &type_name);
     if (!status.ok()) {
       return status;
     }
 
     const Descriptor* descriptor = pool_->FindMessageTypeByName(type_name);
     if (descriptor == NULL) {
-      return Status(util::error::NOT_FOUND,
-                    "Invalid type URL, unknown type: " + type_name);
+      return util::Status(util::error::NOT_FOUND,
+                          "Invalid type URL, unknown type: " + type_name);
     }
     ConvertDescriptor(descriptor, type);
-    return Status();
+    return util::Status();
   }
 
-  Status ResolveEnumType(const std::string& type_url,
-                         Enum* enum_type) override {
+  util::Status ResolveEnumType(const std::string& type_url,
+                               Enum* enum_type) override {
     std::string type_name;
-    Status status = ParseTypeUrl(type_url, &type_name);
+    util::Status status = ParseTypeUrl(type_url, &type_name);
     if (!status.ok()) {
       return status;
     }
 
     const EnumDescriptor* descriptor = pool_->FindEnumTypeByName(type_name);
     if (descriptor == NULL) {
-      return Status(util::error::NOT_FOUND,
-                    "Invalid type URL, unknown type: " + type_name);
+      return util::Status(util::error::NOT_FOUND,
+                          "Invalid type URL, unknown type: " + type_name);
     }
     ConvertEnumDescriptor(descriptor, enum_type);
-    return Status();
+    return util::Status();
   }
 
  private:
@@ -305,15 +307,16 @@
     return url_prefix_ + "/" + descriptor->full_name();
   }
 
-  Status ParseTypeUrl(const std::string& type_url, std::string* type_name) {
+  util::Status ParseTypeUrl(const std::string& type_url,
+                            std::string* type_name) {
     if (type_url.substr(0, url_prefix_.size() + 1) != url_prefix_ + "/") {
-      return Status(
+      return util::Status(
           util::error::INVALID_ARGUMENT,
           StrCat("Invalid type URL, type URLs must be of the form '",
                        url_prefix_, "/<typename>', got: ", type_url));
     }
     *type_name = type_url.substr(url_prefix_.size() + 1);
-    return Status();
+    return util::Status();
   }
 
   std::string DefaultValueAsString(const FieldDescriptor* descriptor) {
diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc
index a3f0fd5..c30b7ab 100644
--- a/src/google/protobuf/wire_format.cc
+++ b/src/google/protobuf/wire_format.cc
@@ -64,8 +64,6 @@
 namespace internal {
 
 // Forward declare static functions
-static size_t MapKeyDataOnlyByteSize(const FieldDescriptor* field,
-                                     const MapKey& value);
 static size_t MapValueRefDataOnlyByteSize(const FieldDescriptor* field,
                                           const MapValueConstRef& value);
 
@@ -1061,9 +1059,9 @@
   }
 }
 
-static uint8* SerializeMapKeyWithCachedSizes(const FieldDescriptor* field,
-                                             const MapKey& value, uint8* target,
-                                             io::EpsCopyOutputStream* stream) {
+uint8* SerializeMapKeyWithCachedSizes(const FieldDescriptor* field,
+                                      const MapKey& value, uint8* target,
+                                      io::EpsCopyOutputStream* stream) {
   target = stream->EnsureSpace(target);
   switch (field->type()) {
     case FieldDescriptor::TYPE_DOUBLE:
@@ -1524,8 +1522,8 @@
   return our_size;
 }
 
-static size_t MapKeyDataOnlyByteSize(const FieldDescriptor* field,
-                                     const MapKey& value) {
+size_t MapKeyDataOnlyByteSize(const FieldDescriptor* field,
+                              const MapKey& value) {
   GOOGLE_DCHECK_EQ(FieldDescriptor::TypeToCppType(field->type()), value.type());
   switch (field->type()) {
     case FieldDescriptor::TYPE_DOUBLE:
diff --git a/src/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h
index d42cefb..d4ffbdf 100644
--- a/src/google/protobuf/wire_format.h
+++ b/src/google/protobuf/wire_format.h
@@ -59,6 +59,7 @@
 
 namespace google {
 namespace protobuf {
+class MapKey;           // map_field.h
 class UnknownFieldSet;  // unknown_field_set.h
 }  // namespace protobuf
 }  // namespace google
@@ -398,6 +399,12 @@
 size_t ComputeUnknownFieldsSize(const InternalMetadata& metadata, size_t size,
                                 CachedSize* cached_size);
 
+size_t MapKeyDataOnlyByteSize(const FieldDescriptor* field,
+                              const MapKey& value);
+
+uint8* SerializeMapKeyWithCachedSizes(const FieldDescriptor* field,
+                                      const MapKey& value, uint8* target,
+                                      io::EpsCopyOutputStream* stream);
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc
index d07f903..7af7bf4 100644
--- a/src/google/protobuf/wire_format_lite.cc
+++ b/src/google/protobuf/wire_format_lite.cc
@@ -547,7 +547,7 @@
   WriteSubMessageMaybeToArray(size, value, output);
 }
 
-PROTOBUF_ALWAYS_INLINE static bool ReadBytesToString(
+PROTOBUF_NDEBUG_INLINE static bool ReadBytesToString(
     io::CodedInputStream* input, std::string* value);
 inline static bool ReadBytesToString(io::CodedInputStream* input,
                                      std::string* value) {
diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h
index c742fe8..8ffae81 100644
--- a/src/google/protobuf/wire_format_lite.h
+++ b/src/google/protobuf/wire_format_lite.h
@@ -254,14 +254,14 @@
   // the represented type and the FieldType. These are specialized with the
   // appropriate definition for each declared type.
   template <typename CType, enum FieldType DeclaredType>
-  PROTOBUF_ALWAYS_INLINE static bool ReadPrimitive(io::CodedInputStream* input,
+  PROTOBUF_NDEBUG_INLINE static bool ReadPrimitive(io::CodedInputStream* input,
                                                    CType* value);
 
   // Reads repeated primitive values, with optimizations for repeats.
   // tag_size and tag should both be compile-time constants provided by the
   // protocol compiler.
   template <typename CType, enum FieldType DeclaredType>
-  PROTOBUF_ALWAYS_INLINE static bool ReadRepeatedPrimitive(
+  PROTOBUF_NDEBUG_INLINE static bool ReadRepeatedPrimitive(
       int tag_size, uint32 tag, io::CodedInputStream* input,
       RepeatedField<CType>* value);
 
@@ -278,14 +278,14 @@
   // This is only implemented for the types with fixed wire size, e.g.
   // float, double, and the (s)fixed* types.
   template <typename CType, enum FieldType DeclaredType>
-  PROTOBUF_ALWAYS_INLINE static const uint8* ReadPrimitiveFromArray(
+  PROTOBUF_NDEBUG_INLINE static const uint8* ReadPrimitiveFromArray(
       const uint8* buffer, CType* value);
 
   // Reads a primitive packed field.
   //
   // This is only implemented for packable types.
   template <typename CType, enum FieldType DeclaredType>
-  PROTOBUF_ALWAYS_INLINE static bool ReadPackedPrimitive(
+  PROTOBUF_NDEBUG_INLINE static bool ReadPackedPrimitive(
       io::CodedInputStream* input, RepeatedField<CType>* value);
 
   // Identical to ReadPackedPrimitive, except will not inline the
@@ -346,37 +346,37 @@
   // Write a tag.  The Write*() functions typically include the tag, so
   // normally there's no need to call this unless using the Write*NoTag()
   // variants.
-  PROTOBUF_ALWAYS_INLINE static void WriteTag(int field_number, WireType type,
+  PROTOBUF_NDEBUG_INLINE static void WriteTag(int field_number, WireType type,
                                               io::CodedOutputStream* output);
 
   // Write fields, without tags.
-  PROTOBUF_ALWAYS_INLINE static void WriteInt32NoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteInt32NoTag(
       int32 value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteInt64NoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteInt64NoTag(
       int64 value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteUInt32NoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteUInt32NoTag(
       uint32 value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteUInt64NoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteUInt64NoTag(
       uint64 value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteSInt32NoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteSInt32NoTag(
       int32 value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteSInt64NoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteSInt64NoTag(
       int64 value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteFixed32NoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteFixed32NoTag(
       uint32 value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteFixed64NoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteFixed64NoTag(
       uint64 value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteSFixed32NoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteSFixed32NoTag(
       int32 value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteSFixed64NoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteSFixed64NoTag(
       int64 value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteFloatNoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteFloatNoTag(
       float value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteDoubleNoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteDoubleNoTag(
       double value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteBoolNoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteBoolNoTag(
       bool value, io::CodedOutputStream* output);
-  PROTOBUF_ALWAYS_INLINE static void WriteEnumNoTag(
+  PROTOBUF_NDEBUG_INLINE static void WriteEnumNoTag(
       int value, io::CodedOutputStream* output);
 
   // Write array of primitive fields, without tags
@@ -460,160 +460,160 @@
                                            io::CodedOutputStream* output);
 
   // Like above, but use only *ToArray methods of CodedOutputStream.
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteTagToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteTagToArray(int field_number,
                                                        WireType type,
                                                        uint8* target);
 
   // Write fields, without tags.
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteInt32NoTagToArray(int32 value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteInt32NoTagToArray(int32 value,
                                                               uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteInt64NoTagToArray(int64 value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteInt64NoTagToArray(int64 value,
                                                               uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteUInt32NoTagToArray(uint32 value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteUInt32NoTagToArray(uint32 value,
                                                                uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteUInt64NoTagToArray(uint64 value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteUInt64NoTagToArray(uint64 value,
                                                                uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSInt32NoTagToArray(int32 value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSInt32NoTagToArray(int32 value,
                                                                uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSInt64NoTagToArray(int64 value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSInt64NoTagToArray(int64 value,
                                                                uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFixed32NoTagToArray(uint32 value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFixed32NoTagToArray(uint32 value,
                                                                 uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFixed64NoTagToArray(uint64 value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFixed64NoTagToArray(uint64 value,
                                                                 uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSFixed32NoTagToArray(int32 value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSFixed32NoTagToArray(int32 value,
                                                                  uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSFixed64NoTagToArray(int64 value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSFixed64NoTagToArray(int64 value,
                                                                  uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFloatNoTagToArray(float value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFloatNoTagToArray(float value,
                                                               uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteDoubleNoTagToArray(double value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteDoubleNoTagToArray(double value,
                                                                uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteBoolNoTagToArray(bool value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteBoolNoTagToArray(bool value,
                                                              uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteEnumNoTagToArray(int value,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteEnumNoTagToArray(int value,
                                                              uint8* target);
 
   // Write fields, without tags.  These require that value.size() > 0.
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE static uint8* WritePrimitiveNoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WritePrimitiveNoTagToArray(
       const RepeatedField<T>& value, uint8* (*Writer)(T, uint8*),
       uint8* target);
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFixedNoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFixedNoTagToArray(
       const RepeatedField<T>& value, uint8* (*Writer)(T, uint8*),
       uint8* target);
 
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteInt32NoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteInt32NoTagToArray(
       const RepeatedField<int32>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteInt64NoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteInt64NoTagToArray(
       const RepeatedField<int64>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteUInt32NoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteUInt32NoTagToArray(
       const RepeatedField<uint32>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteUInt64NoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteUInt64NoTagToArray(
       const RepeatedField<uint64>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSInt32NoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSInt32NoTagToArray(
       const RepeatedField<int32>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSInt64NoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSInt64NoTagToArray(
       const RepeatedField<int64>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFixed32NoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFixed32NoTagToArray(
       const RepeatedField<uint32>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFixed64NoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFixed64NoTagToArray(
       const RepeatedField<uint64>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSFixed32NoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSFixed32NoTagToArray(
       const RepeatedField<int32>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSFixed64NoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSFixed64NoTagToArray(
       const RepeatedField<int64>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFloatNoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFloatNoTagToArray(
       const RepeatedField<float>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteDoubleNoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteDoubleNoTagToArray(
       const RepeatedField<double>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteBoolNoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteBoolNoTagToArray(
       const RepeatedField<bool>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteEnumNoTagToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteEnumNoTagToArray(
       const RepeatedField<int>& value, uint8* output);
 
   // Write fields, including tags.
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteInt32ToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteInt32ToArray(int field_number,
                                                          int32 value,
                                                          uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteInt64ToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteInt64ToArray(int field_number,
                                                          int64 value,
                                                          uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteUInt32ToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteUInt32ToArray(int field_number,
                                                           uint32 value,
                                                           uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteUInt64ToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteUInt64ToArray(int field_number,
                                                           uint64 value,
                                                           uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSInt32ToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSInt32ToArray(int field_number,
                                                           int32 value,
                                                           uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSInt64ToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSInt64ToArray(int field_number,
                                                           int64 value,
                                                           uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFixed32ToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFixed32ToArray(int field_number,
                                                            uint32 value,
                                                            uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFixed64ToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFixed64ToArray(int field_number,
                                                            uint64 value,
                                                            uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSFixed32ToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSFixed32ToArray(int field_number,
                                                             int32 value,
                                                             uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSFixed64ToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSFixed64ToArray(int field_number,
                                                             int64 value,
                                                             uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFloatToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFloatToArray(int field_number,
                                                          float value,
                                                          uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteDoubleToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteDoubleToArray(int field_number,
                                                           double value,
                                                           uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteBoolToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteBoolToArray(int field_number,
                                                         bool value,
                                                         uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteEnumToArray(int field_number,
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteEnumToArray(int field_number,
                                                         int value,
                                                         uint8* target);
 
   template <typename T>
-  PROTOBUF_ALWAYS_INLINE static uint8* WritePrimitiveToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WritePrimitiveToArray(
       int field_number, const RepeatedField<T>& value,
       uint8* (*Writer)(int, T, uint8*), uint8* target);
 
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteInt32ToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteInt32ToArray(
       int field_number, const RepeatedField<int32>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteInt64ToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteInt64ToArray(
       int field_number, const RepeatedField<int64>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteUInt32ToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteUInt32ToArray(
       int field_number, const RepeatedField<uint32>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteUInt64ToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteUInt64ToArray(
       int field_number, const RepeatedField<uint64>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSInt32ToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSInt32ToArray(
       int field_number, const RepeatedField<int32>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSInt64ToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSInt64ToArray(
       int field_number, const RepeatedField<int64>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFixed32ToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFixed32ToArray(
       int field_number, const RepeatedField<uint32>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFixed64ToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFixed64ToArray(
       int field_number, const RepeatedField<uint64>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSFixed32ToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSFixed32ToArray(
       int field_number, const RepeatedField<int32>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteSFixed64ToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteSFixed64ToArray(
       int field_number, const RepeatedField<int64>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteFloatToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteFloatToArray(
       int field_number, const RepeatedField<float>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteDoubleToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteDoubleToArray(
       int field_number, const RepeatedField<double>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteBoolToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteBoolToArray(
       int field_number, const RepeatedField<bool>& value, uint8* output);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteEnumToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteEnumToArray(
       int field_number, const RepeatedField<int>& value, uint8* output);
 
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteStringToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteStringToArray(
       int field_number, const std::string& value, uint8* target);
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteBytesToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteBytesToArray(
       int field_number, const std::string& value, uint8* target);
 
   // Whether to serialize deterministically (e.g., map keys are
@@ -622,11 +622,11 @@
   // have a CodedOutputStream available, so they get an additional parameter
   // telling them whether to serialize deterministically.
   template <typename MessageType>
-  PROTOBUF_ALWAYS_INLINE static uint8* InternalWriteGroup(
+  PROTOBUF_NDEBUG_INLINE static uint8* InternalWriteGroup(
       int field_number, const MessageType& value, uint8* target,
       io::EpsCopyOutputStream* stream);
   template <typename MessageType>
-  PROTOBUF_ALWAYS_INLINE static uint8* InternalWriteMessage(
+  PROTOBUF_NDEBUG_INLINE static uint8* InternalWriteMessage(
       int field_number, const MessageType& value, uint8* target,
       io::EpsCopyOutputStream* stream);
 
@@ -634,15 +634,15 @@
   // pointer must point at an instance of MessageType, *not* a subclass (or
   // the subclass must not override SerializeWithCachedSizes()).
   template <typename MessageType>
-  PROTOBUF_ALWAYS_INLINE static uint8* InternalWriteGroupNoVirtualToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* InternalWriteGroupNoVirtualToArray(
       int field_number, const MessageType& value, uint8* target);
   template <typename MessageType>
-  PROTOBUF_ALWAYS_INLINE static uint8* InternalWriteMessageNoVirtualToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* InternalWriteMessageNoVirtualToArray(
       int field_number, const MessageType& value, uint8* target);
 
   // For backward-compatibility, the last four methods also have versions
   // that are non-deterministic always.
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteGroupToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteGroupToArray(
       int field_number, const MessageLite& value, uint8* target) {
     io::EpsCopyOutputStream stream(
         target,
@@ -652,7 +652,7 @@
         io::CodedOutputStream::IsDefaultSerializationDeterministic());
     return InternalWriteGroup(field_number, value, target, &stream);
   }
-  PROTOBUF_ALWAYS_INLINE static uint8* WriteMessageToArray(
+  PROTOBUF_NDEBUG_INLINE static uint8* WriteMessageToArray(
       int field_number, const MessageLite& value, uint8* target) {
     int size = value.GetCachedSize();
     io::EpsCopyOutputStream stream(
@@ -718,13 +718,13 @@
   // optimizations for primitive types that have fixed size on the wire, and
   // can be read using potentially faster paths.
   template <typename CType, enum FieldType DeclaredType>
-  PROTOBUF_ALWAYS_INLINE static bool ReadRepeatedFixedSizePrimitive(
+  PROTOBUF_NDEBUG_INLINE static bool ReadRepeatedFixedSizePrimitive(
       int tag_size, uint32 tag, io::CodedInputStream* input,
       RepeatedField<CType>* value);
 
   // Like ReadRepeatedFixedSizePrimitive but for packed primitive fields.
   template <typename CType, enum FieldType DeclaredType>
-  PROTOBUF_ALWAYS_INLINE static bool ReadPackedFixedSizePrimitive(
+  PROTOBUF_NDEBUG_INLINE static bool ReadPackedFixedSizePrimitive(
       io::CodedInputStream* input, RepeatedField<CType>* value);
 
   static const CppType kFieldTypeToCppTypeMap[];
diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc
index 8274cec..d1a9561 100644
--- a/src/google/protobuf/wrappers.pb.cc
+++ b/src/google/protobuf/wrappers.pb.cc
@@ -17,160 +17,115 @@
 
 PROTOBUF_PRAGMA_INIT_SEG
 PROTOBUF_NAMESPACE_OPEN
-class DoubleValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<DoubleValue> _instance;
-} _DoubleValue_default_instance_;
-class FloatValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<FloatValue> _instance;
-} _FloatValue_default_instance_;
-class Int64ValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Int64Value> _instance;
-} _Int64Value_default_instance_;
-class UInt64ValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<UInt64Value> _instance;
-} _UInt64Value_default_instance_;
-class Int32ValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Int32Value> _instance;
-} _Int32Value_default_instance_;
-class UInt32ValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<UInt32Value> _instance;
-} _UInt32Value_default_instance_;
-class BoolValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<BoolValue> _instance;
-} _BoolValue_default_instance_;
-class StringValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<StringValue> _instance;
-} _StringValue_default_instance_;
-class BytesValueDefaultTypeInternal {
- public:
-  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<BytesValue> _instance;
-} _BytesValue_default_instance_;
+constexpr DoubleValue::DoubleValue(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : value_(0){}
+struct DoubleValueDefaultTypeInternal {
+  constexpr DoubleValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~DoubleValueDefaultTypeInternal() {}
+  union {
+    DoubleValue _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY DoubleValueDefaultTypeInternal _DoubleValue_default_instance_;
+constexpr FloatValue::FloatValue(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : value_(0){}
+struct FloatValueDefaultTypeInternal {
+  constexpr FloatValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~FloatValueDefaultTypeInternal() {}
+  union {
+    FloatValue _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY FloatValueDefaultTypeInternal _FloatValue_default_instance_;
+constexpr Int64Value::Int64Value(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : value_(PROTOBUF_LONGLONG(0)){}
+struct Int64ValueDefaultTypeInternal {
+  constexpr Int64ValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~Int64ValueDefaultTypeInternal() {}
+  union {
+    Int64Value _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY Int64ValueDefaultTypeInternal _Int64Value_default_instance_;
+constexpr UInt64Value::UInt64Value(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : value_(PROTOBUF_ULONGLONG(0)){}
+struct UInt64ValueDefaultTypeInternal {
+  constexpr UInt64ValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~UInt64ValueDefaultTypeInternal() {}
+  union {
+    UInt64Value _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY UInt64ValueDefaultTypeInternal _UInt64Value_default_instance_;
+constexpr Int32Value::Int32Value(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : value_(0){}
+struct Int32ValueDefaultTypeInternal {
+  constexpr Int32ValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~Int32ValueDefaultTypeInternal() {}
+  union {
+    Int32Value _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY Int32ValueDefaultTypeInternal _Int32Value_default_instance_;
+constexpr UInt32Value::UInt32Value(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : value_(0u){}
+struct UInt32ValueDefaultTypeInternal {
+  constexpr UInt32ValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~UInt32ValueDefaultTypeInternal() {}
+  union {
+    UInt32Value _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY UInt32ValueDefaultTypeInternal _UInt32Value_default_instance_;
+constexpr BoolValue::BoolValue(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : value_(false){}
+struct BoolValueDefaultTypeInternal {
+  constexpr BoolValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~BoolValueDefaultTypeInternal() {}
+  union {
+    BoolValue _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY BoolValueDefaultTypeInternal _BoolValue_default_instance_;
+constexpr StringValue::StringValue(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string){}
+struct StringValueDefaultTypeInternal {
+  constexpr StringValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~StringValueDefaultTypeInternal() {}
+  union {
+    StringValue _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY StringValueDefaultTypeInternal _StringValue_default_instance_;
+constexpr BytesValue::BytesValue(
+  ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized)
+  : value_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string){}
+struct BytesValueDefaultTypeInternal {
+  constexpr BytesValueDefaultTypeInternal()
+    : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {}
+  ~BytesValueDefaultTypeInternal() {}
+  union {
+    BytesValue _instance;
+  };
+};
+PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_NO_DESTROY BytesValueDefaultTypeInternal _BytesValue_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
-static void InitDefaultsscc_info_BoolValue_google_2fprotobuf_2fwrappers_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_BoolValue_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::BoolValue();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_BoolValue_google_2fprotobuf_2fwrappers_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_BoolValue_google_2fprotobuf_2fwrappers_2eproto}, {}};
-
-static void InitDefaultsscc_info_BytesValue_google_2fprotobuf_2fwrappers_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_BytesValue_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::BytesValue();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_BytesValue_google_2fprotobuf_2fwrappers_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_BytesValue_google_2fprotobuf_2fwrappers_2eproto}, {}};
-
-static void InitDefaultsscc_info_DoubleValue_google_2fprotobuf_2fwrappers_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_DoubleValue_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::DoubleValue();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_DoubleValue_google_2fprotobuf_2fwrappers_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_DoubleValue_google_2fprotobuf_2fwrappers_2eproto}, {}};
-
-static void InitDefaultsscc_info_FloatValue_google_2fprotobuf_2fwrappers_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_FloatValue_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::FloatValue();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_FloatValue_google_2fprotobuf_2fwrappers_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_FloatValue_google_2fprotobuf_2fwrappers_2eproto}, {}};
-
-static void InitDefaultsscc_info_Int32Value_google_2fprotobuf_2fwrappers_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Int32Value_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Int32Value();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Int32Value_google_2fprotobuf_2fwrappers_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Int32Value_google_2fprotobuf_2fwrappers_2eproto}, {}};
-
-static void InitDefaultsscc_info_Int64Value_google_2fprotobuf_2fwrappers_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_Int64Value_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::Int64Value();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Int64Value_google_2fprotobuf_2fwrappers_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Int64Value_google_2fprotobuf_2fwrappers_2eproto}, {}};
-
-static void InitDefaultsscc_info_StringValue_google_2fprotobuf_2fwrappers_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_StringValue_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::StringValue();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_StringValue_google_2fprotobuf_2fwrappers_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_StringValue_google_2fprotobuf_2fwrappers_2eproto}, {}};
-
-static void InitDefaultsscc_info_UInt32Value_google_2fprotobuf_2fwrappers_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_UInt32Value_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::UInt32Value();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_UInt32Value_google_2fprotobuf_2fwrappers_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_UInt32Value_google_2fprotobuf_2fwrappers_2eproto}, {}};
-
-static void InitDefaultsscc_info_UInt64Value_google_2fprotobuf_2fwrappers_2eproto() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  {
-    void* ptr = &PROTOBUF_NAMESPACE_ID::_UInt64Value_default_instance_;
-    new (ptr) PROTOBUF_NAMESPACE_ID::UInt64Value();
-    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
-  }
-}
-
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_UInt64Value_google_2fprotobuf_2fwrappers_2eproto =
-    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_UInt64Value_google_2fprotobuf_2fwrappers_2eproto}, {}};
-
 static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[9];
 static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fwrappers_2eproto = nullptr;
 static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fwrappers_2eproto = nullptr;
@@ -269,26 +224,18 @@
   "erspb\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKno"
   "wnTypesb\006proto3"
   ;
-static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fwrappers_2eproto_deps[1] = {
-};
-static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_google_2fprotobuf_2fwrappers_2eproto_sccs[9] = {
-  &scc_info_BoolValue_google_2fprotobuf_2fwrappers_2eproto.base,
-  &scc_info_BytesValue_google_2fprotobuf_2fwrappers_2eproto.base,
-  &scc_info_DoubleValue_google_2fprotobuf_2fwrappers_2eproto.base,
-  &scc_info_FloatValue_google_2fprotobuf_2fwrappers_2eproto.base,
-  &scc_info_Int32Value_google_2fprotobuf_2fwrappers_2eproto.base,
-  &scc_info_Int64Value_google_2fprotobuf_2fwrappers_2eproto.base,
-  &scc_info_StringValue_google_2fprotobuf_2fwrappers_2eproto.base,
-  &scc_info_UInt32Value_google_2fprotobuf_2fwrappers_2eproto.base,
-  &scc_info_UInt64Value_google_2fprotobuf_2fwrappers_2eproto.base,
-};
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fwrappers_2eproto = {
-  false, false, descriptor_table_protodef_google_2fprotobuf_2fwrappers_2eproto, "google/protobuf/wrappers.proto", 455,
-  &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once, descriptor_table_google_2fprotobuf_2fwrappers_2eproto_sccs, descriptor_table_google_2fprotobuf_2fwrappers_2eproto_deps, 9, 0,
+  false, false, 455, descriptor_table_protodef_google_2fprotobuf_2fwrappers_2eproto, "google/protobuf/wrappers.proto", 
+  &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once, nullptr, 0, 9,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fwrappers_2eproto::offsets,
-  file_level_metadata_google_2fprotobuf_2fwrappers_2eproto, 9, file_level_enum_descriptors_google_2fprotobuf_2fwrappers_2eproto, file_level_service_descriptors_google_2fprotobuf_2fwrappers_2eproto,
+  file_level_metadata_google_2fprotobuf_2fwrappers_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fwrappers_2eproto, file_level_service_descriptors_google_2fprotobuf_2fwrappers_2eproto,
 };
+PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
+descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(int index) {
+  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
+  return descriptor_table_google_2fprotobuf_2fwrappers_2eproto.file_level_metadata[index];
+}
 
 // Force running AddDescriptors() at dynamic initialization time.
 PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fwrappers_2eproto(&descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
@@ -314,7 +261,7 @@
 }
 
 void DoubleValue::SharedCtor() {
-  value_ = 0;
+value_ = 0;
 }
 
 DoubleValue::~DoubleValue() {
@@ -336,11 +283,6 @@
 void DoubleValue::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const DoubleValue& DoubleValue::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_DoubleValue_google_2fprotobuf_2fwrappers_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void DoubleValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.DoubleValue)
@@ -506,7 +448,7 @@
 }
 
 void FloatValue::SharedCtor() {
-  value_ = 0;
+value_ = 0;
 }
 
 FloatValue::~FloatValue() {
@@ -528,11 +470,6 @@
 void FloatValue::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const FloatValue& FloatValue::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_FloatValue_google_2fprotobuf_2fwrappers_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void FloatValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FloatValue)
@@ -698,7 +635,7 @@
 }
 
 void Int64Value::SharedCtor() {
-  value_ = PROTOBUF_LONGLONG(0);
+value_ = PROTOBUF_LONGLONG(0);
 }
 
 Int64Value::~Int64Value() {
@@ -720,11 +657,6 @@
 void Int64Value::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Int64Value& Int64Value::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Int64Value_google_2fprotobuf_2fwrappers_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Int64Value::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Int64Value)
@@ -892,7 +824,7 @@
 }
 
 void UInt64Value::SharedCtor() {
-  value_ = PROTOBUF_ULONGLONG(0);
+value_ = PROTOBUF_ULONGLONG(0);
 }
 
 UInt64Value::~UInt64Value() {
@@ -914,11 +846,6 @@
 void UInt64Value::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const UInt64Value& UInt64Value::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_UInt64Value_google_2fprotobuf_2fwrappers_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void UInt64Value::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.UInt64Value)
@@ -1086,7 +1013,7 @@
 }
 
 void Int32Value::SharedCtor() {
-  value_ = 0;
+value_ = 0;
 }
 
 Int32Value::~Int32Value() {
@@ -1108,11 +1035,6 @@
 void Int32Value::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const Int32Value& Int32Value::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Int32Value_google_2fprotobuf_2fwrappers_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void Int32Value::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Int32Value)
@@ -1280,7 +1202,7 @@
 }
 
 void UInt32Value::SharedCtor() {
-  value_ = 0u;
+value_ = 0u;
 }
 
 UInt32Value::~UInt32Value() {
@@ -1302,11 +1224,6 @@
 void UInt32Value::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const UInt32Value& UInt32Value::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_UInt32Value_google_2fprotobuf_2fwrappers_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void UInt32Value::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.UInt32Value)
@@ -1474,7 +1391,7 @@
 }
 
 void BoolValue::SharedCtor() {
-  value_ = false;
+value_ = false;
 }
 
 BoolValue::~BoolValue() {
@@ -1496,11 +1413,6 @@
 void BoolValue::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const BoolValue& BoolValue::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_BoolValue_google_2fprotobuf_2fwrappers_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void BoolValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.BoolValue)
@@ -1670,8 +1582,7 @@
 }
 
 void StringValue::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_StringValue_google_2fprotobuf_2fwrappers_2eproto.base);
-  value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
 StringValue::~StringValue() {
@@ -1694,11 +1605,6 @@
 void StringValue::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const StringValue& StringValue::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_StringValue_google_2fprotobuf_2fwrappers_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void StringValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.StringValue)
@@ -1876,8 +1782,7 @@
 }
 
 void BytesValue::SharedCtor() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_BytesValue_google_2fprotobuf_2fwrappers_2eproto.base);
-  value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
 }
 
 BytesValue::~BytesValue() {
@@ -1900,11 +1805,6 @@
 void BytesValue::SetCachedSize(int size) const {
   _cached_size_.Set(size);
 }
-const BytesValue& BytesValue::default_instance() {
-  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_BytesValue_google_2fprotobuf_2fwrappers_2eproto.base);
-  return *internal_default_instance();
-}
-
 
 void BytesValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.BytesValue)
diff --git a/src/google/protobuf/wrappers.pb.h b/src/google/protobuf/wrappers.pb.h
index 0edfe87..2efd560 100644
--- a/src/google/protobuf/wrappers.pb.h
+++ b/src/google/protobuf/wrappers.pb.h
@@ -53,33 +53,34 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fwrappers_2eproto;
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class BoolValue;
-class BoolValueDefaultTypeInternal;
+struct BoolValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern BoolValueDefaultTypeInternal _BoolValue_default_instance_;
 class BytesValue;
-class BytesValueDefaultTypeInternal;
+struct BytesValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern BytesValueDefaultTypeInternal _BytesValue_default_instance_;
 class DoubleValue;
-class DoubleValueDefaultTypeInternal;
+struct DoubleValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern DoubleValueDefaultTypeInternal _DoubleValue_default_instance_;
 class FloatValue;
-class FloatValueDefaultTypeInternal;
+struct FloatValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern FloatValueDefaultTypeInternal _FloatValue_default_instance_;
 class Int32Value;
-class Int32ValueDefaultTypeInternal;
+struct Int32ValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern Int32ValueDefaultTypeInternal _Int32Value_default_instance_;
 class Int64Value;
-class Int64ValueDefaultTypeInternal;
+struct Int64ValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern Int64ValueDefaultTypeInternal _Int64Value_default_instance_;
 class StringValue;
-class StringValueDefaultTypeInternal;
+struct StringValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern StringValueDefaultTypeInternal _StringValue_default_instance_;
 class UInt32Value;
-class UInt32ValueDefaultTypeInternal;
+struct UInt32ValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern UInt32ValueDefaultTypeInternal _UInt32Value_default_instance_;
 class UInt64Value;
-class UInt64ValueDefaultTypeInternal;
+struct UInt64ValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern UInt64ValueDefaultTypeInternal _UInt64Value_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
@@ -102,6 +103,7 @@
  public:
   inline DoubleValue() : DoubleValue(nullptr) {}
   virtual ~DoubleValue();
+  explicit constexpr DoubleValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   DoubleValue(const DoubleValue& from);
   DoubleValue(DoubleValue&& from) noexcept
@@ -131,8 +133,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const DoubleValue& default_instance();
-
+  static const DoubleValue& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const DoubleValue* internal_default_instance() {
     return reinterpret_cast<const DoubleValue*>(
                &_DoubleValue_default_instance_);
@@ -198,8 +201,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -238,6 +240,7 @@
  public:
   inline FloatValue() : FloatValue(nullptr) {}
   virtual ~FloatValue();
+  explicit constexpr FloatValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FloatValue(const FloatValue& from);
   FloatValue(FloatValue&& from) noexcept
@@ -267,8 +270,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const FloatValue& default_instance();
-
+  static const FloatValue& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const FloatValue* internal_default_instance() {
     return reinterpret_cast<const FloatValue*>(
                &_FloatValue_default_instance_);
@@ -334,8 +338,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -374,6 +377,7 @@
  public:
   inline Int64Value() : Int64Value(nullptr) {}
   virtual ~Int64Value();
+  explicit constexpr Int64Value(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Int64Value(const Int64Value& from);
   Int64Value(Int64Value&& from) noexcept
@@ -403,8 +407,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Int64Value& default_instance();
-
+  static const Int64Value& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Int64Value* internal_default_instance() {
     return reinterpret_cast<const Int64Value*>(
                &_Int64Value_default_instance_);
@@ -470,8 +475,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -510,6 +514,7 @@
  public:
   inline UInt64Value() : UInt64Value(nullptr) {}
   virtual ~UInt64Value();
+  explicit constexpr UInt64Value(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   UInt64Value(const UInt64Value& from);
   UInt64Value(UInt64Value&& from) noexcept
@@ -539,8 +544,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const UInt64Value& default_instance();
-
+  static const UInt64Value& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const UInt64Value* internal_default_instance() {
     return reinterpret_cast<const UInt64Value*>(
                &_UInt64Value_default_instance_);
@@ -606,8 +612,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -646,6 +651,7 @@
  public:
   inline Int32Value() : Int32Value(nullptr) {}
   virtual ~Int32Value();
+  explicit constexpr Int32Value(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Int32Value(const Int32Value& from);
   Int32Value(Int32Value&& from) noexcept
@@ -675,8 +681,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const Int32Value& default_instance();
-
+  static const Int32Value& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const Int32Value* internal_default_instance() {
     return reinterpret_cast<const Int32Value*>(
                &_Int32Value_default_instance_);
@@ -742,8 +749,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -782,6 +788,7 @@
  public:
   inline UInt32Value() : UInt32Value(nullptr) {}
   virtual ~UInt32Value();
+  explicit constexpr UInt32Value(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   UInt32Value(const UInt32Value& from);
   UInt32Value(UInt32Value&& from) noexcept
@@ -811,8 +818,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const UInt32Value& default_instance();
-
+  static const UInt32Value& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const UInt32Value* internal_default_instance() {
     return reinterpret_cast<const UInt32Value*>(
                &_UInt32Value_default_instance_);
@@ -878,8 +886,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -918,6 +925,7 @@
  public:
   inline BoolValue() : BoolValue(nullptr) {}
   virtual ~BoolValue();
+  explicit constexpr BoolValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   BoolValue(const BoolValue& from);
   BoolValue(BoolValue&& from) noexcept
@@ -947,8 +955,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const BoolValue& default_instance();
-
+  static const BoolValue& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const BoolValue* internal_default_instance() {
     return reinterpret_cast<const BoolValue*>(
                &_BoolValue_default_instance_);
@@ -1014,8 +1023,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -1054,6 +1062,7 @@
  public:
   inline StringValue() : StringValue(nullptr) {}
   virtual ~StringValue();
+  explicit constexpr StringValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   StringValue(const StringValue& from);
   StringValue(StringValue&& from) noexcept
@@ -1083,8 +1092,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const StringValue& default_instance();
-
+  static const StringValue& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const StringValue* internal_default_instance() {
     return reinterpret_cast<const StringValue*>(
                &_StringValue_default_instance_);
@@ -1150,8 +1160,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
@@ -1197,6 +1206,7 @@
  public:
   inline BytesValue() : BytesValue(nullptr) {}
   virtual ~BytesValue();
+  explicit constexpr BytesValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   BytesValue(const BytesValue& from);
   BytesValue(BytesValue&& from) noexcept
@@ -1226,8 +1236,9 @@
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
     return GetMetadataStatic().reflection;
   }
-  static const BytesValue& default_instance();
-
+  static const BytesValue& default_instance() {
+    return *internal_default_instance();
+  }
   static inline const BytesValue* internal_default_instance() {
     return reinterpret_cast<const BytesValue*>(
                &_BytesValue_default_instance_);
@@ -1293,8 +1304,7 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   private:
   static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto.file_level_metadata[kIndexInFileMessages];
+    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(kIndexInFileMessages);
   }
 
   public:
diff --git a/tests.sh b/tests.sh
index f1242a5..e445384 100755
--- a/tests.sh
+++ b/tests.sh
@@ -441,6 +441,10 @@
   internal_build_cpp  # For conformance tests.
   cd ruby && bash travis-test.sh ruby-2.7.0 && cd ..
 }
+build_ruby30() {
+  internal_build_cpp  # For conformance tests.
+  cd ruby && bash travis-test.sh ruby-3.0.0 && cd ..
+}
 
 build_jruby() {
   internal_build_cpp  # For conformance tests.
@@ -723,6 +727,7 @@
             ruby25 |
             ruby26 |
             ruby27 |
+            ruby30 |
             jruby |
             ruby_all |
             php7.0   |
diff --git a/third_party/wyhash/wyhash.h b/third_party/wyhash/wyhash.h
index 5658f02..bb247a9 100644
--- a/third_party/wyhash/wyhash.h
+++ b/third_party/wyhash/wyhash.h
@@ -116,7 +116,7 @@
   return _wyfinish(p,len,seed,secret,i);
 }
 //utility functions
-const uint64_t _wyp[5] = {0xa0761d6478bd642full, 0xe7037ed1a0b428dbull, 0x8ebc6af09c88c6e3ull, 0x589965cc75374cc3ull, 0x1d8e4e27c47d124full};
+static const uint64_t _wyp[5] = {0xa0761d6478bd642full, 0xe7037ed1a0b428dbull, 0x8ebc6af09c88c6e3ull, 0x589965cc75374cc3ull, 0x1d8e4e27c47d124full};
 static inline uint64_t wyhash64(uint64_t A, uint64_t B){  A^=_wyp[0]; B^=_wyp[1];  _wymum(&A,&B);  return _wymix(A^_wyp[0],B^_wyp[1]);}
 static inline uint64_t wyrand(uint64_t *seed){  *seed+=_wyp[0]; return _wymix(*seed,*seed^_wyp[1]);}
 static inline double wy2u01(uint64_t r){ const double _wynorm=1.0/(1ull<<52); return (r>>12)*_wynorm;}