From dfab275eca9481b5de31122db6fc91b31db3382a Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Thu, 18 Jun 2020 15:47:49 -0700 Subject: [PATCH 1/8] Sync from Piper @317197168 PROTOBUF_SYNC_PIPER --- CHANGES.txt | 13 +- conformance/binary_json_conformance_suite.cc | 23 ++ .../TestMessagesProto3.cs | 253 +++++++++++------- csharp/src/Google.Protobuf.Test/testprotos.pb | Bin 337637 -> 337912 bytes .../Google.Protobuf/Reflection/Descriptor.cs | 7 +- .../src/Google.Protobuf/WellKnownTypes/Any.cs | 8 +- .../src/Google.Protobuf/WellKnownTypes/Api.cs | 8 +- .../WellKnownTypes/Duration.cs | 8 +- .../Google.Protobuf/WellKnownTypes/Empty.cs | 8 +- .../WellKnownTypes/FieldMask.cs | 9 +- .../WellKnownTypes/SourceContext.cs | 8 +- .../Google.Protobuf/WellKnownTypes/Struct.cs | 8 +- .../WellKnownTypes/Timestamp.cs | 8 +- .../Google.Protobuf/WellKnownTypes/Type.cs | 8 +- .../WellKnownTypes/Wrappers.cs | 9 +- .../protobuf/internal/json_format_test.py | 14 + python/google/protobuf/json_format.py | 5 + src/google/protobuf/any.cc | 2 +- src/google/protobuf/any.h | 6 +- src/google/protobuf/any.pb.cc | 10 +- src/google/protobuf/any.proto | 2 +- src/google/protobuf/any_lite.cc | 8 +- src/google/protobuf/api.pb.cc | 10 +- src/google/protobuf/api.proto | 4 +- .../protobuf/compiler/cpp/cpp_message.cc | 20 +- src/google/protobuf/compiler/plugin.pb.cc | 9 +- src/google/protobuf/compiler/plugin.proto | 2 +- src/google/protobuf/descriptor.pb.cc | 11 +- src/google/protobuf/descriptor.proto | 2 +- src/google/protobuf/duration.pb.cc | 10 +- src/google/protobuf/duration.proto | 2 +- src/google/protobuf/empty.pb.cc | 10 +- src/google/protobuf/empty.proto | 2 +- src/google/protobuf/field_mask.pb.cc | 10 +- src/google/protobuf/field_mask.proto | 2 +- src/google/protobuf/source_context.pb.cc | 11 +- src/google/protobuf/source_context.proto | 2 +- src/google/protobuf/struct.pb.cc | 11 +- src/google/protobuf/struct.proto | 2 +- .../protobuf/test_messages_proto3.proto | 2 + src/google/protobuf/timestamp.pb.cc | 10 +- src/google/protobuf/timestamp.proto | 2 +- src/google/protobuf/type.pb.cc | 10 +- src/google/protobuf/type.proto | 4 +- .../protobuf/util/json_format_proto3.proto | 1 + src/google/protobuf/wrappers.pb.cc | 12 +- src/google/protobuf/wrappers.proto | 2 +- 47 files changed, 348 insertions(+), 240 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 0f540f7752..6d77428d7d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -11,16 +11,25 @@ Unreleased Changes * Added more Windows macros to proto whitelist. * Arena constructors for map entry messages are now marked "explicit" (for regular messages they were already explicit). + * Fix subtle aliasing bug in RepeatedField::Add + * Fix mismatch between MapEntry ByteSize and Serialize with respect to unset + fields. Python: - * Reject lowercase t for Timestamp json format. Fixes a conformance test. + * JSON format conformance fixes: + * Reject lowercase t for Timestamp json format. + * Print full_name directly for extensions (no camelCase). + * Reject boolean values for integer fields. + * Reject NaN, Infinity, -Infinity that is not quoted. + * Base64 fixes for bytes fields: accept URL-safe base64 and missing padding. + * Bugfix for fields/files named "async" or "await". * Improved the error message when AttributeError is returned from __getattr__ in EnumTypeWrapper. - * Json format will print full_name directly for extensions. Java: * Fixed a bug where setting optional proto3 enums with setFooValue() would not mark the value as present. + * Add Subtract function to FieldMaskUtil. C#: * Dropped support for netstandard1.0 (replaced by support for netstandard1.1). diff --git a/conformance/binary_json_conformance_suite.cc b/conformance/binary_json_conformance_suite.cc index f62c705f62..4a0d8e8480 100644 --- a/conformance/binary_json_conformance_suite.cc +++ b/conformance/binary_json_conformance_suite.cc @@ -3051,6 +3051,29 @@ void BinaryAndJsonConformanceSuite::RunJsonTestsForValue() { } ] )"); + RunValidJsonTestWithValidator( + "NullValueInOtherOneofOldFormat", RECOMMENDED, + R"({"oneofNullValue": "NULL_VALUE"})", + [](const Json::Value& value) { + return (value.isMember("oneofNullValue") && + value["oneofNullValue"].isNull()); + }, + true); + RunValidJsonTestWithValidator( + "NullValueInOtherOneofNewFormat", RECOMMENDED, + R"({"oneofNullValue": null})", + [](const Json::Value& value) { + return (value.isMember("oneofNullValue") && + value["oneofNullValue"].isNull()); + }, + true); + RunValidJsonTestWithValidator( + "NullValueInNormalMessage", RECOMMENDED, + R"({"optionalNullValue": null})", + [](const Json::Value& value) { + return value.empty(); + }, + true); } void BinaryAndJsonConformanceSuite::RunJsonTestsForAny() { diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs index 41bc006cb1..ebdab60e4a 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs @@ -29,7 +29,7 @@ namespace ProtobufTestMessages.Proto3 { "dWYvYW55LnByb3RvGh5nb29nbGUvcHJvdG9idWYvZHVyYXRpb24ucHJvdG8a", "IGdvb2dsZS9wcm90b2J1Zi9maWVsZF9tYXNrLnByb3RvGhxnb29nbGUvcHJv", "dG9idWYvc3RydWN0LnByb3RvGh9nb29nbGUvcHJvdG9idWYvdGltZXN0YW1w", - "LnByb3RvGh5nb29nbGUvcHJvdG9idWYvd3JhcHBlcnMucHJvdG8iv0QKElRl", + "LnByb3RvGh5nb29nbGUvcHJvdG9idWYvd3JhcHBlcnMucHJvdG8isUUKElRl", "c3RBbGxUeXBlc1Byb3RvMxIWCg5vcHRpb25hbF9pbnQzMhgBIAEoBRIWCg5v", "cHRpb25hbF9pbnQ2NBgCIAEoAxIXCg9vcHRpb25hbF91aW50MzIYAyABKA0S", "FwoPb3B0aW9uYWxfdWludDY0GAQgASgEEhcKD29wdGlvbmFsX3NpbnQzMhgF", @@ -140,99 +140,101 @@ namespace ProtobufTestMessages.Proto3 { "IAEoBEgAEhUKC29uZW9mX2Zsb2F0GHUgASgCSAASFgoMb25lb2ZfZG91Ymxl", "GHYgASgBSAASUgoKb25lb2ZfZW51bRh3IAEoDjI8LnByb3RvYnVmX3Rlc3Rf", "bWVzc2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlc1Byb3RvMy5OZXN0ZWRFbnVt", - "SAASOgoVb3B0aW9uYWxfYm9vbF93cmFwcGVyGMkBIAEoCzIaLmdvb2dsZS5w", - "cm90b2J1Zi5Cb29sVmFsdWUSPAoWb3B0aW9uYWxfaW50MzJfd3JhcHBlchjK", - "ASABKAsyGy5nb29nbGUucHJvdG9idWYuSW50MzJWYWx1ZRI8ChZvcHRpb25h", - "bF9pbnQ2NF93cmFwcGVyGMsBIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2", - "NFZhbHVlEj4KF29wdGlvbmFsX3VpbnQzMl93cmFwcGVyGMwBIAEoCzIcLmdv", - "b2dsZS5wcm90b2J1Zi5VSW50MzJWYWx1ZRI+ChdvcHRpb25hbF91aW50NjRf", - "d3JhcHBlchjNASABKAsyHC5nb29nbGUucHJvdG9idWYuVUludDY0VmFsdWUS", - "PAoWb3B0aW9uYWxfZmxvYXRfd3JhcHBlchjOASABKAsyGy5nb29nbGUucHJv", - "dG9idWYuRmxvYXRWYWx1ZRI+ChdvcHRpb25hbF9kb3VibGVfd3JhcHBlchjP", - "ASABKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSPgoXb3B0aW9u", - "YWxfc3RyaW5nX3dyYXBwZXIY0AEgASgLMhwuZ29vZ2xlLnByb3RvYnVmLlN0", - "cmluZ1ZhbHVlEjwKFm9wdGlvbmFsX2J5dGVzX3dyYXBwZXIY0QEgASgLMhsu", - "Z29vZ2xlLnByb3RvYnVmLkJ5dGVzVmFsdWUSOgoVcmVwZWF0ZWRfYm9vbF93", - "cmFwcGVyGNMBIAMoCzIaLmdvb2dsZS5wcm90b2J1Zi5Cb29sVmFsdWUSPAoW", - "cmVwZWF0ZWRfaW50MzJfd3JhcHBlchjUASADKAsyGy5nb29nbGUucHJvdG9i", - "dWYuSW50MzJWYWx1ZRI8ChZyZXBlYXRlZF9pbnQ2NF93cmFwcGVyGNUBIAMo", - "CzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVlEj4KF3JlcGVhdGVkX3Vp", - "bnQzMl93cmFwcGVyGNYBIAMoCzIcLmdvb2dsZS5wcm90b2J1Zi5VSW50MzJW", - "YWx1ZRI+ChdyZXBlYXRlZF91aW50NjRfd3JhcHBlchjXASADKAsyHC5nb29n", - "bGUucHJvdG9idWYuVUludDY0VmFsdWUSPAoWcmVwZWF0ZWRfZmxvYXRfd3Jh", - "cHBlchjYASADKAsyGy5nb29nbGUucHJvdG9idWYuRmxvYXRWYWx1ZRI+Chdy", - "ZXBlYXRlZF9kb3VibGVfd3JhcHBlchjZASADKAsyHC5nb29nbGUucHJvdG9i", - "dWYuRG91YmxlVmFsdWUSPgoXcmVwZWF0ZWRfc3RyaW5nX3dyYXBwZXIY2gEg", - "AygLMhwuZ29vZ2xlLnByb3RvYnVmLlN0cmluZ1ZhbHVlEjwKFnJlcGVhdGVk", - "X2J5dGVzX3dyYXBwZXIY2wEgAygLMhsuZ29vZ2xlLnByb3RvYnVmLkJ5dGVz", - "VmFsdWUSNQoRb3B0aW9uYWxfZHVyYXRpb24YrQIgASgLMhkuZ29vZ2xlLnBy", - "b3RvYnVmLkR1cmF0aW9uEjcKEm9wdGlvbmFsX3RpbWVzdGFtcBiuAiABKAsy", - "Gi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEjgKE29wdGlvbmFsX2ZpZWxk", - "X21hc2sYrwIgASgLMhouZ29vZ2xlLnByb3RvYnVmLkZpZWxkTWFzaxIxCg9v", - "cHRpb25hbF9zdHJ1Y3QYsAIgASgLMhcuZ29vZ2xlLnByb3RvYnVmLlN0cnVj", - "dBIrCgxvcHRpb25hbF9hbnkYsQIgASgLMhQuZ29vZ2xlLnByb3RvYnVmLkFu", - "eRIvCg5vcHRpb25hbF92YWx1ZRiyAiABKAsyFi5nb29nbGUucHJvdG9idWYu", - "VmFsdWUSNQoRcmVwZWF0ZWRfZHVyYXRpb24YtwIgAygLMhkuZ29vZ2xlLnBy", - "b3RvYnVmLkR1cmF0aW9uEjcKEnJlcGVhdGVkX3RpbWVzdGFtcBi4AiADKAsy", - "Gi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEjcKEnJlcGVhdGVkX2ZpZWxk", - "bWFzaxi5AiADKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRNYXNrEjEKD3Jl", - "cGVhdGVkX3N0cnVjdBjEAiADKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0", - "EisKDHJlcGVhdGVkX2FueRi7AiADKAsyFC5nb29nbGUucHJvdG9idWYuQW55", - "Ei8KDnJlcGVhdGVkX3ZhbHVlGLwCIAMoCzIWLmdvb2dsZS5wcm90b2J1Zi5W", - "YWx1ZRI4ChNyZXBlYXRlZF9saXN0X3ZhbHVlGL0CIAMoCzIaLmdvb2dsZS5w", - "cm90b2J1Zi5MaXN0VmFsdWUSEwoKZmllbGRuYW1lMRiRAyABKAUSFAoLZmll", - "bGRfbmFtZTIYkgMgASgFEhUKDF9maWVsZF9uYW1lMxiTAyABKAUSFgoNZmll", - "bGRfX25hbWU0XxiUAyABKAUSFAoLZmllbGQwbmFtZTUYlQMgASgFEhYKDWZp", - "ZWxkXzBfbmFtZTYYlgMgASgFEhMKCmZpZWxkTmFtZTcYlwMgASgFEhMKCkZp", - "ZWxkTmFtZTgYmAMgASgFEhQKC2ZpZWxkX05hbWU5GJkDIAEoBRIVCgxGaWVs", - "ZF9OYW1lMTAYmgMgASgFEhUKDEZJRUxEX05BTUUxMRibAyABKAUSFQoMRklF", - "TERfbmFtZTEyGJwDIAEoBRIXCg5fX2ZpZWxkX25hbWUxMxidAyABKAUSFwoO", - "X19GaWVsZF9uYW1lMTQYngMgASgFEhYKDWZpZWxkX19uYW1lMTUYnwMgASgF", - "EhYKDWZpZWxkX19OYW1lMTYYoAMgASgFEhcKDmZpZWxkX25hbWUxN19fGKED", - "IAEoBRIXCg5GaWVsZF9uYW1lMThfXxiiAyABKAUaYgoNTmVzdGVkTWVzc2Fn", - "ZRIJCgFhGAEgASgFEkYKC2NvcmVjdXJzaXZlGAIgASgLMjEucHJvdG9idWZf", - "dGVzdF9tZXNzYWdlcy5wcm90bzMuVGVzdEFsbFR5cGVzUHJvdG8zGjQKEk1h", - "cEludDMySW50MzJFbnRyeRILCgNrZXkYASABKAUSDQoFdmFsdWUYAiABKAU6", - "AjgBGjQKEk1hcEludDY0SW50NjRFbnRyeRILCgNrZXkYASABKAMSDQoFdmFs", - "dWUYAiABKAM6AjgBGjYKFE1hcFVpbnQzMlVpbnQzMkVudHJ5EgsKA2tleRgB", - "IAEoDRINCgV2YWx1ZRgCIAEoDToCOAEaNgoUTWFwVWludDY0VWludDY0RW50", - "cnkSCwoDa2V5GAEgASgEEg0KBXZhbHVlGAIgASgEOgI4ARo2ChRNYXBTaW50", - "MzJTaW50MzJFbnRyeRILCgNrZXkYASABKBESDQoFdmFsdWUYAiABKBE6AjgB", - "GjYKFE1hcFNpbnQ2NFNpbnQ2NEVudHJ5EgsKA2tleRgBIAEoEhINCgV2YWx1", - "ZRgCIAEoEjoCOAEaOAoWTWFwRml4ZWQzMkZpeGVkMzJFbnRyeRILCgNrZXkY", - "ASABKAcSDQoFdmFsdWUYAiABKAc6AjgBGjgKFk1hcEZpeGVkNjRGaXhlZDY0", - "RW50cnkSCwoDa2V5GAEgASgGEg0KBXZhbHVlGAIgASgGOgI4ARo6ChhNYXBT", - "Zml4ZWQzMlNmaXhlZDMyRW50cnkSCwoDa2V5GAEgASgPEg0KBXZhbHVlGAIg", - "ASgPOgI4ARo6ChhNYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnkSCwoDa2V5GAEg", - "ASgQEg0KBXZhbHVlGAIgASgQOgI4ARo0ChJNYXBJbnQzMkZsb2F0RW50cnkS", - "CwoDa2V5GAEgASgFEg0KBXZhbHVlGAIgASgCOgI4ARo1ChNNYXBJbnQzMkRv", - "dWJsZUVudHJ5EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEoAToCOAEaMgoQ", - "TWFwQm9vbEJvb2xFbnRyeRILCgNrZXkYASABKAgSDQoFdmFsdWUYAiABKAg6", - "AjgBGjYKFE1hcFN0cmluZ1N0cmluZ0VudHJ5EgsKA2tleRgBIAEoCRINCgV2", - "YWx1ZRgCIAEoCToCOAEaNQoTTWFwU3RyaW5nQnl0ZXNFbnRyeRILCgNrZXkY", - "ASABKAkSDQoFdmFsdWUYAiABKAw6AjgBGn4KG01hcFN0cmluZ05lc3RlZE1l", - "c3NhZ2VFbnRyeRILCgNrZXkYASABKAkSTgoFdmFsdWUYAiABKAsyPy5wcm90", - "b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXNQcm90bzMu", - "TmVzdGVkTWVzc2FnZToCOAEabQocTWFwU3RyaW5nRm9yZWlnbk1lc3NhZ2VF", - "bnRyeRILCgNrZXkYASABKAkSPAoFdmFsdWUYAiABKAsyLS5wcm90b2J1Zl90", - "ZXN0X21lc3NhZ2VzLnByb3RvMy5Gb3JlaWduTWVzc2FnZToCOAEaeAoYTWFw", - "U3RyaW5nTmVzdGVkRW51bUVudHJ5EgsKA2tleRgBIAEoCRJLCgV2YWx1ZRgC", - "IAEoDjI8LnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLlRlc3RBbGxU", - "eXBlc1Byb3RvMy5OZXN0ZWRFbnVtOgI4ARpnChlNYXBTdHJpbmdGb3JlaWdu", - "RW51bUVudHJ5EgsKA2tleRgBIAEoCRI5CgV2YWx1ZRgCIAEoDjIqLnByb3Rv", - "YnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLkZvcmVpZ25FbnVtOgI4ASI5CgpO", - "ZXN0ZWRFbnVtEgcKA0ZPTxAAEgcKA0JBUhABEgcKA0JBWhACEhAKA05FRxD/", - "//////////8BIlkKC0FsaWFzZWRFbnVtEg0KCUFMSUFTX0ZPTxAAEg0KCUFM", - "SUFTX0JBUhABEg0KCUFMSUFTX0JBWhACEgcKA1FVWBACEgcKA3F1eBACEgcK", - "A2JBehACGgIQAUINCgtvbmVvZl9maWVsZEoGCPUDEP8DIhsKDkZvcmVpZ25N", - "ZXNzYWdlEgkKAWMYASABKAUqQAoLRm9yZWlnbkVudW0SDwoLRk9SRUlHTl9G", - "T08QABIPCgtGT1JFSUdOX0JBUhABEg8KC0ZPUkVJR05fQkFaEAJCOAooY29t", - "Lmdvb2dsZS5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvM0gB+AEBogIG", - "UHJvdG8zYgZwcm90bzM=")); + "SAASNgoQb25lb2ZfbnVsbF92YWx1ZRh4IAEoDjIaLmdvb2dsZS5wcm90b2J1", + "Zi5OdWxsVmFsdWVIABI6ChVvcHRpb25hbF9ib29sX3dyYXBwZXIYyQEgASgL", + "MhouZ29vZ2xlLnByb3RvYnVmLkJvb2xWYWx1ZRI8ChZvcHRpb25hbF9pbnQz", + "Ml93cmFwcGVyGMoBIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQzMlZhbHVl", + "EjwKFm9wdGlvbmFsX2ludDY0X3dyYXBwZXIYywEgASgLMhsuZ29vZ2xlLnBy", + "b3RvYnVmLkludDY0VmFsdWUSPgoXb3B0aW9uYWxfdWludDMyX3dyYXBwZXIY", + "zAEgASgLMhwuZ29vZ2xlLnByb3RvYnVmLlVJbnQzMlZhbHVlEj4KF29wdGlv", + "bmFsX3VpbnQ2NF93cmFwcGVyGM0BIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5V", + "SW50NjRWYWx1ZRI8ChZvcHRpb25hbF9mbG9hdF93cmFwcGVyGM4BIAEoCzIb", + "Lmdvb2dsZS5wcm90b2J1Zi5GbG9hdFZhbHVlEj4KF29wdGlvbmFsX2RvdWJs", + "ZV93cmFwcGVyGM8BIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1", + "ZRI+ChdvcHRpb25hbF9zdHJpbmdfd3JhcHBlchjQASABKAsyHC5nb29nbGUu", + "cHJvdG9idWYuU3RyaW5nVmFsdWUSPAoWb3B0aW9uYWxfYnl0ZXNfd3JhcHBl", + "chjRASABKAsyGy5nb29nbGUucHJvdG9idWYuQnl0ZXNWYWx1ZRI6ChVyZXBl", + "YXRlZF9ib29sX3dyYXBwZXIY0wEgAygLMhouZ29vZ2xlLnByb3RvYnVmLkJv", + "b2xWYWx1ZRI8ChZyZXBlYXRlZF9pbnQzMl93cmFwcGVyGNQBIAMoCzIbLmdv", + "b2dsZS5wcm90b2J1Zi5JbnQzMlZhbHVlEjwKFnJlcGVhdGVkX2ludDY0X3dy", + "YXBwZXIY1QEgAygLMhsuZ29vZ2xlLnByb3RvYnVmLkludDY0VmFsdWUSPgoX", + "cmVwZWF0ZWRfdWludDMyX3dyYXBwZXIY1gEgAygLMhwuZ29vZ2xlLnByb3Rv", + "YnVmLlVJbnQzMlZhbHVlEj4KF3JlcGVhdGVkX3VpbnQ2NF93cmFwcGVyGNcB", + "IAMoCzIcLmdvb2dsZS5wcm90b2J1Zi5VSW50NjRWYWx1ZRI8ChZyZXBlYXRl", + "ZF9mbG9hdF93cmFwcGVyGNgBIAMoCzIbLmdvb2dsZS5wcm90b2J1Zi5GbG9h", + "dFZhbHVlEj4KF3JlcGVhdGVkX2RvdWJsZV93cmFwcGVyGNkBIAMoCzIcLmdv", + "b2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI+ChdyZXBlYXRlZF9zdHJpbmdf", + "d3JhcHBlchjaASADKAsyHC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWUS", + "PAoWcmVwZWF0ZWRfYnl0ZXNfd3JhcHBlchjbASADKAsyGy5nb29nbGUucHJv", + "dG9idWYuQnl0ZXNWYWx1ZRI1ChFvcHRpb25hbF9kdXJhdGlvbhitAiABKAsy", + "GS5nb29nbGUucHJvdG9idWYuRHVyYXRpb24SNwoSb3B0aW9uYWxfdGltZXN0", + "YW1wGK4CIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASOAoTb3B0", + "aW9uYWxfZmllbGRfbWFzaxivAiABKAsyGi5nb29nbGUucHJvdG9idWYuRmll", + "bGRNYXNrEjEKD29wdGlvbmFsX3N0cnVjdBiwAiABKAsyFy5nb29nbGUucHJv", + "dG9idWYuU3RydWN0EisKDG9wdGlvbmFsX2FueRixAiABKAsyFC5nb29nbGUu", + "cHJvdG9idWYuQW55Ei8KDm9wdGlvbmFsX3ZhbHVlGLICIAEoCzIWLmdvb2ds", + "ZS5wcm90b2J1Zi5WYWx1ZRI4ChNvcHRpb25hbF9udWxsX3ZhbHVlGLMCIAEo", + "DjIaLmdvb2dsZS5wcm90b2J1Zi5OdWxsVmFsdWUSNQoRcmVwZWF0ZWRfZHVy", + "YXRpb24YtwIgAygLMhkuZ29vZ2xlLnByb3RvYnVmLkR1cmF0aW9uEjcKEnJl", + "cGVhdGVkX3RpbWVzdGFtcBi4AiADKAsyGi5nb29nbGUucHJvdG9idWYuVGlt", + "ZXN0YW1wEjcKEnJlcGVhdGVkX2ZpZWxkbWFzaxi5AiADKAsyGi5nb29nbGUu", + "cHJvdG9idWYuRmllbGRNYXNrEjEKD3JlcGVhdGVkX3N0cnVjdBjEAiADKAsy", + "Fy5nb29nbGUucHJvdG9idWYuU3RydWN0EisKDHJlcGVhdGVkX2FueRi7AiAD", + "KAsyFC5nb29nbGUucHJvdG9idWYuQW55Ei8KDnJlcGVhdGVkX3ZhbHVlGLwC", + "IAMoCzIWLmdvb2dsZS5wcm90b2J1Zi5WYWx1ZRI4ChNyZXBlYXRlZF9saXN0", + "X3ZhbHVlGL0CIAMoCzIaLmdvb2dsZS5wcm90b2J1Zi5MaXN0VmFsdWUSEwoK", + "ZmllbGRuYW1lMRiRAyABKAUSFAoLZmllbGRfbmFtZTIYkgMgASgFEhUKDF9m", + "aWVsZF9uYW1lMxiTAyABKAUSFgoNZmllbGRfX25hbWU0XxiUAyABKAUSFAoL", + "ZmllbGQwbmFtZTUYlQMgASgFEhYKDWZpZWxkXzBfbmFtZTYYlgMgASgFEhMK", + "CmZpZWxkTmFtZTcYlwMgASgFEhMKCkZpZWxkTmFtZTgYmAMgASgFEhQKC2Zp", + "ZWxkX05hbWU5GJkDIAEoBRIVCgxGaWVsZF9OYW1lMTAYmgMgASgFEhUKDEZJ", + "RUxEX05BTUUxMRibAyABKAUSFQoMRklFTERfbmFtZTEyGJwDIAEoBRIXCg5f", + "X2ZpZWxkX25hbWUxMxidAyABKAUSFwoOX19GaWVsZF9uYW1lMTQYngMgASgF", + "EhYKDWZpZWxkX19uYW1lMTUYnwMgASgFEhYKDWZpZWxkX19OYW1lMTYYoAMg", + "ASgFEhcKDmZpZWxkX25hbWUxN19fGKEDIAEoBRIXCg5GaWVsZF9uYW1lMThf", + "XxiiAyABKAUaYgoNTmVzdGVkTWVzc2FnZRIJCgFhGAEgASgFEkYKC2NvcmVj", + "dXJzaXZlGAIgASgLMjEucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzMu", + "VGVzdEFsbFR5cGVzUHJvdG8zGjQKEk1hcEludDMySW50MzJFbnRyeRILCgNr", + "ZXkYASABKAUSDQoFdmFsdWUYAiABKAU6AjgBGjQKEk1hcEludDY0SW50NjRF", + "bnRyeRILCgNrZXkYASABKAMSDQoFdmFsdWUYAiABKAM6AjgBGjYKFE1hcFVp", + "bnQzMlVpbnQzMkVudHJ5EgsKA2tleRgBIAEoDRINCgV2YWx1ZRgCIAEoDToC", + "OAEaNgoUTWFwVWludDY0VWludDY0RW50cnkSCwoDa2V5GAEgASgEEg0KBXZh", + "bHVlGAIgASgEOgI4ARo2ChRNYXBTaW50MzJTaW50MzJFbnRyeRILCgNrZXkY", + "ASABKBESDQoFdmFsdWUYAiABKBE6AjgBGjYKFE1hcFNpbnQ2NFNpbnQ2NEVu", + "dHJ5EgsKA2tleRgBIAEoEhINCgV2YWx1ZRgCIAEoEjoCOAEaOAoWTWFwRml4", + "ZWQzMkZpeGVkMzJFbnRyeRILCgNrZXkYASABKAcSDQoFdmFsdWUYAiABKAc6", + "AjgBGjgKFk1hcEZpeGVkNjRGaXhlZDY0RW50cnkSCwoDa2V5GAEgASgGEg0K", + "BXZhbHVlGAIgASgGOgI4ARo6ChhNYXBTZml4ZWQzMlNmaXhlZDMyRW50cnkS", + "CwoDa2V5GAEgASgPEg0KBXZhbHVlGAIgASgPOgI4ARo6ChhNYXBTZml4ZWQ2", + "NFNmaXhlZDY0RW50cnkSCwoDa2V5GAEgASgQEg0KBXZhbHVlGAIgASgQOgI4", + "ARo0ChJNYXBJbnQzMkZsb2F0RW50cnkSCwoDa2V5GAEgASgFEg0KBXZhbHVl", + "GAIgASgCOgI4ARo1ChNNYXBJbnQzMkRvdWJsZUVudHJ5EgsKA2tleRgBIAEo", + "BRINCgV2YWx1ZRgCIAEoAToCOAEaMgoQTWFwQm9vbEJvb2xFbnRyeRILCgNr", + "ZXkYASABKAgSDQoFdmFsdWUYAiABKAg6AjgBGjYKFE1hcFN0cmluZ1N0cmlu", + "Z0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAEaNQoTTWFw", + "U3RyaW5nQnl0ZXNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAw6", + "AjgBGn4KG01hcFN0cmluZ05lc3RlZE1lc3NhZ2VFbnRyeRILCgNrZXkYASAB", + "KAkSTgoFdmFsdWUYAiABKAsyPy5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnBy", + "b3RvMy5UZXN0QWxsVHlwZXNQcm90bzMuTmVzdGVkTWVzc2FnZToCOAEabQoc", + "TWFwU3RyaW5nRm9yZWlnbk1lc3NhZ2VFbnRyeRILCgNrZXkYASABKAkSPAoF", + "dmFsdWUYAiABKAsyLS5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5G", + "b3JlaWduTWVzc2FnZToCOAEaeAoYTWFwU3RyaW5nTmVzdGVkRW51bUVudHJ5", + "EgsKA2tleRgBIAEoCRJLCgV2YWx1ZRgCIAEoDjI8LnByb3RvYnVmX3Rlc3Rf", + "bWVzc2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlc1Byb3RvMy5OZXN0ZWRFbnVt", + "OgI4ARpnChlNYXBTdHJpbmdGb3JlaWduRW51bUVudHJ5EgsKA2tleRgBIAEo", + "CRI5CgV2YWx1ZRgCIAEoDjIqLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJv", + "dG8zLkZvcmVpZ25FbnVtOgI4ASI5CgpOZXN0ZWRFbnVtEgcKA0ZPTxAAEgcK", + "A0JBUhABEgcKA0JBWhACEhAKA05FRxD///////////8BIlkKC0FsaWFzZWRF", + "bnVtEg0KCUFMSUFTX0ZPTxAAEg0KCUFMSUFTX0JBUhABEg0KCUFMSUFTX0JB", + "WhACEgcKA1FVWBACEgcKA3F1eBACEgcKA2JBehACGgIQAUINCgtvbmVvZl9m", + "aWVsZEoGCPUDEP8DIhsKDkZvcmVpZ25NZXNzYWdlEgkKAWMYASABKAUqQAoL", + "Rm9yZWlnbkVudW0SDwoLRk9SRUlHTl9GT08QABIPCgtGT1JFSUdOX0JBUhAB", + "Eg8KC0ZPUkVJR05fQkFaEAJCOAooY29tLmdvb2dsZS5wcm90b2J1Zl90ZXN0", + "X21lc3NhZ2VzLnByb3RvM0gB+AEBogIGUHJvdG8zYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.DurationReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.FieldMaskReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::ProtobufTestMessages.Proto3.ForeignEnum), }, null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3), global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Parser, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalAliasedEnum", "OptionalStringPiece", "OptionalCord", "RecursiveMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedStringPiece", "RepeatedCord", "PackedInt32", "PackedInt64", "PackedUint32", "PackedUint64", "PackedSint32", "PackedSint64", "PackedFixed32", "PackedFixed64", "PackedSfixed32", "PackedSfixed64", "PackedFloat", "PackedDouble", "PackedBool", "PackedNestedEnum", "UnpackedInt32", "UnpackedInt64", "UnpackedUint32", "UnpackedUint64", "UnpackedSint32", "UnpackedSint64", "UnpackedFixed32", "UnpackedFixed64", "UnpackedSfixed32", "UnpackedSfixed64", "UnpackedFloat", "UnpackedDouble", "UnpackedBool", "UnpackedNestedEnum", "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapStringBytes", "MapStringNestedMessage", "MapStringForeignMessage", "MapStringNestedEnum", "MapStringForeignEnum", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes", "OneofBool", "OneofUint64", "OneofFloat", "OneofDouble", "OneofEnum", "OptionalBoolWrapper", "OptionalInt32Wrapper", "OptionalInt64Wrapper", "OptionalUint32Wrapper", "OptionalUint64Wrapper", "OptionalFloatWrapper", "OptionalDoubleWrapper", "OptionalStringWrapper", "OptionalBytesWrapper", "RepeatedBoolWrapper", "RepeatedInt32Wrapper", "RepeatedInt64Wrapper", "RepeatedUint32Wrapper", "RepeatedUint64Wrapper", "RepeatedFloatWrapper", "RepeatedDoubleWrapper", "RepeatedStringWrapper", "RepeatedBytesWrapper", "OptionalDuration", "OptionalTimestamp", "OptionalFieldMask", "OptionalStruct", "OptionalAny", "OptionalValue", "RepeatedDuration", "RepeatedTimestamp", "RepeatedFieldmask", "RepeatedStruct", "RepeatedAny", "RepeatedValue", "RepeatedListValue", "Fieldname1", "FieldName2", "FieldName3", "FieldName4", "Field0Name5", "Field0Name6", "FieldName7", "FieldName8", "FieldName9", "FieldName10", "FIELDNAME11", "FIELDName12", "FieldName13", "FieldName14", "FieldName15", "FieldName16", "FieldName17", "FieldName18" }, new[]{ "OneofField" }, new[]{ typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum), typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.AliasedEnum) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage), global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage.Parser, new[]{ "A", "Corecursive" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3), global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Parser, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalAliasedEnum", "OptionalStringPiece", "OptionalCord", "RecursiveMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedStringPiece", "RepeatedCord", "PackedInt32", "PackedInt64", "PackedUint32", "PackedUint64", "PackedSint32", "PackedSint64", "PackedFixed32", "PackedFixed64", "PackedSfixed32", "PackedSfixed64", "PackedFloat", "PackedDouble", "PackedBool", "PackedNestedEnum", "UnpackedInt32", "UnpackedInt64", "UnpackedUint32", "UnpackedUint64", "UnpackedSint32", "UnpackedSint64", "UnpackedFixed32", "UnpackedFixed64", "UnpackedSfixed32", "UnpackedSfixed64", "UnpackedFloat", "UnpackedDouble", "UnpackedBool", "UnpackedNestedEnum", "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapStringBytes", "MapStringNestedMessage", "MapStringForeignMessage", "MapStringNestedEnum", "MapStringForeignEnum", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes", "OneofBool", "OneofUint64", "OneofFloat", "OneofDouble", "OneofEnum", "OneofNullValue", "OptionalBoolWrapper", "OptionalInt32Wrapper", "OptionalInt64Wrapper", "OptionalUint32Wrapper", "OptionalUint64Wrapper", "OptionalFloatWrapper", "OptionalDoubleWrapper", "OptionalStringWrapper", "OptionalBytesWrapper", "RepeatedBoolWrapper", "RepeatedInt32Wrapper", "RepeatedInt64Wrapper", "RepeatedUint32Wrapper", "RepeatedUint64Wrapper", "RepeatedFloatWrapper", "RepeatedDoubleWrapper", "RepeatedStringWrapper", "RepeatedBytesWrapper", "OptionalDuration", "OptionalTimestamp", "OptionalFieldMask", "OptionalStruct", "OptionalAny", "OptionalValue", "OptionalNullValue", "RepeatedDuration", "RepeatedTimestamp", "RepeatedFieldmask", "RepeatedStruct", "RepeatedAny", "RepeatedValue", "RepeatedListValue", "Fieldname1", "FieldName2", "FieldName3", "FieldName4", "Field0Name5", "Field0Name6", "FieldName7", "FieldName8", "FieldName9", "FieldName10", "FIELDNAME11", "FIELDName12", "FieldName13", "FieldName14", "FieldName15", "FieldName16", "FieldName17", "FieldName18" }, new[]{ "OneofField" }, new[]{ typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum), typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.AliasedEnum) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage), global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage.Parser, new[]{ "A", "Corecursive" }, null, null, null, null), null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }), new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto3.ForeignMessage), global::ProtobufTestMessages.Proto3.ForeignMessage.Parser, new[]{ "C" }, null, null, null, null) })); @@ -403,6 +405,7 @@ namespace ProtobufTestMessages.Proto3 { optionalStruct_ = other.optionalStruct_ != null ? other.optionalStruct_.Clone() : null; optionalAny_ = other.optionalAny_ != null ? other.optionalAny_.Clone() : null; optionalValue_ = other.optionalValue_ != null ? other.optionalValue_.Clone() : null; + optionalNullValue_ = other.optionalNullValue_; repeatedDuration_ = other.repeatedDuration_.Clone(); repeatedTimestamp_ = other.repeatedTimestamp_.Clone(); repeatedFieldmask_ = other.repeatedFieldmask_.Clone(); @@ -456,6 +459,9 @@ namespace ProtobufTestMessages.Proto3 { case OneofFieldOneofCase.OneofEnum: OneofEnum = other.OneofEnum; break; + case OneofFieldOneofCase.OneofNullValue: + OneofNullValue = other.OneofNullValue; + break; } _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); @@ -1513,6 +1519,17 @@ namespace ProtobufTestMessages.Proto3 { } } + /// Field number for the "oneof_null_value" field. + public const int OneofNullValueFieldNumber = 120; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.WellKnownTypes.NullValue OneofNullValue { + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNullValue ? (global::Google.Protobuf.WellKnownTypes.NullValue) oneofField_ : global::Google.Protobuf.WellKnownTypes.NullValue.NullValue; } + set { + oneofField_ = value; + oneofFieldCase_ = OneofFieldOneofCase.OneofNullValue; + } + } + /// Field number for the "optional_bool_wrapper" field. public const int OptionalBoolWrapperFieldNumber = 201; private static readonly pb::FieldCodec _single_optionalBoolWrapper_codec = pb::FieldCodec.ForStructWrapper(1610); @@ -1789,6 +1806,17 @@ namespace ProtobufTestMessages.Proto3 { } } + /// Field number for the "optional_null_value" field. + public const int OptionalNullValueFieldNumber = 307; + private global::Google.Protobuf.WellKnownTypes.NullValue optionalNullValue_ = global::Google.Protobuf.WellKnownTypes.NullValue.NullValue; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.WellKnownTypes.NullValue OptionalNullValue { + get { return optionalNullValue_; } + set { + optionalNullValue_ = value; + } + } + /// Field number for the "repeated_duration" field. public const int RepeatedDurationFieldNumber = 311; private static readonly pb::FieldCodec _repeated_repeatedDuration_codec @@ -2074,6 +2102,7 @@ namespace ProtobufTestMessages.Proto3 { OneofFloat = 117, OneofDouble = 118, OneofEnum = 119, + OneofNullValue = 120, } private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2200,6 +2229,7 @@ namespace ProtobufTestMessages.Proto3 { if (!pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.Equals(OneofFloat, other.OneofFloat)) return false; if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(OneofDouble, other.OneofDouble)) return false; if (OneofEnum != other.OneofEnum) return false; + if (OneofNullValue != other.OneofNullValue) return false; if (OptionalBoolWrapper != other.OptionalBoolWrapper) return false; if (OptionalInt32Wrapper != other.OptionalInt32Wrapper) return false; if (OptionalInt64Wrapper != other.OptionalInt64Wrapper) return false; @@ -2224,6 +2254,7 @@ namespace ProtobufTestMessages.Proto3 { if (!object.Equals(OptionalStruct, other.OptionalStruct)) return false; if (!object.Equals(OptionalAny, other.OptionalAny)) return false; if (!object.Equals(OptionalValue, other.OptionalValue)) return false; + if (OptionalNullValue != other.OptionalNullValue) return false; if(!repeatedDuration_.Equals(other.repeatedDuration_)) return false; if(!repeatedTimestamp_.Equals(other.repeatedTimestamp_)) return false; if(!repeatedFieldmask_.Equals(other.repeatedFieldmask_)) return false; @@ -2356,6 +2387,7 @@ namespace ProtobufTestMessages.Proto3 { if (oneofFieldCase_ == OneofFieldOneofCase.OneofFloat) hash ^= pbc::ProtobufEqualityComparers.BitwiseSingleEqualityComparer.GetHashCode(OneofFloat); if (oneofFieldCase_ == OneofFieldOneofCase.OneofDouble) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(OneofDouble); if (oneofFieldCase_ == OneofFieldOneofCase.OneofEnum) hash ^= OneofEnum.GetHashCode(); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNullValue) hash ^= OneofNullValue.GetHashCode(); if (optionalBoolWrapper_ != null) hash ^= OptionalBoolWrapper.GetHashCode(); if (optionalInt32Wrapper_ != null) hash ^= OptionalInt32Wrapper.GetHashCode(); if (optionalInt64Wrapper_ != null) hash ^= OptionalInt64Wrapper.GetHashCode(); @@ -2380,6 +2412,7 @@ namespace ProtobufTestMessages.Proto3 { if (optionalStruct_ != null) hash ^= OptionalStruct.GetHashCode(); if (optionalAny_ != null) hash ^= OptionalAny.GetHashCode(); if (optionalValue_ != null) hash ^= OptionalValue.GetHashCode(); + if (OptionalNullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) hash ^= OptionalNullValue.GetHashCode(); hash ^= repeatedDuration_.GetHashCode(); hash ^= repeatedTimestamp_.GetHashCode(); hash ^= repeatedFieldmask_.GetHashCode(); @@ -2615,6 +2648,10 @@ namespace ProtobufTestMessages.Proto3 { output.WriteRawTag(184, 7); output.WriteEnum((int) OneofEnum); } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNullValue) { + output.WriteRawTag(192, 7); + output.WriteEnum((int) OneofNullValue); + } if (optionalBoolWrapper_ != null) { _single_optionalBoolWrapper_codec.WriteTagAndValue(output, OptionalBoolWrapper); } @@ -2675,6 +2712,10 @@ namespace ProtobufTestMessages.Proto3 { output.WriteRawTag(146, 19); output.WriteMessage(OptionalValue); } + if (OptionalNullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) { + output.WriteRawTag(152, 19); + output.WriteEnum((int) OptionalNullValue); + } repeatedDuration_.WriteTo(output, _repeated_repeatedDuration_codec); repeatedTimestamp_.WriteTo(output, _repeated_repeatedTimestamp_codec); repeatedFieldmask_.WriteTo(output, _repeated_repeatedFieldmask_codec); @@ -2926,6 +2967,9 @@ namespace ProtobufTestMessages.Proto3 { if (oneofFieldCase_ == OneofFieldOneofCase.OneofEnum) { size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OneofEnum); } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNullValue) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OneofNullValue); + } if (optionalBoolWrapper_ != null) { size += _single_optionalBoolWrapper_codec.CalculateSizeWithTag(OptionalBoolWrapper); } @@ -2980,6 +3024,9 @@ namespace ProtobufTestMessages.Proto3 { if (optionalValue_ != null) { size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalValue); } + if (OptionalNullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalNullValue); + } size += repeatedDuration_.CalculateSize(_repeated_repeatedDuration_codec); size += repeatedTimestamp_.CalculateSize(_repeated_repeatedTimestamp_codec); size += repeatedFieldmask_.CalculateSize(_repeated_repeatedFieldmask_codec); @@ -3288,6 +3335,9 @@ namespace ProtobufTestMessages.Proto3 { } OptionalValue.MergeFrom(other.OptionalValue); } + if (other.OptionalNullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) { + OptionalNullValue = other.OptionalNullValue; + } repeatedDuration_.Add(other.repeatedDuration_); repeatedTimestamp_.Add(other.repeatedTimestamp_); repeatedFieldmask_.Add(other.repeatedFieldmask_); @@ -3380,6 +3430,9 @@ namespace ProtobufTestMessages.Proto3 { case OneofFieldOneofCase.OneofEnum: OneofEnum = other.OneofEnum; break; + case OneofFieldOneofCase.OneofNullValue: + OneofNullValue = other.OneofNullValue; + break; } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -3854,6 +3907,11 @@ namespace ProtobufTestMessages.Proto3 { oneofFieldCase_ = OneofFieldOneofCase.OneofEnum; break; } + case 960: { + oneofField_ = input.ReadEnum(); + oneofFieldCase_ = OneofFieldOneofCase.OneofNullValue; + break; + } case 1610: { bool? value = _single_optionalBoolWrapper_codec.Read(input); if (optionalBoolWrapper_ == null || value != false) { @@ -3995,6 +4053,10 @@ namespace ProtobufTestMessages.Proto3 { input.ReadMessage(OptionalValue); break; } + case 2456: { + OptionalNullValue = (global::Google.Protobuf.WellKnownTypes.NullValue) input.ReadEnum(); + break; + } case 2490: { repeatedDuration_.AddEntriesFrom(input, _repeated_repeatedDuration_codec); break; @@ -4567,6 +4629,11 @@ namespace ProtobufTestMessages.Proto3 { oneofFieldCase_ = OneofFieldOneofCase.OneofEnum; break; } + case 960: { + oneofField_ = input.ReadEnum(); + oneofFieldCase_ = OneofFieldOneofCase.OneofNullValue; + break; + } case 1610: { bool? value = _single_optionalBoolWrapper_codec.Read(ref input); if (optionalBoolWrapper_ == null || value != false) { @@ -4708,6 +4775,10 @@ namespace ProtobufTestMessages.Proto3 { input.ReadMessage(OptionalValue); break; } + case 2456: { + OptionalNullValue = (global::Google.Protobuf.WellKnownTypes.NullValue) input.ReadEnum(); + break; + } case 2490: { repeatedDuration_.AddEntriesFrom(ref input, _repeated_repeatedDuration_codec); break; diff --git a/csharp/src/Google.Protobuf.Test/testprotos.pb b/csharp/src/Google.Protobuf.Test/testprotos.pb index 05312db88c13d9bff6a851da5a86b7f1cba3e87b..089ef7512a4cce971aeda0027deff69036c06c1a 100644 GIT binary patch delta 4900 zcmb7|dr(x@9mnr^?84qfg^MU4FCVBu1;rOeB_Tv>DjKJ0YJDUGaYY1nS6Bp1a8*>S zulRx!?MypueN37radf8F8Qa+OpK4~5ajeFSbu?Jt8aMq#GnQWz*ES8Sv$vYQ!rsR*P3Wcg_1Nl{<+KOOR zeyF~xAY31cgcdX|Du^r(2O0_%1{x~stHY5{eR#p)KXpEeOL*DznKa&Sv0=u`tw%p^ zJNh}XkA6;*s>$EP$rsroQGbN>6+bRv2_uGoZ}^&Es3}-b5nLW#AdYphq4wSqw#J)K zs&fo9N=4H#mSxYH#*XzQpNPcStcq_WY7%1WY}R-DxMxh$5NfQi3{-}Kkw9}qC+zie zcGjCPLnjVb6by{o2dkR=Fm<#qw)EraV*G5DWdFOB-J#uW{LlIy(#CMLnw7a~k{M@tvW!k* z-|u4cyyDmv)|TqDHP0wDKj0?ihQ-GkZ`p5dWku9eM6L9oI2~ju;@~#6Ft3Qln+c|e z8`K~cEAsWwia{kNnWZMj7=|W_;_Ylo(L`!02l3*eKS?WTvC^~xJuxHG92cXh#frtz z?W|}*u|reP#SSeK6gxBpT?~3nd<=(r-5$P!ah~_OQ!NAWx-U`XW73n{+ng5zxW(p( zxgG3{yg9U&a&Y+PBxY#^|D65<%)*%8W3l<-%MLcCXueaQ2ldVO>-Zkf^OO22+5>ui zdOveyjE1pX%n+>{D?liLe=&L}Ya|paP$S-d z4>i_MZ)_HL27gUls#fsV^vj5KgvbR53eRpfCNJp3mmLrK(v@F!JeZkfj*7)c$CrxA z-E4H;QYXIb_|iCC4~Ks#>KPsLqvH|rm)&e^QABl|P}%W_+7VEoBWg!LfsQz{fw4)9 z*ux5kH#ybGjyI`}6Dm92gpQv`M$4(?Jx+{Hd($3v+}Ha!iSJ>Sp$dww^Uny*L$Pxn zOtF41%Nv2G@n#R43V5(!pAjsBl1xghgWPGdh5VGbxRtOS?S0HD9QBO%+``8Cib!=RsIQ&Z_OlMJXt~Mq?Boww zuAdwe6OOP6tVQ3V8;-DE1$YU3&%2=eLJQP|ai^&p?bZ>t+M6&%-<|`FDK@U_ZwT8s z*%aAjyuT2ivax)fGm$HwvgFZ)&zNdab)a@(T}4Apc!7-z6nEz2(t@CQsSQe78lh*Z>tbacR@d^;BXxpYbbPMAR#TKpv8V`Ik;${UlJTH>UgBw6`d;-sAPhNpHJG!6>hh|=oF!Sh_-Zg`Nzp{ypmJtQEPjqqoo)$GNS$s8&~t9OB|y)~ zbfJBGT2!a21#{j_R}1F6o30kjc{g31#lLXV)d7Xn>FR)f;ijtt`UTRdN`n@^Kxm1Y zWKc}m&r`AoX$kZK$<^}+0=+;czbKaP=d($vIK7`|X6Gtz7~YFyu&zH0??v*$OQOdC zK70BUWvb^EzeMm_kTrv??;vcLfLR=z4inT`6o3#;HyWFge2+`$cZA6GJH|sKsUqMz?(lSJX)b%ezq$|X) zTd)j~uDHcSmm$;@RHG))Wbvzn>Rr|Z7BXE$ZUTFi^c$`v(5s}NP@&BhzecFuY|TI+ z^_Fi2dW~f0lhO?Inmj4d?!CC&;@1fsrvfhr3#r-VV6T&m0zC@$Iw>5h(yp-h4MO$c z3ZRgw%DV#S4U#rgOQ1K%uzZESZSm+$LZ4HkZ-a$Q(Gu)U(r18{U~iJ#p^AOS;-ZSq2y+xiIuFw{X-`10j8ngv0w4QAX*xT-GTfp9SXS>qkcL>!R zcqNt^QZMyNM7l%#1636(5$O&Yq*r7mBHeM%W7Ohz@iVPhocuk{%-5$W3g#}!9j`(} z!Q3U!PgZgjM(+_?EK)z<*&_#;Jxwo8$SV1ROQVPm1_-#9}rq7{s=0XrCe(y^?+m#b2O+2Bwyd9tr&hNo7-JVD?x{#O-G|e z4~aj=(J_Dj0!Jg2 zlcox6gX?Q-9#I8XQg7vIldi8x-*h29H3M#T6=-o@QL+ekby z9p~uSczlYZfqz3%^@iPq;cqb~HM~jU&>G()TknP0- z^Q23+cBgc$qfTpg!L?qx_P`a@u3gf#-gULZ)rO3!pmy0nXx+ee*}yg$uM2LMc$-^F z2ZlGec!$KHHQpid4Zzb?{0_-)kbI%ZxZ$(-Ch_-!d`xr`^{cznC%;-Cdv@li=AcjtWLzvv?28mK-lrw%c$X%~e+;O{ zu%g}_)ad9A>yZWQpdR`C%su#T!Qwmd5h_8cFbEm@rjioX?WFjo>h@xAm+O`FL255P c*B~7)RJ-=}F=F3i(Ata<-fm|c;wK{i11jy6ivR!s delta 4633 zcma)9X>e3k8hv-^PWMZIA*+{&+qp&)fYz^ zEB3egO3;kepSb%nOC3=j^tZJxuYY;Dza><^I%J+%#2&ii7OO;g+G6v<@7PMh{xx40 zjhQ?{oS)4S%+ONys+)918hNmS4V!@3{jW^Fny2ijJRtvy(VwsabD58kn7H{WU4b^= z^tZ68B(mE)+{4ltX|qz4d8z^p3+1XTBufe&CsS>pp&b7N1~*<`U!lhsu59fLG5>Le zz2p|}Y-5{J=cugt+8q5L*D2QwK1HiFpMHatQ8Hbu?_-_fmqZ?)K1`3(U0kCYGuZU_ z1bwc~fr!B>L|#9eS5ZNAn?c-o7@MGwq!?)mL0yrVrBAig)L@k~JN-#6K9%3Y*HPjm%UTwV|-7giW`{@&S6$Od4RE=f6ljb}9zNi{5yJBxhuz{*oo&23sQL zzQt!>4b=n#+AlS^|b)MmRF+2#>4CWJ; z1e=iWvpw((9zJhmVSwP_!@`tUe1sasw4H2Xeq)qRzd0sVA@G|sGOdXaxc~uidncQmABg(Pi3hytHlImKR<=IT^2fx3qIwsb zlpl=x%ZUeLR6QL0AnKW9@iFmsv40nvQr2!yoKQLOc6&zvLEUce2q382quqemA(D5q z(!!2tb#mez_QVO56Ys#pkB`L2so_3Bv@>RCH~X7+#0laVrdOj1imCI@#WQ=@Z;C!A zFdBvvfQMM2&k5#kLna{xFSnMQ89yyP-NR}MPdgG!o}YFk7(HNo!ZNpY4NcNdi|6(- zKUphJdR{^Pqc6m|w$|EEgTEzmg*>&7z2%OpQipl0RwY&q;cDcESZ*viD)NuA>0)#h zOA%|1vf<j2kLqe&s0Za>vb5=3}&3Chpw_g!GH1V{9?m8o6t~I>w9{(;w$v zTG3G7RQGaoZE$6|^U=gzh-+}6N|UE8G>eb36UnS=j4mpxd6t=anN?8I6-l@93L7zD z;-ec0hFaT}hsq=WiJVVZk$LV4rX?=C%ks@PhuGB^cD6(pHPw8S`29Wh+~D)4QUv>s z8HELpb`Lc)*9Swj&4I|Mg5NRWj*DKZW3@Svb(s7U8xzkyLnG^|d5+oP<-aA7#ZD17 zbRPdWE553=HV~+94Ms98j^%qj&WaanRi-zQZ<$87pA<8X@NweL&+vcJ-X-QAs`*!G z=3iIvT`}f?7G4zR@yjoQTy2N>^%{OK#=V7-^pkY(*wlsQQduLkgIwAf#tV)+7ZX zJwv8W7Z>;N1;rKiQy(;E3C&UvnzJN(ih|IbC1vH}`MrEWSmkMe=A4tK0h)78o(5>n zA&*^Rqrtx*RHbW#6i}sWg!Bt1T_dDlAe}8;Y4G!obfrk$$4jF{G{Nahr-&vved!d@ z1g9^ZBAN|;fzT?ut7dLNT|qcqAhBZ=gwq9*tD0?w(*-hfwp~+9i@`4vI#(Rq$Fp*B zZA}X_7s)u)WeYSHN#z{za35bZbDm8KAnhfBYgS%p8Vw-rB@#PML0DWOd9xIR#U)bp zl<0q(FCufr(Azw#L8WU2_iHCzE4W`Hon2zk;Fk$iS%b(5sImr;^|F&S2&cma%1NY+7e%aMc)ew)xT+b@jlfGT?!*>98B(JBh3+vEv# z1BT&ro8ShFoTBxJ-XXM9AFjJ`sKkzgJat00jn>N_1b0YIK@>xLhZHNXE`;x5_lU0! z@|+2yY*v?4-6f+-q8O^Xa^FN!b|ZX`&`MG8E>vS}R<~5$Be`W!4AnhSK1&Z;8>k22 z?+Hy4e|NcjB7BIu!#%`hJ&Um=J<{TP;xVEa7T=R3wI_QK{y`q9NUyz84y@$8QvL(+ zjEu%1|A8c@*>!I~_(yp-BJvGl;~}0hDp5iCYw1UlqK@oFuNSaf0m?)HSfVgwY6DB|Kqf^1s)INWd8JP))vWn z;ILi?>!HkaU$RuD*Cp$r)8kgKenyXC+WTOs-nL5C&rWaK!1_h9+QCXttZkC@3s_>` z`~2B(mfiApIp!`J9rJcM<}T_aMDqG{@Dw-4cNim$lHnERw0Sglf@ly^JwKAE-K zk@q9qLuqEEt?!q5JW%?6sqdj4wIcme-$SD-GJtR|^y2Ubzgo8e$?A1jgJ5kyk>ajo zsa6IhYlBnE4zM;#R>@(Wlc88UBx|E&mFkRZUW0EI*AMf_;mtJGz5>1S$2;Kg$ky{} zR6-*OH->!ka&M*D8CI;y7Du_C^(Kz{L zMqQc_cK1PQC&a9t3`y1;DE!G^#Lj_ c0e8UR0u3r|vSz)O04p*ge9$a8!jFgk3(BQk2mk;8 diff --git a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs index fda56764e0..91e457ebb8 100644 --- a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs @@ -155,10 +155,9 @@ namespace Google.Protobuf.Reflection { "dGF0aW9uGAEgAygLMi0uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZENvZGVJ", "bmZvLkFubm90YXRpb24aTwoKQW5ub3RhdGlvbhIQCgRwYXRoGAEgAygFQgIQ", "ARITCgtzb3VyY2VfZmlsZRgCIAEoCRINCgViZWdpbhgDIAEoBRILCgNlbmQY", - "BCABKAVCjwEKE2NvbS5nb29nbGUucHJvdG9idWZCEERlc2NyaXB0b3JQcm90", - "b3NIAVo+Z2l0aHViLmNvbS9nb2xhbmcvcHJvdG9idWYvcHJvdG9jLWdlbi1n", - "by9kZXNjcmlwdG9yO2Rlc2NyaXB0b3L4AQGiAgNHUEKqAhpHb29nbGUuUHJv", - "dG9idWYuUmVmbGVjdGlvbg==")); + "BCABKAVCfgoTY29tLmdvb2dsZS5wcm90b2J1ZkIQRGVzY3JpcHRvclByb3Rv", + "c0gBWi1nb29nbGUuZ29sYW5nLm9yZy9wcm90b2J1Zi90eXBlcy9kZXNjcmlw", + "dG9ycGL4AQGiAgNHUEKqAhpHb29nbGUuUHJvdG9idWYuUmVmbGVjdGlvbg==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs index fc23560f8a..18520470d8 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs @@ -25,10 +25,10 @@ namespace Google.Protobuf.WellKnownTypes { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "Chlnb29nbGUvcHJvdG9idWYvYW55LnByb3RvEg9nb29nbGUucHJvdG9idWYi", - "JgoDQW55EhAKCHR5cGVfdXJsGAEgASgJEg0KBXZhbHVlGAIgASgMQm8KE2Nv", - "bS5nb29nbGUucHJvdG9idWZCCEFueVByb3RvUAFaJWdpdGh1Yi5jb20vZ29s", - "YW5nL3Byb3RvYnVmL3B0eXBlcy9hbnmiAgNHUEKqAh5Hb29nbGUuUHJvdG9i", - "dWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw==")); + "JgoDQW55EhAKCHR5cGVfdXJsGAEgASgJEg0KBXZhbHVlGAIgASgMQnYKE2Nv", + "bS5nb29nbGUucHJvdG9idWZCCEFueVByb3RvUAFaLGdvb2dsZS5nb2xhbmcu", + "b3JnL3Byb3RvYnVmL3R5cGVzL2tub3duL2FueXBiogIDR1BCqgIeR29vZ2xl", + "LlByb3RvYnVmLldlbGxLbm93blR5cGVzYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs index e8f1a50e29..4e9cf11c3c 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs @@ -37,10 +37,10 @@ namespace Google.Protobuf.WellKnownTypes { "ChFyZXNwb25zZV90eXBlX3VybBgEIAEoCRIaChJyZXNwb25zZV9zdHJlYW1p", "bmcYBSABKAgSKAoHb3B0aW9ucxgGIAMoCzIXLmdvb2dsZS5wcm90b2J1Zi5P", "cHRpb24SJwoGc3ludGF4GAcgASgOMhcuZ29vZ2xlLnByb3RvYnVmLlN5bnRh", - "eCIjCgVNaXhpbhIMCgRuYW1lGAEgASgJEgwKBHJvb3QYAiABKAlCdQoTY29t", - "Lmdvb2dsZS5wcm90b2J1ZkIIQXBpUHJvdG9QAVorZ29vZ2xlLmdvbGFuZy5v", - "cmcvZ2VucHJvdG8vcHJvdG9idWYvYXBpO2FwaaICA0dQQqoCHkdvb2dsZS5Q", - "cm90b2J1Zi5XZWxsS25vd25UeXBlc2IGcHJvdG8z")); + "eCIjCgVNaXhpbhIMCgRuYW1lGAEgASgJEgwKBHJvb3QYAiABKAlCdgoTY29t", + "Lmdvb2dsZS5wcm90b2J1ZkIIQXBpUHJvdG9QAVosZ29vZ2xlLmdvbGFuZy5v", + "cmcvcHJvdG9idWYvdHlwZXMva25vd24vYXBpcGKiAgNHUEKqAh5Hb29nbGUu", + "UHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.SourceContextReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TypeReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs index 8ef1b3778b..e686655697 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs @@ -26,10 +26,10 @@ namespace Google.Protobuf.WellKnownTypes { string.Concat( "Ch5nb29nbGUvcHJvdG9idWYvZHVyYXRpb24ucHJvdG8SD2dvb2dsZS5wcm90", "b2J1ZiIqCghEdXJhdGlvbhIPCgdzZWNvbmRzGAEgASgDEg0KBW5hbm9zGAIg", - "ASgFQnwKE2NvbS5nb29nbGUucHJvdG9idWZCDUR1cmF0aW9uUHJvdG9QAVoq", - "Z2l0aHViLmNvbS9nb2xhbmcvcHJvdG9idWYvcHR5cGVzL2R1cmF0aW9u+AEB", - "ogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxLbm93blR5cGVzYgZwcm90", - "bzM=")); + "ASgFQoMBChNjb20uZ29vZ2xlLnByb3RvYnVmQg1EdXJhdGlvblByb3RvUAFa", + "MWdvb2dsZS5nb2xhbmcub3JnL3Byb3RvYnVmL3R5cGVzL2tub3duL2R1cmF0", + "aW9ucGL4AQGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlw", + "ZXNiBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs index ff04940390..5e2d5a10df 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs @@ -25,10 +25,10 @@ namespace Google.Protobuf.WellKnownTypes { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "Chtnb29nbGUvcHJvdG9idWYvZW1wdHkucHJvdG8SD2dvb2dsZS5wcm90b2J1", - "ZiIHCgVFbXB0eUJ2ChNjb20uZ29vZ2xlLnByb3RvYnVmQgpFbXB0eVByb3Rv", - "UAFaJ2dpdGh1Yi5jb20vZ29sYW5nL3Byb3RvYnVmL3B0eXBlcy9lbXB0efgB", - "AaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IGcHJv", - "dG8z")); + "ZiIHCgVFbXB0eUJ9ChNjb20uZ29vZ2xlLnByb3RvYnVmQgpFbXB0eVByb3Rv", + "UAFaLmdvb2dsZS5nb2xhbmcub3JnL3Byb3RvYnVmL3R5cGVzL2tub3duL2Vt", + "cHR5cGL4AQGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlw", + "ZXNiBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs index 72c049f709..c92be3c73d 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs @@ -25,11 +25,10 @@ namespace Google.Protobuf.WellKnownTypes { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "CiBnb29nbGUvcHJvdG9idWYvZmllbGRfbWFzay5wcm90bxIPZ29vZ2xlLnBy", - "b3RvYnVmIhoKCUZpZWxkTWFzaxINCgVwYXRocxgBIAMoCUKMAQoTY29tLmdv", - "b2dsZS5wcm90b2J1ZkIORmllbGRNYXNrUHJvdG9QAVo5Z29vZ2xlLmdvbGFu", - "Zy5vcmcvZ2VucHJvdG8vcHJvdG9idWYvZmllbGRfbWFzaztmaWVsZF9tYXNr", - "+AEBogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxLbm93blR5cGVzYgZw", - "cm90bzM=")); + "b3RvYnVmIhoKCUZpZWxkTWFzaxINCgVwYXRocxgBIAMoCUKFAQoTY29tLmdv", + "b2dsZS5wcm90b2J1ZkIORmllbGRNYXNrUHJvdG9QAVoyZ29vZ2xlLmdvbGFu", + "Zy5vcmcvcHJvdG9idWYvdHlwZXMva25vd24vZmllbGRtYXNrcGL4AQGiAgNH", + "UEKqAh5Hb29nbGUuUHJvdG9idWYuV2VsbEtub3duVHlwZXNiBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs b/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs index dbfc8a99c8..7d46be1d93 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs @@ -26,10 +26,10 @@ namespace Google.Protobuf.WellKnownTypes { string.Concat( "CiRnb29nbGUvcHJvdG9idWYvc291cmNlX2NvbnRleHQucHJvdG8SD2dvb2ds", "ZS5wcm90b2J1ZiIiCg1Tb3VyY2VDb250ZXh0EhEKCWZpbGVfbmFtZRgBIAEo", - "CUKVAQoTY29tLmdvb2dsZS5wcm90b2J1ZkISU291cmNlQ29udGV4dFByb3Rv", - "UAFaQWdvb2dsZS5nb2xhbmcub3JnL2dlbnByb3RvL3Byb3RvYnVmL3NvdXJj", - "ZV9jb250ZXh0O3NvdXJjZV9jb250ZXh0ogIDR1BCqgIeR29vZ2xlLlByb3Rv", - "YnVmLldlbGxLbm93blR5cGVzYgZwcm90bzM=")); + "CUKKAQoTY29tLmdvb2dsZS5wcm90b2J1ZkISU291cmNlQ29udGV4dFByb3Rv", + "UAFaNmdvb2dsZS5nb2xhbmcub3JnL3Byb3RvYnVmL3R5cGVzL2tub3duL3Nv", + "dXJjZWNvbnRleHRwYqICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25v", + "d25UeXBlc2IGcHJvdG8z")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs index 2ba1b1cc5c..c7ca9270ab 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs @@ -35,10 +35,10 @@ namespace Google.Protobuf.WellKnownTypes { "ABIwCgpsaXN0X3ZhbHVlGAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLkxpc3RW", "YWx1ZUgAQgYKBGtpbmQiMwoJTGlzdFZhbHVlEiYKBnZhbHVlcxgBIAMoCzIW", "Lmdvb2dsZS5wcm90b2J1Zi5WYWx1ZSobCglOdWxsVmFsdWUSDgoKTlVMTF9W", - "QUxVRRAAQoEBChNjb20uZ29vZ2xlLnByb3RvYnVmQgtTdHJ1Y3RQcm90b1AB", - "WjFnaXRodWIuY29tL2dvbGFuZy9wcm90b2J1Zi9wdHlwZXMvc3RydWN0O3N0", - "cnVjdHBi+AEBogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxLbm93blR5", - "cGVzYgZwcm90bzM=")); + "QUxVRRAAQn8KE2NvbS5nb29nbGUucHJvdG9idWZCC1N0cnVjdFByb3RvUAFa", + "L2dvb2dsZS5nb2xhbmcub3JnL3Byb3RvYnVmL3R5cGVzL2tub3duL3N0cnVj", + "dHBi+AEBogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxLbm93blR5cGVz", + "YgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.WellKnownTypes.NullValue), }, null, new pbr::GeneratedClrTypeInfo[] { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs index 208cd26fe7..849162f048 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs @@ -26,10 +26,10 @@ namespace Google.Protobuf.WellKnownTypes { string.Concat( "Ch9nb29nbGUvcHJvdG9idWYvdGltZXN0YW1wLnByb3RvEg9nb29nbGUucHJv", "dG9idWYiKwoJVGltZXN0YW1wEg8KB3NlY29uZHMYASABKAMSDQoFbmFub3MY", - "AiABKAVCfgoTY29tLmdvb2dsZS5wcm90b2J1ZkIOVGltZXN0YW1wUHJvdG9Q", - "AVorZ2l0aHViLmNvbS9nb2xhbmcvcHJvdG9idWYvcHR5cGVzL3RpbWVzdGFt", - "cPgBAaICA0dQQqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IG", - "cHJvdG8z")); + "AiABKAVChQEKE2NvbS5nb29nbGUucHJvdG9idWZCDlRpbWVzdGFtcFByb3Rv", + "UAFaMmdvb2dsZS5nb2xhbmcub3JnL3Byb3RvYnVmL3R5cGVzL2tub3duL3Rp", + "bWVzdGFtcHBi+AEBogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxLbm93", + "blR5cGVzYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs index 453ff8dd6d..8e92707476 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs @@ -56,10 +56,10 @@ namespace Google.Protobuf.WellKnownTypes { "ASgFEigKB29wdGlvbnMYAyADKAsyFy5nb29nbGUucHJvdG9idWYuT3B0aW9u", "IjsKBk9wdGlvbhIMCgRuYW1lGAEgASgJEiMKBXZhbHVlGAIgASgLMhQuZ29v", "Z2xlLnByb3RvYnVmLkFueSouCgZTeW50YXgSEQoNU1lOVEFYX1BST1RPMhAA", - "EhEKDVNZTlRBWF9QUk9UTzMQAUJ9ChNjb20uZ29vZ2xlLnByb3RvYnVmQglU", - "eXBlUHJvdG9QAVovZ29vZ2xlLmdvbGFuZy5vcmcvZ2VucHJvdG8vcHJvdG9i", - "dWYvcHR5cGU7cHR5cGX4AQGiAgNHUEKqAh5Hb29nbGUuUHJvdG9idWYuV2Vs", - "bEtub3duVHlwZXNiBnByb3RvMw==")); + "EhEKDVNZTlRBWF9QUk9UTzMQAUJ7ChNjb20uZ29vZ2xlLnByb3RvYnVmQglU", + "eXBlUHJvdG9QAVotZ29vZ2xlLmdvbGFuZy5vcmcvcHJvdG9idWYvdHlwZXMv", + "a25vd24vdHlwZXBi+AEBogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxL", + "bm93blR5cGVzYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.SourceContextReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.WellKnownTypes.Syntax), }, null, new pbr::GeneratedClrTypeInfo[] { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs index fa3458cf3d..1ccbc2a9c8 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs @@ -30,10 +30,11 @@ namespace Google.Protobuf.WellKnownTypes { "KAMiHAoLVUludDY0VmFsdWUSDQoFdmFsdWUYASABKAQiGwoKSW50MzJWYWx1", "ZRINCgV2YWx1ZRgBIAEoBSIcCgtVSW50MzJWYWx1ZRINCgV2YWx1ZRgBIAEo", "DSIaCglCb29sVmFsdWUSDQoFdmFsdWUYASABKAgiHAoLU3RyaW5nVmFsdWUS", - "DQoFdmFsdWUYASABKAkiGwoKQnl0ZXNWYWx1ZRINCgV2YWx1ZRgBIAEoDEJ8", - "ChNjb20uZ29vZ2xlLnByb3RvYnVmQg1XcmFwcGVyc1Byb3RvUAFaKmdpdGh1", - "Yi5jb20vZ29sYW5nL3Byb3RvYnVmL3B0eXBlcy93cmFwcGVyc/gBAaICA0dQ", - "QqoCHkdvb2dsZS5Qcm90b2J1Zi5XZWxsS25vd25UeXBlc2IGcHJvdG8z")); + "DQoFdmFsdWUYASABKAkiGwoKQnl0ZXNWYWx1ZRINCgV2YWx1ZRgBIAEoDEKD", + "AQoTY29tLmdvb2dsZS5wcm90b2J1ZkINV3JhcHBlcnNQcm90b1ABWjFnb29n", + "bGUuZ29sYW5nLm9yZy9wcm90b2J1Zi90eXBlcy9rbm93bi93cmFwcGVyc3Bi", + "+AEBogIDR1BCqgIeR29vZ2xlLlByb3RvYnVmLldlbGxLbm93blR5cGVzYgZw", + "cm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { diff --git a/python/google/protobuf/internal/json_format_test.py b/python/google/protobuf/internal/json_format_test.py index 68aa21c43f..6a60348b1c 100755 --- a/python/google/protobuf/internal/json_format_test.py +++ b/python/google/protobuf/internal/json_format_test.py @@ -636,6 +636,20 @@ class JsonFormatTest(JsonFormatBase): parsed_message = json_format_proto3_pb2.TestListValue() self.CheckParseBack(message, parsed_message) + def testNullValue(self): + message = json_format_proto3_pb2.TestOneof() + message.oneof_null_value = 0 + self.assertEqual(json_format.MessageToJson(message), + '{\n "oneofNullValue": null\n}') + parsed_message = json_format_proto3_pb2.TestOneof() + self.CheckParseBack(message, parsed_message) + # Check old format is also accepted + new_message = json_format_proto3_pb2.TestOneof() + json_format.Parse('{\n "oneofNullValue": "NULL_VALUE"\n}', + new_message) + self.assertEqual(json_format.MessageToJson(new_message), + '{\n "oneofNullValue": null\n}') + def testAnyMessage(self): message = json_format_proto3_pb2.TestAny() value1 = json_format_proto3_pb2.MessageType() diff --git a/python/google/protobuf/json_format.py b/python/google/protobuf/json_format.py index 4d76d021a6..c8f5602f36 100644 --- a/python/google/protobuf/json_format.py +++ b/python/google/protobuf/json_format.py @@ -286,6 +286,8 @@ class _Printer(object): elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM: if self.use_integers_for_enums: return value + if field.enum_type.full_name == 'google.protobuf.NullValue': + return None enum_value = field.enum_type.values_by_number.get(value, None) if enum_value is not None: return enum_value.name @@ -544,6 +546,9 @@ class _Parser(object): and field.message_type.full_name == 'google.protobuf.Value'): sub_message = getattr(message, field.name) sub_message.null_value = 0 + elif (field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM + and field.enum_type.full_name == 'google.protobuf.NullValue'): + setattr(message, field.name, 0) else: message.ClearField(field.name) continue diff --git a/src/google/protobuf/any.cc b/src/google/protobuf/any.cc index a79214b750..a9876fc4ed 100644 --- a/src/google/protobuf/any.cc +++ b/src/google/protobuf/any.cc @@ -46,7 +46,7 @@ void AnyMetadata::PackFrom(const Message& message) { } void AnyMetadata::PackFrom(const Message& message, - const std::string& type_url_prefix) { + StringPiece type_url_prefix) { type_url_->SetNoArena( &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString(), GetTypeUrl(message.GetDescriptor()->full_name(), type_url_prefix)); diff --git a/src/google/protobuf/any.h b/src/google/protobuf/any.h index 59dd50cb21..16a68ca687 100644 --- a/src/google/protobuf/any.h +++ b/src/google/protobuf/any.h @@ -82,7 +82,7 @@ class PROTOBUF_EXPORT AnyMetadata { InternalPackFrom(message, type_url_prefix, T::FullMessageName()); } - void PackFrom(const Message& message, const std::string& type_url_prefix); + void PackFrom(const Message& message, StringPiece type_url_prefix); // Unpacks the payload into the given message. Returns false if the message's // type doesn't match the type specified in the type URL (i.e., the full @@ -124,14 +124,14 @@ class PROTOBUF_EXPORT AnyMetadata { // // NOTE: this function is available publicly as: // google::protobuf::Any() // static method on the generated message type. -bool ParseAnyTypeUrl(const std::string& type_url, std::string* full_type_name); +bool ParseAnyTypeUrl(StringPiece type_url, std::string* full_type_name); // Get the proto type name and prefix from Any::type_url value. For example, // passing "type.googleapis.com/rpc.QueryOrigin" will return // "type.googleapis.com/" in *url_prefix and "rpc.QueryOrigin" in // *full_type_name. Returns false if the type_url does not have a "/" in the // type url separating the full type name. -bool ParseAnyTypeUrl(const std::string& type_url, std::string* url_prefix, +bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix, std::string* full_type_name); // See if message is of type google.protobuf.Any, if so, return the descriptors diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc index 1eba999eba..1993555f14 100644 --- a/src/google/protobuf/any.pb.cc +++ b/src/google/protobuf/any.pb.cc @@ -58,10 +58,10 @@ static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = const char descriptor_table_protodef_google_2fprotobuf_2fany_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = "\n\031google/protobuf/any.proto\022\017google.prot" "obuf\"&\n\003Any\022\020\n\010type_url\030\001 \001(\t\022\r\n\005value\030\002" - " \001(\014Bo\n\023com.google.protobufB\010AnyProtoP\001Z" - "%github.com/golang/protobuf/ptypes/any\242\002" - "\003GPB\252\002\036Google.Protobuf.WellKnownTypesb\006p" - "roto3" + " \001(\014Bv\n\023com.google.protobufB\010AnyProtoP\001Z" + ",google.golang.org/protobuf/types/known/" + "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] = { }; @@ -70,7 +70,7 @@ static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_goo }; 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", 205, + 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, 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, diff --git a/src/google/protobuf/any.proto b/src/google/protobuf/any.proto index c9be854167..066cf60dd5 100644 --- a/src/google/protobuf/any.proto +++ b/src/google/protobuf/any.proto @@ -33,7 +33,7 @@ syntax = "proto3"; package google.protobuf; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; -option go_package = "github.com/golang/protobuf/ptypes/any"; +option go_package = "google.golang.org/protobuf/types/known/anypb"; option java_package = "com.google.protobuf"; option java_outer_classname = "AnyProto"; option java_multiple_files = true; diff --git a/src/google/protobuf/any_lite.cc b/src/google/protobuf/any_lite.cc index 7839381337..3badb411f1 100644 --- a/src/google/protobuf/any_lite.cc +++ b/src/google/protobuf/any_lite.cc @@ -100,20 +100,20 @@ bool AnyMetadata::InternalIs(StringPiece type_name) const { HasSuffixString(type_url, type_name); } -bool ParseAnyTypeUrl(const std::string& type_url, std::string* url_prefix, +bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix, std::string* full_type_name) { size_t pos = type_url.find_last_of("/"); if (pos == std::string::npos || pos + 1 == type_url.size()) { return false; } if (url_prefix) { - *url_prefix = type_url.substr(0, pos + 1); + *url_prefix = std::string(type_url.substr(0, pos + 1)); } - *full_type_name = type_url.substr(pos + 1); + *full_type_name = std::string(type_url.substr(pos + 1)); return true; } -bool ParseAnyTypeUrl(const std::string& type_url, std::string* full_type_name) { +bool ParseAnyTypeUrl(StringPiece type_url, std::string* full_type_name) { return ParseAnyTypeUrl(type_url, nullptr, full_type_name); } diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc index 816df1201c..6ae678a120 100644 --- a/src/google/protobuf/api.pb.cc +++ b/src/google/protobuf/api.pb.cc @@ -144,10 +144,10 @@ const char descriptor_table_protodef_google_2fprotobuf_2fapi_2eproto[] PROTOBUF_ "esponse_streaming\030\005 \001(\010\022(\n\007options\030\006 \003(\013" "2\027.google.protobuf.Option\022\'\n\006syntax\030\007 \001(" "\0162\027.google.protobuf.Syntax\"#\n\005Mixin\022\014\n\004n" - "ame\030\001 \001(\t\022\014\n\004root\030\002 \001(\tBu\n\023com.google.pr" - "otobufB\010ApiProtoP\001Z+google.golang.org/ge" - "nproto/protobuf/api;api\242\002\003GPB\252\002\036Google.P" - "rotobuf.WellKnownTypesb\006proto3" + "ame\030\001 \001(\t\022\014\n\004root\030\002 \001(\tBv\n\023com.google.pr" + "otobufB\010ApiProtoP\001Z,google.golang.org/pr" + "otobuf/types/known/apipb\242\002\003GPB\252\002\036Google." + "Protobuf.WellKnownTypesb\006proto3" ; static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fapi_2eproto_deps[2] = { &::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto, @@ -160,7 +160,7 @@ static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_goo }; 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", 750, + 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, 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, diff --git a/src/google/protobuf/api.proto b/src/google/protobuf/api.proto index f37ee2fa46..8dd9457426 100644 --- a/src/google/protobuf/api.proto +++ b/src/google/protobuf/api.proto @@ -40,7 +40,7 @@ option java_package = "com.google.protobuf"; option java_outer_classname = "ApiProto"; option java_multiple_files = true; option objc_class_prefix = "GPB"; -option go_package = "google.golang.org/genproto/protobuf/api;api"; +option go_package = "google.golang.org/protobuf/types/known/apipb"; // Api is a light-weight descriptor for an API Interface. // @@ -52,7 +52,6 @@ option go_package = "google.golang.org/genproto/protobuf/api;api"; // this message itself. See https://cloud.google.com/apis/design/glossary for // detailed terminology. message Api { - // The fully qualified name of this interface, including package name // followed by the interface's simple name. string name = 1; @@ -99,7 +98,6 @@ message Api { // Method represents a method of an API interface. message Method { - // The simple name of this method. string name = 1; diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index 61a239574e..eed07dc746 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -631,16 +631,7 @@ MessageGenerator::MessageGenerator( MessageGenerator::~MessageGenerator() = default; size_t MessageGenerator::HasBitsSize() const { - size_t sizeof_has_bits = (max_has_bit_index_ + 31) / 32 * 4; - if (sizeof_has_bits == 0) { - // Zero-size arrays aren't technically allowed, and MSVC in particular - // doesn't like them. We still need to declare these arrays to make - // other code compile. Since this is an uncommon case, we'll just declare - // them with size 1 and waste some space. Oh well. - sizeof_has_bits = 4; - } - - return sizeof_has_bits; + return (max_has_bit_index_ + 31) / 32; } int MessageGenerator::HasBitIndex(const FieldDescriptor* field) const { @@ -1515,10 +1506,9 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { const size_t sizeof_has_bits = HasBitsSize(); const std::string has_bits_decl = - sizeof_has_bits == 0 - ? "" - : StrCat("::$proto_ns$::internal::HasBits<", - sizeof_has_bits / 4, "> _has_bits_;\n"); + sizeof_has_bits == 0 ? "" + : StrCat("::$proto_ns$::internal::HasBits<", + sizeof_has_bits, "> _has_bits_;\n"); // To minimize padding, data members are divided into three sections: // (1) members assumed to align to 8 bytes @@ -3065,7 +3055,7 @@ void MessageGenerator::GenerateSwap(io::Printer* printer) { "metadata_);\n"); if (!has_bit_indices_.empty()) { - for (int i = 0; i < HasBitsSize() / 4; ++i) { + for (int i = 0; i < HasBitsSize(); ++i) { format("swap(_has_bits_[$1$], other->_has_bits_[$1$]);\n", i); } } diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index 6739215d89..c2e430acda 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -180,10 +180,9 @@ const char descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2epro "atorResponse.File\032>\n\004File\022\014\n\004name\030\001 \001(\t\022" "\027\n\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(" "\t\"8\n\007Feature\022\020\n\014FEATURE_NONE\020\000\022\033\n\027FEATUR" - "E_PROTO3_OPTIONAL\020\001Bg\n\034com.google.protob" - "uf.compilerB\014PluginProtosZ9github.com/go" - "lang/protobuf/protoc-gen-go/plugin;plugi" - "n_go" + "E_PROTO3_OPTIONAL\020\001BW\n\034com.google.protob" + "uf.compilerB\014PluginProtosZ)google.golang" + ".org/protobuf/types/pluginpb" ; static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps[1] = { &::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, @@ -196,7 +195,7 @@ static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_goo }; 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", 724, + false, false, descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto, "google/protobuf/compiler/plugin.proto", 708, &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, 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, diff --git a/src/google/protobuf/compiler/plugin.proto b/src/google/protobuf/compiler/plugin.proto index 492b896c5b..189db19429 100644 --- a/src/google/protobuf/compiler/plugin.proto +++ b/src/google/protobuf/compiler/plugin.proto @@ -50,7 +50,7 @@ package google.protobuf.compiler; option java_package = "com.google.protobuf.compiler"; option java_outer_classname = "PluginProtos"; -option go_package = "github.com/golang/protobuf/protoc-gen-go/plugin;plugin_go"; +option go_package = "google.golang.org/protobuf/types/pluginpb"; import "google/protobuf/descriptor.proto"; diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index 471351c406..c4e26b6c8c 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -1156,11 +1156,10 @@ const char descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto[] PR "tation\030\001 \003(\0132-.google.protobuf.Generated" "CodeInfo.Annotation\032O\n\nAnnotation\022\020\n\004pat" "h\030\001 \003(\005B\002\020\001\022\023\n\013source_file\030\002 \001(\t\022\r\n\005begi" - "n\030\003 \001(\005\022\013\n\003end\030\004 \001(\005B\217\001\n\023com.google.prot" - "obufB\020DescriptorProtosH\001Z>github.com/gol" - "ang/protobuf/protoc-gen-go/descriptor;de" - "scriptor\370\001\001\242\002\003GPB\252\002\032Google.Protobuf.Refl" - "ection" + "n\030\003 \001(\005\022\013\n\003end\030\004 \001(\005B~\n\023com.google.proto" + "bufB\020DescriptorProtosH\001Z-google.golang.o" + "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] = { }; @@ -1195,7 +1194,7 @@ static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_goo }; 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", 6046, + 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, 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, diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index d29fdec5e5..9f0ce6cde0 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -41,7 +41,7 @@ syntax = "proto2"; package google.protobuf; -option go_package = "github.com/golang/protobuf/protoc-gen-go/descriptor;descriptor"; +option go_package = "google.golang.org/protobuf/types/descriptorpb"; option java_package = "com.google.protobuf"; option java_outer_classname = "DescriptorProtos"; option csharp_namespace = "Google.Protobuf.Reflection"; diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc index 26826620a9..b8bceca6c6 100644 --- a/src/google/protobuf/duration.pb.cc +++ b/src/google/protobuf/duration.pb.cc @@ -58,10 +58,10 @@ static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = const char descriptor_table_protodef_google_2fprotobuf_2fduration_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = "\n\036google/protobuf/duration.proto\022\017google" ".protobuf\"*\n\010Duration\022\017\n\007seconds\030\001 \001(\003\022\r" - "\n\005nanos\030\002 \001(\005B|\n\023com.google.protobufB\rDu" - "rationProtoP\001Z*github.com/golang/protobu" - "f/ptypes/duration\370\001\001\242\002\003GPB\252\002\036Google.Prot" - "obuf.WellKnownTypesb\006proto3" + "\n\005nanos\030\002 \001(\005B\203\001\n\023com.google.protobufB\rD" + "urationProtoP\001Z1google.golang.org/protob" + "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] = { }; @@ -70,7 +70,7 @@ static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_goo }; 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", 227, + 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, 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, diff --git a/src/google/protobuf/duration.proto b/src/google/protobuf/duration.proto index 99cb102c35..81c3e369fd 100644 --- a/src/google/protobuf/duration.proto +++ b/src/google/protobuf/duration.proto @@ -34,7 +34,7 @@ package google.protobuf; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option cc_enable_arenas = true; -option go_package = "github.com/golang/protobuf/ptypes/duration"; +option go_package = "google.golang.org/protobuf/types/known/durationpb"; option java_package = "com.google.protobuf"; option java_outer_classname = "DurationProto"; option java_multiple_files = true; diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc index 855db18b01..27f801fd9d 100644 --- a/src/google/protobuf/empty.pb.cc +++ b/src/google/protobuf/empty.pb.cc @@ -55,10 +55,10 @@ static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = const char descriptor_table_protodef_google_2fprotobuf_2fempty_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = "\n\033google/protobuf/empty.proto\022\017google.pr" - "otobuf\"\007\n\005EmptyBv\n\023com.google.protobufB\n" - "EmptyProtoP\001Z\'github.com/golang/protobuf" - "/ptypes/empty\370\001\001\242\002\003GPB\252\002\036Google.Protobuf" - ".WellKnownTypesb\006proto3" + "otobuf\"\007\n\005EmptyB}\n\023com.google.protobufB\n" + "EmptyProtoP\001Z.google.golang.org/protobuf" + "/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] = { }; @@ -67,7 +67,7 @@ static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_goo }; 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", 183, + 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, 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, diff --git a/src/google/protobuf/empty.proto b/src/google/protobuf/empty.proto index 03cacd2330..5f992de94a 100644 --- a/src/google/protobuf/empty.proto +++ b/src/google/protobuf/empty.proto @@ -33,7 +33,7 @@ syntax = "proto3"; package google.protobuf; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; -option go_package = "github.com/golang/protobuf/ptypes/empty"; +option go_package = "google.golang.org/protobuf/types/known/emptypb"; option java_package = "com.google.protobuf"; option java_outer_classname = "EmptyProto"; option java_multiple_files = true; diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc index 42e077f3cf..e735b3ac66 100644 --- a/src/google/protobuf/field_mask.pb.cc +++ b/src/google/protobuf/field_mask.pb.cc @@ -57,10 +57,10 @@ static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = const char descriptor_table_protodef_google_2fprotobuf_2ffield_5fmask_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = "\n google/protobuf/field_mask.proto\022\017goog" "le.protobuf\"\032\n\tFieldMask\022\r\n\005paths\030\001 \003(\tB" - "\214\001\n\023com.google.protobufB\016FieldMaskProtoP" - "\001Z9google.golang.org/genproto/protobuf/f" - "ield_mask;field_mask\370\001\001\242\002\003GPB\252\002\036Google.P" - "rotobuf.WellKnownTypesb\006proto3" + "\205\001\n\023com.google.protobufB\016FieldMaskProtoP" + "\001Z2google.golang.org/protobuf/types/know" + "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] = { }; @@ -69,7 +69,7 @@ static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_goo }; 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", 230, + 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, 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, diff --git a/src/google/protobuf/field_mask.proto b/src/google/protobuf/field_mask.proto index baac8744cb..6b5104f188 100644 --- a/src/google/protobuf/field_mask.proto +++ b/src/google/protobuf/field_mask.proto @@ -37,7 +37,7 @@ option java_package = "com.google.protobuf"; option java_outer_classname = "FieldMaskProto"; option java_multiple_files = true; option objc_class_prefix = "GPB"; -option go_package = "google.golang.org/genproto/protobuf/field_mask;field_mask"; +option go_package = "google.golang.org/protobuf/types/known/fieldmaskpb"; option cc_enable_arenas = true; // `FieldMask` represents a set of symbolic field paths, for example: diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc index 9f09bec137..059456f287 100644 --- a/src/google/protobuf/source_context.pb.cc +++ b/src/google/protobuf/source_context.pb.cc @@ -57,11 +57,10 @@ static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = const char descriptor_table_protodef_google_2fprotobuf_2fsource_5fcontext_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = "\n$google/protobuf/source_context.proto\022\017" "google.protobuf\"\"\n\rSourceContext\022\021\n\tfile" - "_name\030\001 \001(\tB\225\001\n\023com.google.protobufB\022Sou" - "rceContextProtoP\001ZAgoogle.golang.org/gen" - "proto/protobuf/source_context;source_con" - "text\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTy" - "pesb\006proto3" + "_name\030\001 \001(\tB\212\001\n\023com.google.protobufB\022Sou" + "rceContextProtoP\001Z6google.golang.org/pro" + "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] = { }; @@ -70,7 +69,7 @@ static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_goo }; 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", 251, + 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, 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, diff --git a/src/google/protobuf/source_context.proto b/src/google/protobuf/source_context.proto index f3b2c96681..06bfc43a78 100644 --- a/src/google/protobuf/source_context.proto +++ b/src/google/protobuf/source_context.proto @@ -37,7 +37,7 @@ option java_package = "com.google.protobuf"; option java_outer_classname = "SourceContextProto"; option java_multiple_files = true; option objc_class_prefix = "GPB"; -option go_package = "google.golang.org/genproto/protobuf/source_context;source_context"; +option go_package = "google.golang.org/protobuf/types/known/sourcecontextpb"; // `SourceContext` represents information about the source of a // protobuf element, like the file in which it is defined. diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc index 027fef6f55..54c928342b 100644 --- a/src/google/protobuf/struct.pb.cc +++ b/src/google/protobuf/struct.pb.cc @@ -136,11 +136,10 @@ const char descriptor_table_protodef_google_2fprotobuf_2fstruct_2eproto[] PROTOB "\000\0220\n\nlist_value\030\006 \001(\0132\032.google.protobuf." "ListValueH\000B\006\n\004kind\"3\n\tListValue\022&\n\006valu" "es\030\001 \003(\0132\026.google.protobuf.Value*\033\n\tNull" - "Value\022\016\n\nNULL_VALUE\020\000B\201\001\n\023com.google.pro" - "tobufB\013StructProtoP\001Z1github.com/golang/" - "protobuf/ptypes/struct;structpb\370\001\001\242\002\003GPB" - "\252\002\036Google.Protobuf.WellKnownTypesb\006proto" - "3" + "Value\022\016\n\nNULL_VALUE\020\000B\177\n\023com.google.prot" + "obufB\013StructProtoP\001Z/google.golang.org/p" + "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] = { }; @@ -149,7 +148,7 @@ static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_goo }; 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", 641, + 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, 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, diff --git a/src/google/protobuf/struct.proto b/src/google/protobuf/struct.proto index ed990e31d9..545215c252 100644 --- a/src/google/protobuf/struct.proto +++ b/src/google/protobuf/struct.proto @@ -34,7 +34,7 @@ package google.protobuf; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option cc_enable_arenas = true; -option go_package = "github.com/golang/protobuf/ptypes/struct;structpb"; +option go_package = "google.golang.org/protobuf/types/known/structpb"; option java_package = "com.google.protobuf"; option java_outer_classname = "StructProto"; option java_multiple_files = true; diff --git a/src/google/protobuf/test_messages_proto3.proto b/src/google/protobuf/test_messages_proto3.proto index a10f44d946..4e409dc900 100644 --- a/src/google/protobuf/test_messages_proto3.proto +++ b/src/google/protobuf/test_messages_proto3.proto @@ -203,6 +203,7 @@ message TestAllTypesProto3 { float oneof_float = 117; double oneof_double = 118; NestedEnum oneof_enum = 119; + google.protobuf.NullValue oneof_null_value = 120; } // Well-known types @@ -232,6 +233,7 @@ message TestAllTypesProto3 { google.protobuf.Struct optional_struct = 304; google.protobuf.Any optional_any = 305; google.protobuf.Value optional_value = 306; + google.protobuf.NullValue optional_null_value = 307; repeated google.protobuf.Duration repeated_duration = 311; repeated google.protobuf.Timestamp repeated_timestamp = 312; diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc index 8b2721022d..1458bc000a 100644 --- a/src/google/protobuf/timestamp.pb.cc +++ b/src/google/protobuf/timestamp.pb.cc @@ -58,10 +58,10 @@ static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = const char descriptor_table_protodef_google_2fprotobuf_2ftimestamp_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = "\n\037google/protobuf/timestamp.proto\022\017googl" "e.protobuf\"+\n\tTimestamp\022\017\n\007seconds\030\001 \001(\003" - "\022\r\n\005nanos\030\002 \001(\005B~\n\023com.google.protobufB\016" - "TimestampProtoP\001Z+github.com/golang/prot" - "obuf/ptypes/timestamp\370\001\001\242\002\003GPB\252\002\036Google." - "Protobuf.WellKnownTypesb\006proto3" + "\022\r\n\005nanos\030\002 \001(\005B\205\001\n\023com.google.protobufB" + "\016TimestampProtoP\001Z2google.golang.org/pro" + "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] = { }; @@ -70,7 +70,7 @@ static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_goo }; 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", 231, + 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, 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, diff --git a/src/google/protobuf/timestamp.proto b/src/google/protobuf/timestamp.proto index cd357864a9..a343d81928 100644 --- a/src/google/protobuf/timestamp.proto +++ b/src/google/protobuf/timestamp.proto @@ -34,7 +34,7 @@ package google.protobuf; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option cc_enable_arenas = true; -option go_package = "github.com/golang/protobuf/ptypes/timestamp"; +option go_package = "google.golang.org/protobuf/types/known/timestamppb"; option java_package = "com.google.protobuf"; option java_outer_classname = "TimestampProto"; option java_multiple_files = true; diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc index 8da70ecc52..8da9559110 100644 --- a/src/google/protobuf/type.pb.cc +++ b/src/google/protobuf/type.pb.cc @@ -230,10 +230,10 @@ const char descriptor_table_protodef_google_2fprotobuf_2ftype_2eproto[] PROTOBUF "\003 \003(\0132\027.google.protobuf.Option\";\n\006Option" "\022\014\n\004name\030\001 \001(\t\022#\n\005value\030\002 \001(\0132\024.google.p" "rotobuf.Any*.\n\006Syntax\022\021\n\rSYNTAX_PROTO2\020\000" - "\022\021\n\rSYNTAX_PROTO3\020\001B}\n\023com.google.protob" - "ufB\tTypeProtoP\001Z/google.golang.org/genpr" - "oto/protobuf/ptype;ptype\370\001\001\242\002\003GPB\252\002\036Goog" - "le.Protobuf.WellKnownTypesb\006proto3" + "\022\021\n\rSYNTAX_PROTO3\020\001B{\n\023com.google.protob" + "ufB\tTypeProtoP\001Z-google.golang.org/proto" + "buf/types/known/typepb\370\001\001\242\002\003GPB\252\002\036Google" + ".Protobuf.WellKnownTypesb\006proto3" ; static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2ftype_2eproto_deps[2] = { &::descriptor_table_google_2fprotobuf_2fany_2eproto, @@ -248,7 +248,7 @@ static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_goo }; 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", 1594, + 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, 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, diff --git a/src/google/protobuf/type.proto b/src/google/protobuf/type.proto index e4b1d3a4ab..d3f6a68b83 100644 --- a/src/google/protobuf/type.proto +++ b/src/google/protobuf/type.proto @@ -41,7 +41,7 @@ option java_package = "com.google.protobuf"; option java_outer_classname = "TypeProto"; option java_multiple_files = true; option objc_class_prefix = "GPB"; -option go_package = "google.golang.org/genproto/protobuf/ptype;ptype"; +option go_package = "google.golang.org/protobuf/types/known/typepb"; // A protocol buffer message type. message Type { @@ -113,7 +113,7 @@ message Field { CARDINALITY_REQUIRED = 2; // For repeated fields. CARDINALITY_REPEATED = 3; - }; + } // The field type. Kind kind = 1; diff --git a/src/google/protobuf/util/json_format_proto3.proto b/src/google/protobuf/util/json_format_proto3.proto index b62487a578..0eec9da319 100644 --- a/src/google/protobuf/util/json_format_proto3.proto +++ b/src/google/protobuf/util/json_format_proto3.proto @@ -91,6 +91,7 @@ message TestOneof { bytes oneof_bytes_value = 3; EnumType oneof_enum_value = 4; MessageType oneof_message_value = 5; + google.protobuf.NullValue oneof_null_value = 6; } } diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc index be039b420a..e9f53a53d1 100644 --- a/src/google/protobuf/wrappers.pb.cc +++ b/src/google/protobuf/wrappers.pb.cc @@ -270,11 +270,11 @@ const char descriptor_table_protodef_google_2fprotobuf_2fwrappers_2eproto[] PROT "e\030\001 \001(\004\"\033\n\nInt32Value\022\r\n\005value\030\001 \001(\005\"\034\n\013" "UInt32Value\022\r\n\005value\030\001 \001(\r\"\032\n\tBoolValue\022" "\r\n\005value\030\001 \001(\010\"\034\n\013StringValue\022\r\n\005value\030\001" - " \001(\t\"\033\n\nBytesValue\022\r\n\005value\030\001 \001(\014B|\n\023com" - ".google.protobufB\rWrappersProtoP\001Z*githu" - "b.com/golang/protobuf/ptypes/wrappers\370\001\001" - "\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypesb" - "\006proto3" + " \001(\t\"\033\n\nBytesValue\022\r\n\005value\030\001 \001(\014B\203\001\n\023co" + "m.google.protobufB\rWrappersProtoP\001Z1goog" + "le.golang.org/protobuf/types/known/wrapp" + "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] = { }; @@ -291,7 +291,7 @@ static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_goo }; 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", 447, + 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, 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, diff --git a/src/google/protobuf/wrappers.proto b/src/google/protobuf/wrappers.proto index 9ee41e384a..d49dd53c8d 100644 --- a/src/google/protobuf/wrappers.proto +++ b/src/google/protobuf/wrappers.proto @@ -44,7 +44,7 @@ package google.protobuf; option csharp_namespace = "Google.Protobuf.WellKnownTypes"; option cc_enable_arenas = true; -option go_package = "github.com/golang/protobuf/ptypes/wrappers"; +option go_package = "google.golang.org/protobuf/types/known/wrapperspb"; option java_package = "com.google.protobuf"; option java_outer_classname = "WrappersProto"; option java_multiple_files = true; From 25755efc4f4a4e9d6efb34a100df0a4860dca695 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Mon, 6 Jul 2020 13:54:50 -0700 Subject: [PATCH 2/8] Sync from Piper @319848517 PROTOBUF_SYNC_PIPER --- BUILD | 7 +- README.md | 2 +- .../CodedOutputStreamTest.cs | 64 +- .../Google.Protobuf.Test/FieldCodecTest.cs | 22 +- csharp/install_dotnet_sdk.ps1 | 12 +- csharp/protos/unittest_issues.proto | 15 +- csharp/src/AddressBook/Addressbook.cs | 65 + .../BenchmarkMessage1Proto3.cs | 267 + .../Google.Protobuf.Benchmarks/Benchmarks.cs | 22 + .../Google.Protobuf.Benchmarks.csproj | 6 +- .../ParseMessagesBenchmark.cs | 6 +- .../ParseRawPrimitivesBenchmark.cs | 43 +- .../WrapperBenchmarkMessages.cs | 801 ++ .../WriteMessagesBenchmark.cs | 198 + .../WriteRawPrimitivesBenchmark.cs | 519 ++ .../Conformance.cs | 125 + .../MapUnittestProto3.cs | 132 + .../TestMessagesProto2.cs | 446 + .../TestMessagesProto3.cs | 394 + .../Unittest.cs | 2557 +++++- .../UnittestCustomOptionsProto3.cs | 335 + .../UnittestImport.cs | 17 + .../UnittestImportProto3.cs | 17 + .../UnittestImportPublic.cs | 17 + .../UnittestImportPublicProto3.cs | 17 + .../UnittestIssue6936B.cs | 13 + .../UnittestIssue6936C.cs | 17 + .../UnittestIssues.cs | 734 +- .../UnittestProto3.cs | 833 +- .../UnittestProto3Optional.cs | 114 + .../UnittestSelfreferentialOptions.cs | 24 + .../UnittestWellKnownTypes.cs | 218 + .../Buffers/ArrayBufferWriter.cs | 225 + .../CodedOutputStreamTest.cs | 186 +- .../Google.Protobuf.Test/ExtensionSetTest.cs | 2 + .../Google.Protobuf.Test/FieldCodecTest.cs | 24 +- .../GeneratedMessageTest.Proto2.cs | 6 + .../GeneratedMessageTest.cs | 14 +- .../Google.Protobuf.Test/JsonFormatterTest.cs | 22 + .../Google.Protobuf.Test/JsonParserTest.cs | 38 + .../LegacyGeneratedCodeTest.cs | 101 +- .../MessageParsingHelpers.cs | 42 + .../WellKnownTypes/WrappersTest.cs | 10 + csharp/src/Google.Protobuf.Test/testprotos.pb | Bin 337912 -> 338456 bytes .../CodedOutputStream.ComputeSize.cs | 6 +- .../src/Google.Protobuf/CodedOutputStream.cs | 415 +- .../Google.Protobuf/Collections/MapField.cs | 35 +- .../Collections/RepeatedField.cs | 36 +- csharp/src/Google.Protobuf/ExtensionSet.cs | 21 +- csharp/src/Google.Protobuf/ExtensionValue.cs | 19 +- csharp/src/Google.Protobuf/FieldCodec.cs | 90 +- csharp/src/Google.Protobuf/IBufferMessage.cs | 8 +- csharp/src/Google.Protobuf/JsonFormatter.cs | 2 +- csharp/src/Google.Protobuf/JsonParser.cs | 17 +- .../src/Google.Protobuf/MessageExtensions.cs | 36 +- .../Google.Protobuf/ParserInternalState.cs | 2 +- .../src/Google.Protobuf/ParsingPrimitives.cs | 6 +- .../Google.Protobuf/Reflection/Descriptor.cs | 794 +- csharp/src/Google.Protobuf/UnknownField.cs | 6 +- csharp/src/Google.Protobuf/UnknownFieldSet.cs | 19 +- .../src/Google.Protobuf/WellKnownTypes/Any.cs | 28 +- .../src/Google.Protobuf/WellKnownTypes/Api.cs | 91 + .../WellKnownTypes/Duration.cs | 21 + .../Google.Protobuf/WellKnownTypes/Empty.cs | 13 + .../WellKnownTypes/FieldMask.cs | 14 + .../WellKnownTypes/SourceContext.cs | 17 + .../Google.Protobuf/WellKnownTypes/Struct.cs | 65 + .../WellKnownTypes/Timestamp.cs | 21 + .../Google.Protobuf/WellKnownTypes/Type.cs | 148 + .../WellKnownTypes/Wrappers.cs | 153 + .../src/Google.Protobuf/WriteBufferHelper.cs | 166 + csharp/src/Google.Protobuf/WriteContext.cs | 371 + .../Google.Protobuf/WriterInternalState.cs | 62 + .../src/Google.Protobuf/WritingPrimitives.cs | 628 ++ .../WritingPrimitivesMessages.cs | 112 + docs/third_party.md | 1 + editors/protobuf-mode.el | 6 +- .../linux/dockerfile/test/csharp/Dockerfile | 2 +- objectivec/GPBAny.pbobjc.h | 7 +- php/ext/google/protobuf2/arena.c | 95 + php/ext/google/protobuf2/arena.h | 47 + php/ext/google/protobuf2/array.c | 602 ++ php/ext/google/protobuf2/array.h | 61 + php/ext/google/protobuf2/bundled_php.h | 46 + php/ext/google/protobuf2/config.m4 | 10 + php/ext/google/protobuf2/convert.c | 478 + php/ext/google/protobuf2/convert.h | 73 + php/ext/google/protobuf2/def.c | 1085 +++ php/ext/google/protobuf2/def.h | 69 + php/ext/google/protobuf2/make-preload.php | 62 + php/ext/google/protobuf2/map.c | 590 ++ php/ext/google/protobuf2/map.h | 60 + php/ext/google/protobuf2/message.c | 841 ++ php/ext/google/protobuf2/message.h | 59 + php/ext/google/protobuf2/names.c | 226 + php/ext/google/protobuf2/names.h | 40 + php/ext/google/protobuf2/php-upb.c | 8077 +++++++++++++++++ php/ext/google/protobuf2/php-upb.h | 3885 ++++++++ php/ext/google/protobuf2/protobuf.c | 349 + php/ext/google/protobuf2/protobuf.h | 89 + php/src/Google/Protobuf/Any.php | 8 +- .../Protobuf/Internal/DescriptorPool.php | 6 + php/src/Google/Protobuf/Internal/GPBUtil.php | 4 +- php/tests/compile_extension.sh | 13 +- php/tests/test.sh | 29 +- .../protobuf/internal/text_format_test.py | 4 + .../google/protobuf/internal/type_checkers.py | 5 - python/google/protobuf/text_format.py | 15 +- src/google/protobuf/any.pb.cc | 5 +- src/google/protobuf/any.pb.h | 6 +- src/google/protobuf/any.proto | 7 +- .../protobuf/compiler/cpp/cpp_map_field.cc | 11 +- .../protobuf/compiler/cpp/cpp_message.cc | 31 +- .../compiler/csharp/csharp_field_base.cc | 6 + .../compiler/csharp/csharp_field_base.h | 1 + .../compiler/csharp/csharp_map_field.cc | 8 +- .../compiler/csharp/csharp_map_field.h | 1 + .../compiler/csharp/csharp_message.cc | 75 +- .../protobuf/compiler/csharp/csharp_message.h | 1 + .../csharp/csharp_repeated_enum_field.cc | 8 +- .../csharp/csharp_repeated_enum_field.h | 1 + .../csharp/csharp_repeated_message_field.cc | 8 +- .../csharp/csharp_repeated_message_field.h | 1 + .../csharp/csharp_repeated_primitive_field.cc | 8 +- .../csharp/csharp_repeated_primitive_field.h | 1 + .../compiler/csharp/csharp_wrapper_field.cc | 28 +- .../compiler/csharp/csharp_wrapper_field.h | 2 + src/google/protobuf/extension_set_unittest.cc | 3 - src/google/protobuf/io/tokenizer.cc | 7 +- src/google/protobuf/io/tokenizer_unittest.cc | 5 +- src/google/protobuf/map.h | 136 +- src/google/protobuf/map_entry.h | 45 +- src/google/protobuf/map_entry_lite.h | 44 +- src/google/protobuf/map_field.h | 26 +- src/google/protobuf/map_field_inl.h | 75 +- src/google/protobuf/map_field_lite.h | 31 +- src/google/protobuf/map_field_test.cc | 4 +- src/google/protobuf/map_test.cc | 61 + src/google/protobuf/map_type_handler.h | 99 - src/google/protobuf/port_def.inc | 4 + src/google/protobuf/port_undef.inc | 2 + src/google/protobuf/struct.pb.h | 9 +- .../protobuf/util/internal/datapiece.cc | 1 + .../util/internal/field_mask_utility.cc | 3 +- .../util/internal/field_mask_utility.h | 3 +- .../util/internal/json_objectwriter.cc | 2 +- .../internal/protostream_objectsource_test.cc | 1 + .../util/internal/protostream_objectwriter.cc | 1 + .../internal/protostream_objectwriter_test.cc | 8 +- .../protobuf/util/internal/type_info.cc | 1 + src/google/protobuf/wire_format_lite.cc | 4 - tests.sh | 105 +- 152 files changed, 28848 insertions(+), 1136 deletions(-) create mode 100644 csharp/src/Google.Protobuf.Benchmarks/WriteMessagesBenchmark.cs create mode 100644 csharp/src/Google.Protobuf.Benchmarks/WriteRawPrimitivesBenchmark.cs create mode 100644 csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs create mode 100644 csharp/src/Google.Protobuf/WriteBufferHelper.cs create mode 100644 csharp/src/Google.Protobuf/WriteContext.cs create mode 100644 csharp/src/Google.Protobuf/WriterInternalState.cs create mode 100644 csharp/src/Google.Protobuf/WritingPrimitives.cs create mode 100644 csharp/src/Google.Protobuf/WritingPrimitivesMessages.cs create mode 100644 php/ext/google/protobuf2/arena.c create mode 100644 php/ext/google/protobuf2/arena.h create mode 100644 php/ext/google/protobuf2/array.c create mode 100644 php/ext/google/protobuf2/array.h create mode 100644 php/ext/google/protobuf2/bundled_php.h create mode 100644 php/ext/google/protobuf2/config.m4 create mode 100644 php/ext/google/protobuf2/convert.c create mode 100644 php/ext/google/protobuf2/convert.h create mode 100644 php/ext/google/protobuf2/def.c create mode 100644 php/ext/google/protobuf2/def.h create mode 100644 php/ext/google/protobuf2/make-preload.php create mode 100644 php/ext/google/protobuf2/map.c create mode 100644 php/ext/google/protobuf2/map.h create mode 100644 php/ext/google/protobuf2/message.c create mode 100644 php/ext/google/protobuf2/message.h create mode 100644 php/ext/google/protobuf2/names.c create mode 100644 php/ext/google/protobuf2/names.h create mode 100644 php/ext/google/protobuf2/php-upb.c create mode 100644 php/ext/google/protobuf2/php-upb.h create mode 100644 php/ext/google/protobuf2/protobuf.c create mode 100644 php/ext/google/protobuf2/protobuf.h diff --git a/BUILD b/BUILD index 996c334a37..224c8fce19 100644 --- a/BUILD +++ b/BUILD @@ -3,7 +3,6 @@ load("@bazel_skylib//rules:common_settings.bzl", "string_flag") load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test", "objc_library", native_cc_proto_library = "cc_proto_library") load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain", "proto_library") -load("@rules_proto//proto/private:native.bzl", "native_proto_common") load("@rules_python//python:defs.bzl", "py_library") load(":cc_proto_blacklist_test.bzl", "cc_proto_blacklist_test") @@ -945,13 +944,9 @@ cc_library( ], ) -# Note: We use `native_proto_common` here because we depend on an implementation-detail of -# `proto_lang_toolchain`, which may not be available on `proto_common`. -reject_blacklisted_files = hasattr(native_proto_common, "proto_lang_toolchain_rejects_files_do_not_use_or_we_will_break_you_without_mercy") -cc_toolchain_blacklisted_protos = [proto + "_proto" for proto in WELL_KNOWN_PROTO_MAP.keys()] if reject_blacklisted_files else [":well_known_protos"] proto_lang_toolchain( name = "cc_toolchain", - blacklisted_protos = cc_toolchain_blacklisted_protos, + blacklisted_protos = [proto + "_proto" for proto in WELL_KNOWN_PROTO_MAP.keys()], command_line = "--cpp_out=$(OUT)", runtime = ":protobuf", visibility = ["//visibility:public"], diff --git a/README.md b/README.md index 2f42c6c934..d5155ae9ab 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ how to install protobuf runtime for that specific language: | C# | [csharp](csharp) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-csharp.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fcsharp%2Fcontinuous) | | [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/windows-csharp-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fwindows%2Fcsharp_release%2Fcontinuous) | | JavaScript | [js](js) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-javascript.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fjavascript%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-javascript.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fjavascript%2Fcontinuous) | | | Ruby | [ruby](ruby) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-ruby23.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fruby23%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-ruby24.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fruby24%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-ruby25.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fruby25%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-ruby26.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fruby26%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-ruby-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fruby_release%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-ruby23.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fruby23%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-ruby24.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fruby24%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-ruby25.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fruby25%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-ruby26.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fruby26%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-ruby-release.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fruby_release%2Fcontinuous) | | -| Go | [golang/protobuf](https://github.com/golang/protobuf) | | | | +| Go | [protocolbuffers/protobuf-go](https://github.com/protocolbuffers/protobuf-go) | | | | | PHP | [php](php) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-php_all.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2Fphp_all%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/linux-32-bit.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fubuntu%2F32-bit%2Fcontinuous) | [![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-php5.6_mac.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fphp5.6_mac%2Fcontinuous)
[![Build status](https://storage.googleapis.com/protobuf-kokoro-results/status-badge/macos-php7.0_mac.png)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod:protobuf%2Fgithub%2Fmaster%2Fmacos%2Fphp7.0_mac%2Fcontinuous) | | | Dart | [dart-lang/protobuf](https://github.com/dart-lang/protobuf) | [![Build Status](https://travis-ci.org/dart-lang/protobuf.svg?branch=master)](https://travis-ci.org/dart-lang/protobuf) | | | diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedOutputStreamTest.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedOutputStreamTest.cs index f25e14e968..e9b4ea8cf0 100644 --- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedOutputStreamTest.cs +++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedOutputStreamTest.cs @@ -211,35 +211,35 @@ namespace Google.Protobuf [Test] public void EncodeZigZag32() { - Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag32(0)); - Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag32(-1)); - Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag32(1)); - Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag32(-2)); - Assert.AreEqual(0x7FFFFFFEu, CodedOutputStream.EncodeZigZag32(0x3FFFFFFF)); - Assert.AreEqual(0x7FFFFFFFu, CodedOutputStream.EncodeZigZag32(unchecked((int) 0xC0000000))); - Assert.AreEqual(0xFFFFFFFEu, CodedOutputStream.EncodeZigZag32(0x7FFFFFFF)); - Assert.AreEqual(0xFFFFFFFFu, CodedOutputStream.EncodeZigZag32(unchecked((int) 0x80000000))); + Assert.AreEqual(0u, WritingPrimitives.EncodeZigZag32(0)); + Assert.AreEqual(1u, WritingPrimitives.EncodeZigZag32(-1)); + Assert.AreEqual(2u, WritingPrimitives.EncodeZigZag32(1)); + Assert.AreEqual(3u, WritingPrimitives.EncodeZigZag32(-2)); + Assert.AreEqual(0x7FFFFFFEu, WritingPrimitives.EncodeZigZag32(0x3FFFFFFF)); + Assert.AreEqual(0x7FFFFFFFu, WritingPrimitives.EncodeZigZag32(unchecked((int) 0xC0000000))); + Assert.AreEqual(0xFFFFFFFEu, WritingPrimitives.EncodeZigZag32(0x7FFFFFFF)); + Assert.AreEqual(0xFFFFFFFFu, WritingPrimitives.EncodeZigZag32(unchecked((int) 0x80000000))); } [Test] public void EncodeZigZag64() { - Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag64(0)); - Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag64(-1)); - Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag64(1)); - Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag64(-2)); + Assert.AreEqual(0u, WritingPrimitives.EncodeZigZag64(0)); + Assert.AreEqual(1u, WritingPrimitives.EncodeZigZag64(-1)); + Assert.AreEqual(2u, WritingPrimitives.EncodeZigZag64(1)); + Assert.AreEqual(3u, WritingPrimitives.EncodeZigZag64(-2)); Assert.AreEqual(0x000000007FFFFFFEuL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000003FFFFFFFUL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0x000000003FFFFFFFUL))); Assert.AreEqual(0x000000007FFFFFFFuL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFFC0000000UL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0xFFFFFFFFC0000000UL))); Assert.AreEqual(0x00000000FFFFFFFEuL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000007FFFFFFFUL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0x000000007FFFFFFFUL))); Assert.AreEqual(0x00000000FFFFFFFFuL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFF80000000UL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0xFFFFFFFF80000000UL))); Assert.AreEqual(0xFFFFFFFFFFFFFFFEL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0x7FFFFFFFFFFFFFFFUL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0x7FFFFFFFFFFFFFFFUL))); Assert.AreEqual(0xFFFFFFFFFFFFFFFFL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0x8000000000000000UL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0x8000000000000000UL))); } [Test] @@ -247,26 +247,26 @@ namespace Google.Protobuf { // Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1) // were chosen semi-randomly via keyboard bashing. - Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(0))); - Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(1))); - Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-1))); - Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(14927))); - Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-3612))); + Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(0))); + Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(1))); + Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(-1))); + Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(14927))); + Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(-3612))); } [Test] public void RoundTripZigZag64() { - Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(0))); - Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(1))); - Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-1))); - Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(14927))); - Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-3612))); + Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(0))); + Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(1))); + Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-1))); + Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(14927))); + Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-3612))); Assert.AreEqual(856912304801416L, - ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(856912304801416L))); + ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(856912304801416L))); Assert.AreEqual(-75123905439571256L, - ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-75123905439571256L))); + ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-75123905439571256L))); } [Test] @@ -395,7 +395,7 @@ namespace Google.Protobuf Assert.IsTrue(memoryStream.CanWrite); using (var cos = new CodedOutputStream(memoryStream)) { - cos.WriteRawByte(0); + cos.WriteRawBytes(new byte[] {0}); Assert.AreEqual(0, memoryStream.Position); // Not flushed yet } Assert.AreEqual(1, memoryStream.ToArray().Length); // Flushed data from CodedOutputStream to MemoryStream @@ -409,7 +409,7 @@ namespace Google.Protobuf Assert.IsTrue(memoryStream.CanWrite); using (var cos = new CodedOutputStream(memoryStream, true)) { - cos.WriteRawByte(0); + cos.WriteRawBytes(new byte[] {0}); Assert.AreEqual(0, memoryStream.Position); // Not flushed yet } Assert.AreEqual(1, memoryStream.Position); // Flushed data from CodedOutputStream to MemoryStream diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/FieldCodecTest.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/FieldCodecTest.cs index a5825a0708..18e8767217 100644 --- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/FieldCodecTest.cs +++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/FieldCodecTest.cs @@ -124,7 +124,16 @@ namespace Google.Protobuf { var stream = new MemoryStream(); var codedOutput = new CodedOutputStream(stream); - codec.ValueWriter(codedOutput, sampleValue); + WriteContext.Initialize(codedOutput, out WriteContext ctx); + try + { + // only write the value using the codec + codec.ValueWriter(ref ctx, sampleValue); + } + finally + { + ctx.CopyStateTo(codedOutput); + } codedOutput.Flush(); stream.Position = 0; var codedInput = new CodedInputStream(stream); @@ -172,7 +181,16 @@ namespace Google.Protobuf if (codec.DefaultValue != null) // This part isn't appropriate for message types. { codedOutput = new CodedOutputStream(stream); - codec.ValueWriter(codedOutput, codec.DefaultValue); + WriteContext.Initialize(codedOutput, out WriteContext ctx); + try + { + // only write the value using the codec + codec.ValueWriter(ref ctx, codec.DefaultValue); + } + finally + { + ctx.CopyStateTo(codedOutput); + } codedOutput.Flush(); Assert.AreNotEqual(0, stream.Position); Assert.AreEqual(stream.Position, codec.ValueSizeCalculator(codec.DefaultValue)); diff --git a/csharp/install_dotnet_sdk.ps1 b/csharp/install_dotnet_sdk.ps1 index 9e300eda06..8bc967c9f4 100755 --- a/csharp/install_dotnet_sdk.ps1 +++ b/csharp/install_dotnet_sdk.ps1 @@ -1,5 +1,5 @@ #!/usr/bin/env powershell -# Install dotnet SDK based on the SDK version from global.json +# Install dotnet SDK using the official dotnet-install.ps1 script Set-StrictMode -Version 2 $ErrorActionPreference = 'Stop' @@ -9,16 +9,12 @@ $ErrorActionPreference = 'Stop' $InstallScriptUrl = 'https://dot.net/v1/dotnet-install.ps1' $InstallScriptPath = Join-Path "$env:TEMP" 'dotnet-install.ps1' -$GlobalJsonPath = Join-Path $PSScriptRoot '..' | Join-Path -ChildPath 'global.json' - -# Resolve SDK version from global.json file -$GlobalJson = Get-Content -Raw $GlobalJsonPath | ConvertFrom-Json -$SDKVersion = $GlobalJson.sdk.version # Download install script Write-Host "Downloading install script: $InstallScriptUrl => $InstallScriptPath" Invoke-WebRequest -Uri $InstallScriptUrl -OutFile $InstallScriptPath -&$InstallScriptPath -Version $SDKVersion -# Also install dotnet SDK LTS which is required to run some of the tests +# The SDK versions to install should be kept in sync with versions +# installed by kokoro/linux/dockerfile/test/csharp/Dockerfile &$InstallScriptPath -Version 2.1.802 +&$InstallScriptPath -Version 3.1.301 diff --git a/csharp/protos/unittest_issues.proto b/csharp/protos/unittest_issues.proto index b4a88d8648..ef40d75fce 100644 --- a/csharp/protos/unittest_issues.proto +++ b/csharp/protos/unittest_issues.proto @@ -8,6 +8,8 @@ option csharp_namespace = "UnitTest.Issues.TestProtos"; package unittest_issues; +import "google/protobuf/struct.proto"; + // Issue 307: when generating doubly-nested types, any references // should be of the form A.Types.B.Types.C. message Issue307 { @@ -137,4 +139,15 @@ message OneofMerging { string text = 1; Nested nested = 2; } -} \ No newline at end of file +} + +message NullValueOutsideStruct { + oneof value { + string string_value = 1; + google.protobuf.NullValue null_value = 2; + } +} + +message NullValueNotInOneof { + google.protobuf.NullValue null_value = 2; +} diff --git a/csharp/src/AddressBook/Addressbook.cs b/csharp/src/AddressBook/Addressbook.cs index 1b1c1b6c1f..042f69ee60 100644 --- a/csharp/src/AddressBook/Addressbook.cs +++ b/csharp/src/AddressBook/Addressbook.cs @@ -190,6 +190,9 @@ namespace Google.Protobuf.Examples.AddressBook { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); @@ -210,8 +213,35 @@ namespace Google.Protobuf.Examples.AddressBook { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (Id != 0) { + output.WriteRawTag(16); + output.WriteInt32(Id); + } + if (Email.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Email); + } + phones_.WriteTo(ref output, _repeated_phones_codec); + if (lastUpdated_ != null) { + output.WriteRawTag(42); + output.WriteMessage(LastUpdated); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -441,6 +471,9 @@ namespace Google.Protobuf.Examples.AddressBook { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Number.Length != 0) { output.WriteRawTag(10); output.WriteString(Number); @@ -452,8 +485,26 @@ namespace Google.Protobuf.Examples.AddressBook { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Number.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Number); + } + if (Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.Mobile) { + output.WriteRawTag(16); + output.WriteEnum((int) Type); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -621,12 +672,26 @@ namespace Google.Protobuf.Examples.AddressBook { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else people_.WriteTo(output, _repeated_people_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + people_.WriteTo(ref output, _repeated_people_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; diff --git a/csharp/src/Google.Protobuf.Benchmarks/BenchmarkMessage1Proto3.cs b/csharp/src/Google.Protobuf.Benchmarks/BenchmarkMessage1Proto3.cs index 6a213346a6..027da02a10 100644 --- a/csharp/src/Google.Protobuf.Benchmarks/BenchmarkMessage1Proto3.cs +++ b/csharp/src/Google.Protobuf.Benchmarks/BenchmarkMessage1Proto3.cs @@ -706,6 +706,9 @@ namespace Benchmarks.Proto3 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Field1.Length != 0) { output.WriteRawTag(10); output.WriteString(Field1); @@ -870,7 +873,178 @@ namespace Benchmarks.Proto3 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Field1.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Field1); + } + if (Field2 != 0) { + output.WriteRawTag(16); + output.WriteInt32(Field2); + } + if (Field3 != 0) { + output.WriteRawTag(24); + output.WriteInt32(Field3); + } + if (Field4.Length != 0) { + output.WriteRawTag(34); + output.WriteString(Field4); + } + field5_.WriteTo(ref output, _repeated_field5_codec); + if (Field6 != 0) { + output.WriteRawTag(48); + output.WriteInt32(Field6); + } + if (Field7.Length != 0) { + output.WriteRawTag(58); + output.WriteString(Field7); + } + if (Field9.Length != 0) { + output.WriteRawTag(74); + output.WriteString(Field9); + } + if (Field12 != false) { + output.WriteRawTag(96); + output.WriteBool(Field12); + } + if (Field13 != false) { + output.WriteRawTag(104); + output.WriteBool(Field13); + } + if (Field14 != false) { + output.WriteRawTag(112); + output.WriteBool(Field14); + } + if (field15_ != null) { + output.WriteRawTag(122); + output.WriteMessage(Field15); + } + if (Field16 != 0) { + output.WriteRawTag(128, 1); + output.WriteInt32(Field16); + } + if (Field17 != false) { + output.WriteRawTag(136, 1); + output.WriteBool(Field17); + } + if (Field18.Length != 0) { + output.WriteRawTag(146, 1); + output.WriteString(Field18); + } + if (Field22 != 0L) { + output.WriteRawTag(176, 1); + output.WriteInt64(Field22); + } + if (Field23 != 0) { + output.WriteRawTag(184, 1); + output.WriteInt32(Field23); + } + if (Field24 != false) { + output.WriteRawTag(192, 1); + output.WriteBool(Field24); + } + if (Field25 != 0) { + output.WriteRawTag(200, 1); + output.WriteInt32(Field25); + } + if (Field29 != 0) { + output.WriteRawTag(232, 1); + output.WriteInt32(Field29); + } + if (Field30 != false) { + output.WriteRawTag(240, 1); + output.WriteBool(Field30); + } + if (Field59 != false) { + output.WriteRawTag(216, 3); + output.WriteBool(Field59); + } + if (Field60 != 0) { + output.WriteRawTag(224, 3); + output.WriteInt32(Field60); + } + if (Field67 != 0) { + output.WriteRawTag(152, 4); + output.WriteInt32(Field67); + } + if (Field68 != 0) { + output.WriteRawTag(160, 4); + output.WriteInt32(Field68); + } + if (Field78 != false) { + output.WriteRawTag(240, 4); + output.WriteBool(Field78); + } + if (Field80 != false) { + output.WriteRawTag(128, 5); + output.WriteBool(Field80); + } + if (Field81 != false) { + output.WriteRawTag(136, 5); + output.WriteBool(Field81); + } + if (Field100 != 0) { + output.WriteRawTag(160, 6); + output.WriteInt32(Field100); + } + if (Field101 != 0) { + output.WriteRawTag(168, 6); + output.WriteInt32(Field101); + } + if (Field102.Length != 0) { + output.WriteRawTag(178, 6); + output.WriteString(Field102); + } + if (Field103.Length != 0) { + output.WriteRawTag(186, 6); + output.WriteString(Field103); + } + if (Field104 != 0) { + output.WriteRawTag(192, 6); + output.WriteInt32(Field104); + } + if (Field128 != 0) { + output.WriteRawTag(128, 8); + output.WriteInt32(Field128); + } + if (Field129.Length != 0) { + output.WriteRawTag(138, 8); + output.WriteString(Field129); + } + if (Field130 != 0) { + output.WriteRawTag(144, 8); + output.WriteInt32(Field130); + } + if (Field131 != 0) { + output.WriteRawTag(152, 8); + output.WriteInt32(Field131); + } + if (Field150 != 0) { + output.WriteRawTag(176, 9); + output.WriteInt32(Field150); + } + if (Field271 != 0) { + output.WriteRawTag(248, 16); + output.WriteInt32(Field271); + } + if (Field272 != 0) { + output.WriteRawTag(128, 17); + output.WriteInt32(Field272); + } + if (Field280 != 0) { + output.WriteRawTag(192, 17); + output.WriteInt32(Field280); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1851,6 +2025,9 @@ namespace Benchmarks.Proto3 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Field1 != 0) { output.WriteRawTag(8); output.WriteInt32(Field1); @@ -1934,7 +2111,97 @@ namespace Benchmarks.Proto3 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Field1 != 0) { + output.WriteRawTag(8); + output.WriteInt32(Field1); + } + if (Field2 != 0) { + output.WriteRawTag(16); + output.WriteInt32(Field2); + } + if (Field3 != 0) { + output.WriteRawTag(24); + output.WriteInt32(Field3); + } + if (Field12 != false) { + output.WriteRawTag(96); + output.WriteBool(Field12); + } + if (Field13 != 0L) { + output.WriteRawTag(104); + output.WriteInt64(Field13); + } + if (Field14 != 0L) { + output.WriteRawTag(112); + output.WriteInt64(Field14); + } + if (Field15.Length != 0) { + output.WriteRawTag(122); + output.WriteString(Field15); + } + if (Field16 != 0) { + output.WriteRawTag(128, 1); + output.WriteInt32(Field16); + } + if (Field19 != 0) { + output.WriteRawTag(152, 1); + output.WriteInt32(Field19); + } + if (Field20 != false) { + output.WriteRawTag(160, 1); + output.WriteBool(Field20); + } + if (Field21 != 0UL) { + output.WriteRawTag(169, 1); + output.WriteFixed64(Field21); + } + if (Field22 != 0) { + output.WriteRawTag(176, 1); + output.WriteInt32(Field22); + } + if (Field23 != false) { + output.WriteRawTag(184, 1); + output.WriteBool(Field23); + } + if (Field28 != false) { + output.WriteRawTag(224, 1); + output.WriteBool(Field28); + } + if (Field203 != 0) { + output.WriteRawTag(221, 12); + output.WriteFixed32(Field203); + } + if (Field204 != 0) { + output.WriteRawTag(224, 12); + output.WriteInt32(Field204); + } + if (Field205.Length != 0) { + output.WriteRawTag(234, 12); + output.WriteString(Field205); + } + if (Field206 != false) { + output.WriteRawTag(240, 12); + output.WriteBool(Field206); + } + if (Field207 != 0UL) { + output.WriteRawTag(248, 12); + output.WriteUInt64(Field207); + } + if (Field300 != 0UL) { + output.WriteRawTag(224, 18); + output.WriteUInt64(Field300); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { diff --git a/csharp/src/Google.Protobuf.Benchmarks/Benchmarks.cs b/csharp/src/Google.Protobuf.Benchmarks/Benchmarks.cs index ce2248aed6..e2578f367f 100644 --- a/csharp/src/Google.Protobuf.Benchmarks/Benchmarks.cs +++ b/csharp/src/Google.Protobuf.Benchmarks/Benchmarks.cs @@ -176,6 +176,9 @@ namespace Benchmarks { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); @@ -188,7 +191,26 @@ namespace Benchmarks { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (MessageName.Length != 0) { + output.WriteRawTag(18); + output.WriteString(MessageName); + } + payload_.WriteTo(ref output, _repeated_payload_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { diff --git a/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj b/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj index 7432168210..e2fe2556f1 100644 --- a/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj +++ b/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj @@ -2,15 +2,17 @@ Exe - netcoreapp2.1 + netcoreapp3.1 ../../keys/Google.Protobuf.snk true true False + pdbonly + true - + diff --git a/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs index 92c3dbe5f0..8e6710b708 100644 --- a/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs +++ b/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs @@ -151,7 +151,7 @@ namespace Google.Protobuf.Benchmarks repeatedFieldTest.ParseDelimitedMessagesFromReadOnlySequence(messageCount); } - private static ManyWrapperFieldsMessage CreateManyWrapperFieldsMessage() + public static ManyWrapperFieldsMessage CreateManyWrapperFieldsMessage() { // Example data match data of an internal benchmarks return new ManyWrapperFieldsMessage() @@ -168,7 +168,7 @@ namespace Google.Protobuf.Benchmarks }; } - private static ManyPrimitiveFieldsMessage CreateManyPrimitiveFieldsMessage() + public static ManyPrimitiveFieldsMessage CreateManyPrimitiveFieldsMessage() { // Example data match data of an internal benchmarks return new ManyPrimitiveFieldsMessage() @@ -185,7 +185,7 @@ namespace Google.Protobuf.Benchmarks }; } - private static GoogleMessage1 CreateRepeatedFieldMessage() + public static GoogleMessage1 CreateRepeatedFieldMessage() { // Message with a repeated fixed length item collection var message = new GoogleMessage1(); diff --git a/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs index 863e74dc49..2f226a323c 100644 --- a/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs +++ b/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs @@ -337,7 +337,7 @@ namespace Google.Protobuf.Benchmarks CodedOutputStream cos = new CodedOutputStream(ms); for (int i = 0; i < valueCount + paddingValueCount; i++) { - cos.WriteUInt64(RandomUnsignedVarint(random, encodedSize)); + cos.WriteUInt64(RandomUnsignedVarint(random, encodedSize, false)); } cos.Flush(); var buffer = ms.ToArray(); @@ -386,11 +386,11 @@ namespace Google.Protobuf.Benchmarks /// /// Generate a random value that will take exactly "encodedSize" bytes when varint-encoded. /// - private static ulong RandomUnsignedVarint(Random random, int encodedSize) + public static ulong RandomUnsignedVarint(Random random, int encodedSize, bool fitsIn32Bits) { Span randomBytesBuffer = stackalloc byte[8]; - if (encodedSize < 1 || encodedSize > 10) + if (encodedSize < 1 || encodedSize > 10 || (fitsIn32Bits && encodedSize > 5)) { throw new ArgumentException("Illegal encodedSize value requested", nameof(encodedSize)); } @@ -406,6 +406,12 @@ namespace Google.Protobuf.Benchmarks ulong bitmask = encodedSize < 10 ? ((1UL << (encodedSize * bitsPerByte)) - 1) : ulong.MaxValue; result = randomValue & bitmask; + if (fitsIn32Bits) + { + // make sure the resulting value is representable by a uint. + result &= uint.MaxValue; + } + if (encodedSize == 10) { // for 10-byte values the highest bit always needs to be set (7*9=63) @@ -443,7 +449,7 @@ namespace Google.Protobuf.Benchmarks return buffer; } - private static string CreateStringWithEncodedSize(int encodedSize) + public static string CreateStringWithEncodedSize(int encodedSize) { var str = new string('a', encodedSize); while (CodedOutputStream.ComputeStringSize(str) > encodedSize) @@ -457,5 +463,34 @@ namespace Google.Protobuf.Benchmarks } return str; } + + public static string CreateNonAsciiStringWithEncodedSize(int encodedSize) + { + if (encodedSize < 3) + { + throw new ArgumentException("Illegal encoded size for a string with non-ascii chars."); + } + var twoByteChar = '\u00DC'; // U-umlaut, UTF8 encoding has 2 bytes + var str = new string(twoByteChar, encodedSize / 2); + while (CodedOutputStream.ComputeStringSize(str) > encodedSize) + { + str = str.Substring(1); + } + + // add padding of ascii characters to reach the desired encoded size. + while (CodedOutputStream.ComputeStringSize(str) < encodedSize) + { + str += 'a'; + } + + // Note that for a few specific encodedSize values, it might be impossible to generate + // the string with the desired encodedSize using the algorithm above. For testing purposes, checking that + // the encoded size we got is actually correct is good enough. + if (CodedOutputStream.ComputeStringSize(str) != encodedSize) + { + throw new InvalidOperationException($"Generated string with wrong encodedSize"); + } + return str; + } } } diff --git a/csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs b/csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs index 95f613e1ba..9db92447ee 100644 --- a/csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs +++ b/csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs @@ -2073,6 +2073,9 @@ namespace Google.Protobuf.Benchmarks { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (doubleField1_ != null) { _single_doubleField1_codec.WriteTagAndValue(output, DoubleField1); } @@ -2410,7 +2413,351 @@ namespace Google.Protobuf.Benchmarks { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (doubleField1_ != null) { + _single_doubleField1_codec.WriteTagAndValue(ref output, DoubleField1); + } + if (int64Field2_ != null) { + _single_int64Field2_codec.WriteTagAndValue(ref output, Int64Field2); + } + if (int64Field3_ != null) { + _single_int64Field3_codec.WriteTagAndValue(ref output, Int64Field3); + } + if (int64Field4_ != null) { + _single_int64Field4_codec.WriteTagAndValue(ref output, Int64Field4); + } + if (doubleField7_ != null) { + _single_doubleField7_codec.WriteTagAndValue(ref output, DoubleField7); + } + if (doubleField8_ != null) { + _single_doubleField8_codec.WriteTagAndValue(ref output, DoubleField8); + } + if (doubleField9_ != null) { + _single_doubleField9_codec.WriteTagAndValue(ref output, DoubleField9); + } + if (doubleField10_ != null) { + _single_doubleField10_codec.WriteTagAndValue(ref output, DoubleField10); + } + if (doubleField11_ != null) { + _single_doubleField11_codec.WriteTagAndValue(ref output, DoubleField11); + } + if (doubleField14_ != null) { + _single_doubleField14_codec.WriteTagAndValue(ref output, DoubleField14); + } + if (doubleField15_ != null) { + _single_doubleField15_codec.WriteTagAndValue(ref output, DoubleField15); + } + if (int64Field19_ != null) { + _single_int64Field19_codec.WriteTagAndValue(ref output, Int64Field19); + } + if (doubleField20_ != null) { + _single_doubleField20_codec.WriteTagAndValue(ref output, DoubleField20); + } + if (doubleField21_ != null) { + _single_doubleField21_codec.WriteTagAndValue(ref output, DoubleField21); + } + if (doubleField22_ != null) { + _single_doubleField22_codec.WriteTagAndValue(ref output, DoubleField22); + } + if (doubleField25_ != null) { + _single_doubleField25_codec.WriteTagAndValue(ref output, DoubleField25); + } + if (int64Field26_ != null) { + _single_int64Field26_codec.WriteTagAndValue(ref output, Int64Field26); + } + if (doubleField28_ != null) { + _single_doubleField28_codec.WriteTagAndValue(ref output, DoubleField28); + } + if (doubleField29_ != null) { + _single_doubleField29_codec.WriteTagAndValue(ref output, DoubleField29); + } + if (doubleField30_ != null) { + _single_doubleField30_codec.WriteTagAndValue(ref output, DoubleField30); + } + if (doubleField31_ != null) { + _single_doubleField31_codec.WriteTagAndValue(ref output, DoubleField31); + } + if (int64Field32_ != null) { + _single_int64Field32_codec.WriteTagAndValue(ref output, Int64Field32); + } + if (int64Field37_ != null) { + _single_int64Field37_codec.WriteTagAndValue(ref output, Int64Field37); + } + if (doubleField38_ != null) { + _single_doubleField38_codec.WriteTagAndValue(ref output, DoubleField38); + } + if (interactions_ != null) { + _single_interactions_codec.WriteTagAndValue(ref output, Interactions); + } + if (doubleField40_ != null) { + _single_doubleField40_codec.WriteTagAndValue(ref output, DoubleField40); + } + if (int64Field41_ != null) { + _single_int64Field41_codec.WriteTagAndValue(ref output, Int64Field41); + } + if (doubleField42_ != null) { + _single_doubleField42_codec.WriteTagAndValue(ref output, DoubleField42); + } + if (int64Field43_ != null) { + _single_int64Field43_codec.WriteTagAndValue(ref output, Int64Field43); + } + if (int64Field44_ != null) { + _single_int64Field44_codec.WriteTagAndValue(ref output, Int64Field44); + } + if (doubleField45_ != null) { + _single_doubleField45_codec.WriteTagAndValue(ref output, DoubleField45); + } + if (doubleField46_ != null) { + _single_doubleField46_codec.WriteTagAndValue(ref output, DoubleField46); + } + if (doubleField47_ != null) { + _single_doubleField47_codec.WriteTagAndValue(ref output, DoubleField47); + } + if (doubleField48_ != null) { + _single_doubleField48_codec.WriteTagAndValue(ref output, DoubleField48); + } + if (doubleField49_ != null) { + _single_doubleField49_codec.WriteTagAndValue(ref output, DoubleField49); + } + if (doubleField50_ != null) { + _single_doubleField50_codec.WriteTagAndValue(ref output, DoubleField50); + } + if (doubleField51_ != null) { + _single_doubleField51_codec.WriteTagAndValue(ref output, DoubleField51); + } + if (doubleField52_ != null) { + _single_doubleField52_codec.WriteTagAndValue(ref output, DoubleField52); + } + if (doubleField53_ != null) { + _single_doubleField53_codec.WriteTagAndValue(ref output, DoubleField53); + } + if (doubleField54_ != null) { + _single_doubleField54_codec.WriteTagAndValue(ref output, DoubleField54); + } + if (doubleField55_ != null) { + _single_doubleField55_codec.WriteTagAndValue(ref output, DoubleField55); + } + if (doubleField56_ != null) { + _single_doubleField56_codec.WriteTagAndValue(ref output, DoubleField56); + } + if (doubleField57_ != null) { + _single_doubleField57_codec.WriteTagAndValue(ref output, DoubleField57); + } + if (doubleField58_ != null) { + _single_doubleField58_codec.WriteTagAndValue(ref output, DoubleField58); + } + if (int64Field59_ != null) { + _single_int64Field59_codec.WriteTagAndValue(ref output, Int64Field59); + } + if (int64Field60_ != null) { + _single_int64Field60_codec.WriteTagAndValue(ref output, Int64Field60); + } + if (doubleField62_ != null) { + _single_doubleField62_codec.WriteTagAndValue(ref output, DoubleField62); + } + if (doubleField65_ != null) { + _single_doubleField65_codec.WriteTagAndValue(ref output, DoubleField65); + } + if (doubleField66_ != null) { + _single_doubleField66_codec.WriteTagAndValue(ref output, DoubleField66); + } + if (doubleField67_ != null) { + _single_doubleField67_codec.WriteTagAndValue(ref output, DoubleField67); + } + if (doubleField68_ != null) { + _single_doubleField68_codec.WriteTagAndValue(ref output, DoubleField68); + } + if (doubleField69_ != null) { + _single_doubleField69_codec.WriteTagAndValue(ref output, DoubleField69); + } + if (doubleField70_ != null) { + _single_doubleField70_codec.WriteTagAndValue(ref output, DoubleField70); + } + if (doubleField71_ != null) { + _single_doubleField71_codec.WriteTagAndValue(ref output, DoubleField71); + } + if (doubleField72_ != null) { + _single_doubleField72_codec.WriteTagAndValue(ref output, DoubleField72); + } + if (stringField73_ != null) { + _single_stringField73_codec.WriteTagAndValue(ref output, StringField73); + } + if (stringField74_ != null) { + _single_stringField74_codec.WriteTagAndValue(ref output, StringField74); + } + if (doubleField75_ != null) { + _single_doubleField75_codec.WriteTagAndValue(ref output, DoubleField75); + } + if (doubleField77_ != null) { + _single_doubleField77_codec.WriteTagAndValue(ref output, DoubleField77); + } + if (doubleField78_ != null) { + _single_doubleField78_codec.WriteTagAndValue(ref output, DoubleField78); + } + if (doubleField79_ != null) { + _single_doubleField79_codec.WriteTagAndValue(ref output, DoubleField79); + } + if (EnumField80 != 0) { + output.WriteRawTag(128, 5); + output.WriteInt32(EnumField80); + } + if (EnumField81 != 0) { + output.WriteRawTag(136, 5); + output.WriteInt32(EnumField81); + } + if (int64Field82_ != null) { + _single_int64Field82_codec.WriteTagAndValue(ref output, Int64Field82); + } + if (EnumField83 != 0) { + output.WriteRawTag(152, 5); + output.WriteInt32(EnumField83); + } + if (doubleField84_ != null) { + _single_doubleField84_codec.WriteTagAndValue(ref output, DoubleField84); + } + if (int64Field85_ != null) { + _single_int64Field85_codec.WriteTagAndValue(ref output, Int64Field85); + } + if (int64Field86_ != null) { + _single_int64Field86_codec.WriteTagAndValue(ref output, Int64Field86); + } + if (int64Field87_ != null) { + _single_int64Field87_codec.WriteTagAndValue(ref output, Int64Field87); + } + if (doubleField88_ != null) { + _single_doubleField88_codec.WriteTagAndValue(ref output, DoubleField88); + } + if (doubleField89_ != null) { + _single_doubleField89_codec.WriteTagAndValue(ref output, DoubleField89); + } + if (doubleField90_ != null) { + _single_doubleField90_codec.WriteTagAndValue(ref output, DoubleField90); + } + if (doubleField91_ != null) { + _single_doubleField91_codec.WriteTagAndValue(ref output, DoubleField91); + } + if (doubleField92_ != null) { + _single_doubleField92_codec.WriteTagAndValue(ref output, DoubleField92); + } + if (doubleField93_ != null) { + _single_doubleField93_codec.WriteTagAndValue(ref output, DoubleField93); + } + if (doubleField94_ != null) { + _single_doubleField94_codec.WriteTagAndValue(ref output, DoubleField94); + } + if (doubleField95_ != null) { + _single_doubleField95_codec.WriteTagAndValue(ref output, DoubleField95); + } + if (doubleField96_ != null) { + _single_doubleField96_codec.WriteTagAndValue(ref output, DoubleField96); + } + if (doubleField97_ != null) { + _single_doubleField97_codec.WriteTagAndValue(ref output, DoubleField97); + } + if (doubleField98_ != null) { + _single_doubleField98_codec.WriteTagAndValue(ref output, DoubleField98); + } + if (doubleField99_ != null) { + _single_doubleField99_codec.WriteTagAndValue(ref output, DoubleField99); + } + repeatedIntField100_.WriteTo(ref output, _repeated_repeatedIntField100_codec); + if (doubleField101_ != null) { + _single_doubleField101_codec.WriteTagAndValue(ref output, DoubleField101); + } + if (doubleField102_ != null) { + _single_doubleField102_codec.WriteTagAndValue(ref output, DoubleField102); + } + if (doubleField103_ != null) { + _single_doubleField103_codec.WriteTagAndValue(ref output, DoubleField103); + } + if (doubleField104_ != null) { + _single_doubleField104_codec.WriteTagAndValue(ref output, DoubleField104); + } + if (doubleField105_ != null) { + _single_doubleField105_codec.WriteTagAndValue(ref output, DoubleField105); + } + if (doubleField106_ != null) { + _single_doubleField106_codec.WriteTagAndValue(ref output, DoubleField106); + } + if (int64Field107_ != null) { + _single_int64Field107_codec.WriteTagAndValue(ref output, Int64Field107); + } + if (doubleField108_ != null) { + _single_doubleField108_codec.WriteTagAndValue(ref output, DoubleField108); + } + if (doubleField109_ != null) { + _single_doubleField109_codec.WriteTagAndValue(ref output, DoubleField109); + } + if (int64Field110_ != null) { + _single_int64Field110_codec.WriteTagAndValue(ref output, Int64Field110); + } + if (doubleField111_ != null) { + _single_doubleField111_codec.WriteTagAndValue(ref output, DoubleField111); + } + if (int64Field112_ != null) { + _single_int64Field112_codec.WriteTagAndValue(ref output, Int64Field112); + } + if (doubleField113_ != null) { + _single_doubleField113_codec.WriteTagAndValue(ref output, DoubleField113); + } + if (int64Field114_ != null) { + _single_int64Field114_codec.WriteTagAndValue(ref output, Int64Field114); + } + if (int64Field115_ != null) { + _single_int64Field115_codec.WriteTagAndValue(ref output, Int64Field115); + } + if (doubleField116_ != null) { + _single_doubleField116_codec.WriteTagAndValue(ref output, DoubleField116); + } + if (int64Field117_ != null) { + _single_int64Field117_codec.WriteTagAndValue(ref output, Int64Field117); + } + if (doubleField118_ != null) { + _single_doubleField118_codec.WriteTagAndValue(ref output, DoubleField118); + } + if (doubleField119_ != null) { + _single_doubleField119_codec.WriteTagAndValue(ref output, DoubleField119); + } + if (doubleField120_ != null) { + _single_doubleField120_codec.WriteTagAndValue(ref output, DoubleField120); + } + if (doubleField121_ != null) { + _single_doubleField121_codec.WriteTagAndValue(ref output, DoubleField121); + } + if (doubleField122_ != null) { + _single_doubleField122_codec.WriteTagAndValue(ref output, DoubleField122); + } + if (doubleField123_ != null) { + _single_doubleField123_codec.WriteTagAndValue(ref output, DoubleField123); + } + if (doubleField124_ != null) { + _single_doubleField124_codec.WriteTagAndValue(ref output, DoubleField124); + } + if (int64Field125_ != null) { + _single_int64Field125_codec.WriteTagAndValue(ref output, Int64Field125); + } + if (int64Field126_ != null) { + _single_int64Field126_codec.WriteTagAndValue(ref output, Int64Field126); + } + if (int64Field127_ != null) { + _single_int64Field127_codec.WriteTagAndValue(ref output, Int64Field127); + } + if (doubleField128_ != null) { + _single_doubleField128_codec.WriteTagAndValue(ref output, DoubleField128); + } + if (doubleField129_ != null) { + _single_doubleField129_codec.WriteTagAndValue(ref output, DoubleField129); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -6495,6 +6842,9 @@ namespace Google.Protobuf.Benchmarks { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (DoubleField1 != 0D) { output.WriteRawTag(9); output.WriteDouble(DoubleField1); @@ -6939,8 +7289,459 @@ namespace Google.Protobuf.Benchmarks { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (DoubleField1 != 0D) { + output.WriteRawTag(9); + output.WriteDouble(DoubleField1); + } + if (Int64Field2 != 0L) { + output.WriteRawTag(16); + output.WriteInt64(Int64Field2); + } + if (Int64Field3 != 0L) { + output.WriteRawTag(24); + output.WriteInt64(Int64Field3); + } + if (Int64Field4 != 0L) { + output.WriteRawTag(32); + output.WriteInt64(Int64Field4); + } + if (DoubleField7 != 0D) { + output.WriteRawTag(57); + output.WriteDouble(DoubleField7); + } + if (DoubleField8 != 0D) { + output.WriteRawTag(65); + output.WriteDouble(DoubleField8); + } + if (DoubleField9 != 0D) { + output.WriteRawTag(73); + output.WriteDouble(DoubleField9); + } + if (DoubleField10 != 0D) { + output.WriteRawTag(81); + output.WriteDouble(DoubleField10); + } + if (DoubleField11 != 0D) { + output.WriteRawTag(89); + output.WriteDouble(DoubleField11); + } + if (DoubleField14 != 0D) { + output.WriteRawTag(113); + output.WriteDouble(DoubleField14); + } + if (DoubleField15 != 0D) { + output.WriteRawTag(121); + output.WriteDouble(DoubleField15); + } + if (Int64Field19 != 0L) { + output.WriteRawTag(152, 1); + output.WriteInt64(Int64Field19); + } + if (DoubleField20 != 0D) { + output.WriteRawTag(161, 1); + output.WriteDouble(DoubleField20); + } + if (DoubleField21 != 0D) { + output.WriteRawTag(169, 1); + output.WriteDouble(DoubleField21); + } + if (DoubleField22 != 0D) { + output.WriteRawTag(177, 1); + output.WriteDouble(DoubleField22); + } + if (DoubleField25 != 0D) { + output.WriteRawTag(201, 1); + output.WriteDouble(DoubleField25); + } + if (Int64Field26 != 0L) { + output.WriteRawTag(208, 1); + output.WriteInt64(Int64Field26); + } + if (DoubleField28 != 0D) { + output.WriteRawTag(225, 1); + output.WriteDouble(DoubleField28); + } + if (DoubleField29 != 0D) { + output.WriteRawTag(233, 1); + output.WriteDouble(DoubleField29); + } + if (DoubleField30 != 0D) { + output.WriteRawTag(241, 1); + output.WriteDouble(DoubleField30); + } + if (DoubleField31 != 0D) { + output.WriteRawTag(249, 1); + output.WriteDouble(DoubleField31); + } + if (Int64Field32 != 0L) { + output.WriteRawTag(128, 2); + output.WriteInt64(Int64Field32); + } + if (Int64Field37 != 0L) { + output.WriteRawTag(168, 2); + output.WriteInt64(Int64Field37); + } + if (DoubleField38 != 0D) { + output.WriteRawTag(177, 2); + output.WriteDouble(DoubleField38); + } + if (Interactions != 0L) { + output.WriteRawTag(184, 2); + output.WriteInt64(Interactions); + } + if (DoubleField40 != 0D) { + output.WriteRawTag(193, 2); + output.WriteDouble(DoubleField40); + } + if (Int64Field41 != 0L) { + output.WriteRawTag(200, 2); + output.WriteInt64(Int64Field41); + } + if (DoubleField42 != 0D) { + output.WriteRawTag(209, 2); + output.WriteDouble(DoubleField42); + } + if (Int64Field43 != 0L) { + output.WriteRawTag(216, 2); + output.WriteInt64(Int64Field43); + } + if (Int64Field44 != 0L) { + output.WriteRawTag(224, 2); + output.WriteInt64(Int64Field44); + } + if (DoubleField45 != 0D) { + output.WriteRawTag(233, 2); + output.WriteDouble(DoubleField45); + } + if (DoubleField46 != 0D) { + output.WriteRawTag(241, 2); + output.WriteDouble(DoubleField46); + } + if (DoubleField47 != 0D) { + output.WriteRawTag(249, 2); + output.WriteDouble(DoubleField47); + } + if (DoubleField48 != 0D) { + output.WriteRawTag(129, 3); + output.WriteDouble(DoubleField48); + } + if (DoubleField49 != 0D) { + output.WriteRawTag(137, 3); + output.WriteDouble(DoubleField49); + } + if (DoubleField50 != 0D) { + output.WriteRawTag(145, 3); + output.WriteDouble(DoubleField50); + } + if (DoubleField51 != 0D) { + output.WriteRawTag(153, 3); + output.WriteDouble(DoubleField51); + } + if (DoubleField52 != 0D) { + output.WriteRawTag(161, 3); + output.WriteDouble(DoubleField52); + } + if (DoubleField53 != 0D) { + output.WriteRawTag(169, 3); + output.WriteDouble(DoubleField53); + } + if (DoubleField54 != 0D) { + output.WriteRawTag(177, 3); + output.WriteDouble(DoubleField54); + } + if (DoubleField55 != 0D) { + output.WriteRawTag(185, 3); + output.WriteDouble(DoubleField55); + } + if (DoubleField56 != 0D) { + output.WriteRawTag(193, 3); + output.WriteDouble(DoubleField56); + } + if (DoubleField57 != 0D) { + output.WriteRawTag(201, 3); + output.WriteDouble(DoubleField57); + } + if (DoubleField58 != 0D) { + output.WriteRawTag(209, 3); + output.WriteDouble(DoubleField58); + } + if (Int64Field59 != 0L) { + output.WriteRawTag(216, 3); + output.WriteInt64(Int64Field59); + } + if (Int64Field60 != 0L) { + output.WriteRawTag(224, 3); + output.WriteInt64(Int64Field60); + } + if (DoubleField62 != 0D) { + output.WriteRawTag(241, 3); + output.WriteDouble(DoubleField62); + } + if (DoubleField65 != 0D) { + output.WriteRawTag(137, 4); + output.WriteDouble(DoubleField65); + } + if (DoubleField66 != 0D) { + output.WriteRawTag(145, 4); + output.WriteDouble(DoubleField66); + } + if (DoubleField67 != 0D) { + output.WriteRawTag(153, 4); + output.WriteDouble(DoubleField67); + } + if (DoubleField68 != 0D) { + output.WriteRawTag(161, 4); + output.WriteDouble(DoubleField68); + } + if (DoubleField69 != 0D) { + output.WriteRawTag(169, 4); + output.WriteDouble(DoubleField69); + } + if (DoubleField70 != 0D) { + output.WriteRawTag(177, 4); + output.WriteDouble(DoubleField70); + } + if (DoubleField71 != 0D) { + output.WriteRawTag(185, 4); + output.WriteDouble(DoubleField71); + } + if (DoubleField72 != 0D) { + output.WriteRawTag(193, 4); + output.WriteDouble(DoubleField72); + } + if (StringField73.Length != 0) { + output.WriteRawTag(202, 4); + output.WriteString(StringField73); + } + if (StringField74.Length != 0) { + output.WriteRawTag(210, 4); + output.WriteString(StringField74); + } + if (DoubleField75 != 0D) { + output.WriteRawTag(217, 4); + output.WriteDouble(DoubleField75); + } + if (DoubleField77 != 0D) { + output.WriteRawTag(233, 4); + output.WriteDouble(DoubleField77); + } + if (DoubleField78 != 0D) { + output.WriteRawTag(241, 4); + output.WriteDouble(DoubleField78); + } + if (DoubleField79 != 0D) { + output.WriteRawTag(249, 4); + output.WriteDouble(DoubleField79); + } + if (EnumField80 != 0) { + output.WriteRawTag(128, 5); + output.WriteInt32(EnumField80); + } + if (EnumField81 != 0) { + output.WriteRawTag(136, 5); + output.WriteInt32(EnumField81); + } + if (Int64Field82 != 0L) { + output.WriteRawTag(144, 5); + output.WriteInt64(Int64Field82); + } + if (EnumField83 != 0) { + output.WriteRawTag(152, 5); + output.WriteInt32(EnumField83); + } + if (DoubleField84 != 0D) { + output.WriteRawTag(161, 5); + output.WriteDouble(DoubleField84); + } + if (Int64Field85 != 0L) { + output.WriteRawTag(168, 5); + output.WriteInt64(Int64Field85); + } + if (Int64Field86 != 0L) { + output.WriteRawTag(176, 5); + output.WriteInt64(Int64Field86); + } + if (Int64Field87 != 0L) { + output.WriteRawTag(184, 5); + output.WriteInt64(Int64Field87); + } + if (DoubleField88 != 0D) { + output.WriteRawTag(193, 5); + output.WriteDouble(DoubleField88); + } + if (DoubleField89 != 0D) { + output.WriteRawTag(201, 5); + output.WriteDouble(DoubleField89); + } + if (DoubleField90 != 0D) { + output.WriteRawTag(209, 5); + output.WriteDouble(DoubleField90); + } + if (DoubleField91 != 0D) { + output.WriteRawTag(217, 5); + output.WriteDouble(DoubleField91); + } + if (DoubleField92 != 0D) { + output.WriteRawTag(225, 5); + output.WriteDouble(DoubleField92); + } + if (DoubleField93 != 0D) { + output.WriteRawTag(233, 5); + output.WriteDouble(DoubleField93); + } + if (DoubleField94 != 0D) { + output.WriteRawTag(241, 5); + output.WriteDouble(DoubleField94); + } + if (DoubleField95 != 0D) { + output.WriteRawTag(249, 5); + output.WriteDouble(DoubleField95); + } + if (DoubleField96 != 0D) { + output.WriteRawTag(129, 6); + output.WriteDouble(DoubleField96); + } + if (DoubleField97 != 0D) { + output.WriteRawTag(137, 6); + output.WriteDouble(DoubleField97); + } + if (DoubleField98 != 0D) { + output.WriteRawTag(145, 6); + output.WriteDouble(DoubleField98); + } + if (DoubleField99 != 0D) { + output.WriteRawTag(153, 6); + output.WriteDouble(DoubleField99); + } + repeatedIntField100_.WriteTo(ref output, _repeated_repeatedIntField100_codec); + if (DoubleField101 != 0D) { + output.WriteRawTag(169, 6); + output.WriteDouble(DoubleField101); + } + if (DoubleField102 != 0D) { + output.WriteRawTag(177, 6); + output.WriteDouble(DoubleField102); + } + if (DoubleField103 != 0D) { + output.WriteRawTag(185, 6); + output.WriteDouble(DoubleField103); + } + if (DoubleField104 != 0D) { + output.WriteRawTag(193, 6); + output.WriteDouble(DoubleField104); + } + if (DoubleField105 != 0D) { + output.WriteRawTag(201, 6); + output.WriteDouble(DoubleField105); + } + if (DoubleField106 != 0D) { + output.WriteRawTag(209, 6); + output.WriteDouble(DoubleField106); + } + if (Int64Field107 != 0L) { + output.WriteRawTag(216, 6); + output.WriteInt64(Int64Field107); + } + if (DoubleField108 != 0D) { + output.WriteRawTag(225, 6); + output.WriteDouble(DoubleField108); + } + if (DoubleField109 != 0D) { + output.WriteRawTag(233, 6); + output.WriteDouble(DoubleField109); + } + if (Int64Field110 != 0L) { + output.WriteRawTag(240, 6); + output.WriteInt64(Int64Field110); + } + if (DoubleField111 != 0D) { + output.WriteRawTag(249, 6); + output.WriteDouble(DoubleField111); + } + if (Int64Field112 != 0L) { + output.WriteRawTag(128, 7); + output.WriteInt64(Int64Field112); + } + if (DoubleField113 != 0D) { + output.WriteRawTag(137, 7); + output.WriteDouble(DoubleField113); + } + if (Int64Field114 != 0L) { + output.WriteRawTag(144, 7); + output.WriteInt64(Int64Field114); + } + if (Int64Field115 != 0L) { + output.WriteRawTag(152, 7); + output.WriteInt64(Int64Field115); + } + if (DoubleField116 != 0D) { + output.WriteRawTag(161, 7); + output.WriteDouble(DoubleField116); + } + if (Int64Field117 != 0L) { + output.WriteRawTag(168, 7); + output.WriteInt64(Int64Field117); + } + if (DoubleField118 != 0D) { + output.WriteRawTag(177, 7); + output.WriteDouble(DoubleField118); + } + if (DoubleField119 != 0D) { + output.WriteRawTag(185, 7); + output.WriteDouble(DoubleField119); + } + if (DoubleField120 != 0D) { + output.WriteRawTag(193, 7); + output.WriteDouble(DoubleField120); + } + if (DoubleField121 != 0D) { + output.WriteRawTag(201, 7); + output.WriteDouble(DoubleField121); + } + if (DoubleField122 != 0D) { + output.WriteRawTag(209, 7); + output.WriteDouble(DoubleField122); + } + if (DoubleField123 != 0D) { + output.WriteRawTag(217, 7); + output.WriteDouble(DoubleField123); + } + if (DoubleField124 != 0D) { + output.WriteRawTag(225, 7); + output.WriteDouble(DoubleField124); + } + if (Int64Field125 != 0L) { + output.WriteRawTag(232, 7); + output.WriteInt64(Int64Field125); + } + if (Int64Field126 != 0L) { + output.WriteRawTag(240, 7); + output.WriteInt64(Int64Field126); + } + if (Int64Field127 != 0L) { + output.WriteRawTag(248, 7); + output.WriteInt64(Int64Field127); + } + if (DoubleField128 != 0D) { + output.WriteRawTag(129, 8); + output.WriteDouble(DoubleField128); + } + if (DoubleField129 != 0D) { + output.WriteRawTag(137, 8); + output.WriteDouble(DoubleField129); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; diff --git a/csharp/src/Google.Protobuf.Benchmarks/WriteMessagesBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/WriteMessagesBenchmark.cs new file mode 100644 index 0000000000..5a3bba74d2 --- /dev/null +++ b/csharp/src/Google.Protobuf.Benchmarks/WriteMessagesBenchmark.cs @@ -0,0 +1,198 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2019 Google Inc. All rights reserved. +// https://github.com/protocolbuffers/protobuf +// +// 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. +#endregion + +using BenchmarkDotNet.Attributes; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Buffers; +using Google.Protobuf.WellKnownTypes; + +namespace Google.Protobuf.Benchmarks +{ + /// + /// Benchmark that tests writing performance for various messages. + /// + [MemoryDiagnoser] + public class WriteMessagesBenchmark + { + const int MaxMessages = 100; + + SubTest manyWrapperFieldsTest = new SubTest(ParseMessagesBenchmark.CreateManyWrapperFieldsMessage(), MaxMessages); + SubTest manyPrimitiveFieldsTest = new SubTest(ParseMessagesBenchmark.CreateManyPrimitiveFieldsMessage(), MaxMessages); + SubTest emptyMessageTest = new SubTest(new Empty(), MaxMessages); + + public IEnumerable MessageCountValues => new[] { 10, 100 }; + + [GlobalSetup] + public void GlobalSetup() + { + } + + [Benchmark] + public byte[] ManyWrapperFieldsMessage_ToByteArray() + { + return manyWrapperFieldsTest.ToByteArray(); + } + + [Benchmark] + public byte[] ManyWrapperFieldsMessage_WriteToCodedOutputStream() + { + return manyWrapperFieldsTest.WriteToCodedOutputStream_PreAllocatedBuffer(); + } + + [Benchmark] + public byte[] ManyWrapperFieldsMessage_WriteToSpan() + { + return manyWrapperFieldsTest.WriteToSpan_PreAllocatedBuffer(); + } + + + [Benchmark] + public byte[] ManyPrimitiveFieldsMessage_ToByteArray() + { + return manyPrimitiveFieldsTest.ToByteArray(); + } + + [Benchmark] + public byte[] ManyPrimitiveFieldsMessage_WriteToCodedOutputStream() + { + return manyPrimitiveFieldsTest.WriteToCodedOutputStream_PreAllocatedBuffer(); + } + + [Benchmark] + public byte[] ManyPrimitiveFieldsMessage_WriteToSpan() + { + return manyPrimitiveFieldsTest.WriteToSpan_PreAllocatedBuffer(); + } + + [Benchmark] + public byte[] EmptyMessage_ToByteArray() + { + return emptyMessageTest.ToByteArray(); + } + + [Benchmark] + public byte[] EmptyMessage_WriteToCodedOutputStream() + { + return emptyMessageTest.WriteToCodedOutputStream_PreAllocatedBuffer(); + } + + [Benchmark] + public byte[] EmptyMessage_WriteToSpan() + { + return emptyMessageTest.WriteToSpan_PreAllocatedBuffer(); + } + + [Benchmark] + [ArgumentsSource(nameof(MessageCountValues))] + public void ManyWrapperFieldsMessage_WriteDelimitedMessagesToCodedOutputStream(int messageCount) + { + manyWrapperFieldsTest.WriteDelimitedMessagesToCodedOutputStream_PreAllocatedBuffer(messageCount); + } + + [Benchmark] + [ArgumentsSource(nameof(MessageCountValues))] + public void ManyWrapperFieldsMessage_WriteDelimitedMessagesToSpan(int messageCount) + { + manyWrapperFieldsTest.WriteDelimitedMessagesToSpan_PreAllocatedBuffer(messageCount); + } + + [Benchmark] + [ArgumentsSource(nameof(MessageCountValues))] + public void ManyPrimitiveFieldsMessage_WriteDelimitedMessagesToCodedOutputStream(int messageCount) + { + manyPrimitiveFieldsTest.WriteDelimitedMessagesToCodedOutputStream_PreAllocatedBuffer(messageCount); + } + + [Benchmark] + [ArgumentsSource(nameof(MessageCountValues))] + public void ManyPrimitiveFieldsMessage_WriteDelimitedMessagesToSpan(int messageCount) + { + manyPrimitiveFieldsTest.WriteDelimitedMessagesToSpan_PreAllocatedBuffer(messageCount); + } + + private class SubTest + { + private readonly IMessage message; + private readonly byte[] outputBuffer; + private readonly byte[] multipleMessagesOutputBuffer; + + public SubTest(IMessage message, int maxMessageCount) + { + this.message = message; + + int messageSize = message.CalculateSize(); + this.outputBuffer = new byte[messageSize]; + this.multipleMessagesOutputBuffer = new byte[maxMessageCount * (messageSize + CodedOutputStream.ComputeLengthSize(messageSize))]; + } + + public byte[] ToByteArray() => message.ToByteArray(); + + public byte[] WriteToCodedOutputStream_PreAllocatedBuffer() + { + var cos = new CodedOutputStream(outputBuffer); // use pre-existing output buffer + message.WriteTo(cos); + return outputBuffer; + } + + public byte[] WriteToSpan_PreAllocatedBuffer() + { + var span = new Span(outputBuffer); // use pre-existing output buffer + message.WriteTo(span); + return outputBuffer; + } + + public byte[] WriteDelimitedMessagesToCodedOutputStream_PreAllocatedBuffer(int messageCount) + { + var cos = new CodedOutputStream(multipleMessagesOutputBuffer); // use pre-existing output buffer + for (int i = 0; i < messageCount; i++) + { + cos.WriteMessage(message); + } + return multipleMessagesOutputBuffer; + } + + public byte[] WriteDelimitedMessagesToSpan_PreAllocatedBuffer(int messageCount) + { + var span = new Span(multipleMessagesOutputBuffer); // use pre-existing output buffer + WriteContext.Initialize(ref span, out WriteContext ctx); + for (int i = 0; i < messageCount; i++) + { + ctx.WriteMessage(message); + } + return multipleMessagesOutputBuffer; + } + } + } +} diff --git a/csharp/src/Google.Protobuf.Benchmarks/WriteRawPrimitivesBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/WriteRawPrimitivesBenchmark.cs new file mode 100644 index 0000000000..66b6b4a028 --- /dev/null +++ b/csharp/src/Google.Protobuf.Benchmarks/WriteRawPrimitivesBenchmark.cs @@ -0,0 +1,519 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2019 Google Inc. All rights reserved. +// https://github.com/protocolbuffers/protobuf +// +// 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. +#endregion + +using BenchmarkDotNet.Attributes; +using System; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.IO; +using System.Buffers; +using System.Text; + +namespace Google.Protobuf.Benchmarks +{ + /// + /// Benchmarks throughput when writing raw primitives. + /// + [MemoryDiagnoser] + public class WriteRawPrimitivesBenchmark + { + // key is the encodedSize of varint values + Dictionary varint32Values; + Dictionary varint64Values; + + double[] doubleValues; + float[] floatValues; + + // key is the encodedSize of string values + Dictionary stringValues; + + // key is the encodedSize of string values + Dictionary nonAsciiStringValues; + + // key is the encodedSize of string values + Dictionary byteStringValues; + + // the buffer to which all the data will be written + byte[] outputBuffer; + + Random random = new Random(417384220); // random but deterministic seed + + public IEnumerable StringEncodedSizes => new[] { 1, 4, 10, 105, 10080 }; + + public IEnumerable NonAsciiStringEncodedSizes => new[] { 4, 10, 105, 10080 }; + + [GlobalSetup] + public void GlobalSetup() + { + outputBuffer = new byte[BytesToWrite]; + + varint32Values = new Dictionary(); + varint64Values = new Dictionary(); + for (int encodedSize = 1; encodedSize <= 10; encodedSize++) + { + if (encodedSize <= 5) + { + varint32Values.Add(encodedSize, CreateRandomVarints32(random, BytesToWrite / encodedSize, encodedSize)); + } + varint64Values.Add(encodedSize, CreateRandomVarints64(random, BytesToWrite / encodedSize, encodedSize)); + } + + doubleValues = CreateRandomDoubles(random, BytesToWrite / sizeof(double)); + floatValues = CreateRandomFloats(random, BytesToWrite / sizeof(float)); + + stringValues = new Dictionary(); + + byteStringValues = new Dictionary(); + foreach(var encodedSize in StringEncodedSizes) + { + stringValues.Add(encodedSize, CreateStrings(BytesToWrite / encodedSize, encodedSize)); + byteStringValues.Add(encodedSize, CreateByteStrings(BytesToWrite / encodedSize, encodedSize)); + } + + nonAsciiStringValues = new Dictionary(); + foreach(var encodedSize in NonAsciiStringEncodedSizes) + { + nonAsciiStringValues.Add(encodedSize, CreateNonAsciiStrings(BytesToWrite / encodedSize, encodedSize)); + } + } + + // Total number of bytes that each benchmark will write. + // Measuring the time taken to write buffer of given size makes it easier to compare parsing speed for different + // types and makes it easy to calculate the througput (in MB/s) + // 10800 bytes is chosen because it is divisible by all possible encoded sizes for all primitive types {1..10} + [Params(10080)] + public int BytesToWrite { get; set; } + + [Benchmark] + [Arguments(1)] + [Arguments(2)] + [Arguments(3)] + [Arguments(4)] + [Arguments(5)] + public void WriteRawVarint32_CodedOutputStream(int encodedSize) + { + var values = varint32Values[encodedSize]; + var cos = new CodedOutputStream(outputBuffer); + for (int i = 0; i < values.Length; i++) + { + cos.WriteRawVarint32(values[i]); + } + cos.Flush(); + cos.CheckNoSpaceLeft(); + } + + [Benchmark] + [Arguments(1)] + [Arguments(2)] + [Arguments(3)] + [Arguments(4)] + [Arguments(5)] + public void WriteRawVarint32_WriteContext(int encodedSize) + { + var values = varint32Values[encodedSize]; + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + for (int i = 0; i < values.Length; i++) + { + ctx.WriteUInt32(values[i]); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + [Arguments(1)] + [Arguments(2)] + [Arguments(3)] + [Arguments(4)] + [Arguments(5)] + [Arguments(6)] + [Arguments(7)] + [Arguments(8)] + [Arguments(9)] + [Arguments(10)] + public void WriteRawVarint64_CodedOutputStream(int encodedSize) + { + var values = varint64Values[encodedSize]; + var cos = new CodedOutputStream(outputBuffer); + for (int i = 0; i < values.Length; i++) + { + cos.WriteRawVarint64(values[i]); + } + cos.Flush(); + cos.CheckNoSpaceLeft(); + } + + [Benchmark] + [Arguments(1)] + [Arguments(2)] + [Arguments(3)] + [Arguments(4)] + [Arguments(5)] + [Arguments(6)] + [Arguments(7)] + [Arguments(8)] + [Arguments(9)] + [Arguments(10)] + public void WriteRawVarint64_WriteContext(int encodedSize) + { + var values = varint64Values[encodedSize]; + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + for (int i = 0; i < values.Length; i++) + { + ctx.WriteUInt64(values[i]); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteFixed32_CodedOutputStream() + { + const int encodedSize = sizeof(uint); + var cos = new CodedOutputStream(outputBuffer); + for (int i = 0; i < BytesToWrite / encodedSize; i++) + { + cos.WriteFixed32(12345); + } + cos.Flush(); + cos.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteFixed32_WriteContext() + { + const int encodedSize = sizeof(uint); + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + for (uint i = 0; i < BytesToWrite / encodedSize; i++) + { + ctx.WriteFixed32(12345); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteFixed64_CodedOutputStream() + { + const int encodedSize = sizeof(ulong); + var cos = new CodedOutputStream(outputBuffer); + for(int i = 0; i < BytesToWrite / encodedSize; i++) + { + cos.WriteFixed64(123456789); + } + cos.Flush(); + cos.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteFixed64_WriteContext() + { + const int encodedSize = sizeof(ulong); + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + for (uint i = 0; i < BytesToWrite / encodedSize; i++) + { + ctx.WriteFixed64(123456789); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteRawTag_OneByte_WriteContext() + { + const int encodedSize = 1; + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + for (uint i = 0; i < BytesToWrite / encodedSize; i++) + { + ctx.WriteRawTag(16); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteRawTag_TwoBytes_WriteContext() + { + const int encodedSize = 2; + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + for (uint i = 0; i < BytesToWrite / encodedSize; i++) + { + ctx.WriteRawTag(137, 6); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteRawTag_ThreeBytes_WriteContext() + { + const int encodedSize = 3; + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + for (uint i = 0; i < BytesToWrite / encodedSize; i++) + { + ctx.WriteRawTag(160, 131, 1); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + public void Baseline_WriteContext() + { + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + ctx.state.position = outputBuffer.Length; + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteRawFloat_CodedOutputStream() + { + var cos = new CodedOutputStream(outputBuffer); + foreach (var value in floatValues) + { + cos.WriteFloat(value); + } + cos.Flush(); + cos.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteRawFloat_WriteContext() + { + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + foreach (var value in floatValues) + { + ctx.WriteFloat(value); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteRawDouble_CodedOutputStream() + { + var cos = new CodedOutputStream(outputBuffer); + foreach (var value in doubleValues) + { + cos.WriteDouble(value); + } + cos.Flush(); + cos.CheckNoSpaceLeft(); + } + + [Benchmark] + public void WriteRawDouble_WriteContext() + { + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + foreach (var value in doubleValues) + { + ctx.WriteDouble(value); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + [ArgumentsSource(nameof(StringEncodedSizes))] + public void WriteString_CodedOutputStream(int encodedSize) + { + var values = stringValues[encodedSize]; + var cos = new CodedOutputStream(outputBuffer); + foreach (var value in values) + { + cos.WriteString(value); + } + cos.Flush(); + cos.CheckNoSpaceLeft(); + } + + [Benchmark] + [ArgumentsSource(nameof(StringEncodedSizes))] + public void WriteString_WriteContext(int encodedSize) + { + var values = stringValues[encodedSize]; + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + foreach (var value in values) + { + ctx.WriteString(value); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + [ArgumentsSource(nameof(NonAsciiStringEncodedSizes))] + public void WriteNonAsciiString_CodedOutputStream(int encodedSize) + { + var values = nonAsciiStringValues[encodedSize]; + var cos = new CodedOutputStream(outputBuffer); + foreach (var value in values) + { + cos.WriteString(value); + } + cos.Flush(); + cos.CheckNoSpaceLeft(); + } + + [Benchmark] + [ArgumentsSource(nameof(NonAsciiStringEncodedSizes))] + public void WriteNonAsciiString_WriteContext(int encodedSize) + { + var values = nonAsciiStringValues[encodedSize]; + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + foreach (var value in values) + { + ctx.WriteString(value); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + [Benchmark] + [ArgumentsSource(nameof(StringEncodedSizes))] + public void WriteBytes_CodedOutputStream(int encodedSize) + { + var values = byteStringValues[encodedSize]; + var cos = new CodedOutputStream(outputBuffer); + foreach (var value in values) + { + cos.WriteBytes(value); + } + cos.Flush(); + cos.CheckNoSpaceLeft(); + } + + [Benchmark] + [ArgumentsSource(nameof(StringEncodedSizes))] + public void WriteBytes_WriteContext(int encodedSize) + { + var values = byteStringValues[encodedSize]; + var span = new Span(outputBuffer); + WriteContext.Initialize(ref span, out WriteContext ctx); + foreach (var value in values) + { + ctx.WriteBytes(value); + } + ctx.Flush(); + ctx.CheckNoSpaceLeft(); + } + + private static uint[] CreateRandomVarints32(Random random, int valueCount, int encodedSize) + { + var result = new uint[valueCount]; + for (int i = 0; i < valueCount; i++) + { + result[i] = (uint) ParseRawPrimitivesBenchmark.RandomUnsignedVarint(random, encodedSize, true); + } + return result; + } + + private static ulong[] CreateRandomVarints64(Random random, int valueCount, int encodedSize) + { + var result = new ulong[valueCount]; + for (int i = 0; i < valueCount; i++) + { + result[i] = ParseRawPrimitivesBenchmark.RandomUnsignedVarint(random, encodedSize, false); + } + return result; + } + + private static float[] CreateRandomFloats(Random random, int valueCount) + { + var result = new float[valueCount]; + for (int i = 0; i < valueCount; i++) + { + result[i] = (float)random.NextDouble(); + } + return result; + } + + private static double[] CreateRandomDoubles(Random random, int valueCount) + { + var result = new double[valueCount]; + for (int i = 0; i < valueCount; i++) + { + result[i] = random.NextDouble(); + } + return result; + } + + private static string[] CreateStrings(int valueCount, int encodedSize) + { + var str = ParseRawPrimitivesBenchmark.CreateStringWithEncodedSize(encodedSize); + + var result = new string[valueCount]; + for (int i = 0; i < valueCount; i++) + { + result[i] = str; + } + return result; + } + + private static string[] CreateNonAsciiStrings(int valueCount, int encodedSize) + { + var str = ParseRawPrimitivesBenchmark.CreateNonAsciiStringWithEncodedSize(encodedSize); + + var result = new string[valueCount]; + for (int i = 0; i < valueCount; i++) + { + result[i] = str; + } + return result; + } + + private static ByteString[] CreateByteStrings(int valueCount, int encodedSize) + { + var str = ParseRawPrimitivesBenchmark.CreateStringWithEncodedSize(encodedSize); + + var result = new ByteString[valueCount]; + for (int i = 0; i < valueCount; i++) + { + result[i] = ByteString.CopyFrom(Encoding.UTF8.GetBytes(str)); + } + return result; + } + } +} diff --git a/csharp/src/Google.Protobuf.Conformance/Conformance.cs b/csharp/src/Google.Protobuf.Conformance/Conformance.cs index 2c0846643e..f26d181a98 100644 --- a/csharp/src/Google.Protobuf.Conformance/Conformance.cs +++ b/csharp/src/Google.Protobuf.Conformance/Conformance.cs @@ -189,11 +189,25 @@ namespace Conformance { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else failure_.WriteTo(output, _repeated_failure_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + failure_.WriteTo(ref output, _repeated_failure_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -513,6 +527,9 @@ namespace Conformance { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (payloadCase_ == PayloadOneofCase.ProtobufPayload) { output.WriteRawTag(10); output.WriteBytes(ProtobufPayload); @@ -552,7 +569,53 @@ namespace Conformance { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (payloadCase_ == PayloadOneofCase.ProtobufPayload) { + output.WriteRawTag(10); + output.WriteBytes(ProtobufPayload); + } + if (payloadCase_ == PayloadOneofCase.JsonPayload) { + output.WriteRawTag(18); + output.WriteString(JsonPayload); + } + if (RequestedOutputFormat != global::Conformance.WireFormat.Unspecified) { + output.WriteRawTag(24); + output.WriteEnum((int) RequestedOutputFormat); + } + if (MessageType.Length != 0) { + output.WriteRawTag(34); + output.WriteString(MessageType); + } + if (TestCategory != global::Conformance.TestCategory.UnspecifiedTest) { + output.WriteRawTag(40); + output.WriteEnum((int) TestCategory); + } + if (jspbEncodingOptions_ != null) { + output.WriteRawTag(50); + output.WriteMessage(JspbEncodingOptions); + } + if (payloadCase_ == PayloadOneofCase.JspbPayload) { + output.WriteRawTag(58); + output.WriteString(JspbPayload); + } + if (payloadCase_ == PayloadOneofCase.TextPayload) { + output.WriteRawTag(66); + output.WriteString(TextPayload); + } + if (PrintUnknownFields != false) { + output.WriteRawTag(72); + output.WriteBool(PrintUnknownFields); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1009,6 +1072,9 @@ namespace Conformance { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (resultCase_ == ResultOneofCase.ParseError) { output.WriteRawTag(10); output.WriteString(ParseError); @@ -1044,7 +1110,49 @@ namespace Conformance { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (resultCase_ == ResultOneofCase.ParseError) { + output.WriteRawTag(10); + output.WriteString(ParseError); + } + if (resultCase_ == ResultOneofCase.RuntimeError) { + output.WriteRawTag(18); + output.WriteString(RuntimeError); + } + if (resultCase_ == ResultOneofCase.ProtobufPayload) { + output.WriteRawTag(26); + output.WriteBytes(ProtobufPayload); + } + if (resultCase_ == ResultOneofCase.JsonPayload) { + output.WriteRawTag(34); + output.WriteString(JsonPayload); + } + if (resultCase_ == ResultOneofCase.Skipped) { + output.WriteRawTag(42); + output.WriteString(Skipped); + } + if (resultCase_ == ResultOneofCase.SerializeError) { + output.WriteRawTag(50); + output.WriteString(SerializeError); + } + if (resultCase_ == ResultOneofCase.JspbPayload) { + output.WriteRawTag(58); + output.WriteString(JspbPayload); + } + if (resultCase_ == ResultOneofCase.TextPayload) { + output.WriteRawTag(66); + output.WriteString(TextPayload); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1299,6 +1407,9 @@ namespace Conformance { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (UseJspbArrayAnyFormat != false) { output.WriteRawTag(8); output.WriteBool(UseJspbArrayAnyFormat); @@ -1306,7 +1417,21 @@ namespace Conformance { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (UseJspbArrayAnyFormat != false) { + output.WriteRawTag(8); + output.WriteBool(UseJspbArrayAnyFormat); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs index 308ccbd649..bbf0061f88 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs @@ -466,6 +466,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else mapInt32Int32_.WriteTo(output, _map_mapInt32Int32_codec); mapInt64Int64_.WriteTo(output, _map_mapInt64Int64_codec); mapUint32Uint32_.WriteTo(output, _map_mapUint32Uint32_codec); @@ -486,7 +489,34 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + mapInt32Int32_.WriteTo(ref output, _map_mapInt32Int32_codec); + mapInt64Int64_.WriteTo(ref output, _map_mapInt64Int64_codec); + mapUint32Uint32_.WriteTo(ref output, _map_mapUint32Uint32_codec); + mapUint64Uint64_.WriteTo(ref output, _map_mapUint64Uint64_codec); + mapSint32Sint32_.WriteTo(ref output, _map_mapSint32Sint32_codec); + mapSint64Sint64_.WriteTo(ref output, _map_mapSint64Sint64_codec); + mapFixed32Fixed32_.WriteTo(ref output, _map_mapFixed32Fixed32_codec); + mapFixed64Fixed64_.WriteTo(ref output, _map_mapFixed64Fixed64_codec); + mapSfixed32Sfixed32_.WriteTo(ref output, _map_mapSfixed32Sfixed32_codec); + mapSfixed64Sfixed64_.WriteTo(ref output, _map_mapSfixed64Sfixed64_codec); + mapInt32Float_.WriteTo(ref output, _map_mapInt32Float_codec); + mapInt32Double_.WriteTo(ref output, _map_mapInt32Double_codec); + mapBoolBool_.WriteTo(ref output, _map_mapBoolBool_codec); + mapStringString_.WriteTo(ref output, _map_mapStringString_codec); + mapInt32Bytes_.WriteTo(ref output, _map_mapInt32Bytes_codec); + mapInt32Enum_.WriteTo(ref output, _map_mapInt32Enum_codec); + mapInt32ForeignMessage_.WriteTo(ref output, _map_mapInt32ForeignMessage_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -790,6 +820,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (testMap_ != null) { output.WriteRawTag(10); output.WriteMessage(TestMap); @@ -797,8 +830,22 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (testMap_ != null) { + output.WriteRawTag(10); + output.WriteMessage(TestMap); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -953,11 +1000,25 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else mapInt32Message_.WriteTo(output, _map_mapInt32Message_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + mapInt32Message_.WriteTo(ref output, _map_mapInt32Message_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1116,12 +1177,27 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else map1_.WriteTo(output, _map_map1_codec); map2_.WriteTo(output, _map_map2_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + map1_.WriteTo(ref output, _map_map1_codec); + map2_.WriteTo(ref output, _map_map2_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1456,6 +1532,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else mapInt32Int32_.WriteTo(output, _map_mapInt32Int32_codec); mapInt64Int64_.WriteTo(output, _map_mapInt64Int64_codec); mapUint32Uint32_.WriteTo(output, _map_mapUint32Uint32_codec); @@ -1474,8 +1553,33 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + mapInt32Int32_.WriteTo(ref output, _map_mapInt32Int32_codec); + mapInt64Int64_.WriteTo(ref output, _map_mapInt64Int64_codec); + mapUint32Uint32_.WriteTo(ref output, _map_mapUint32Uint32_codec); + mapUint64Uint64_.WriteTo(ref output, _map_mapUint64Uint64_codec); + mapSint32Sint32_.WriteTo(ref output, _map_mapSint32Sint32_codec); + mapSint64Sint64_.WriteTo(ref output, _map_mapSint64Sint64_codec); + mapFixed32Fixed32_.WriteTo(ref output, _map_mapFixed32Fixed32_codec); + mapFixed64Fixed64_.WriteTo(ref output, _map_mapFixed64Fixed64_codec); + mapSfixed32Sfixed32_.WriteTo(ref output, _map_mapSfixed32Sfixed32_codec); + mapSfixed64Sfixed64_.WriteTo(ref output, _map_mapSfixed64Sfixed64_codec); + mapInt32Float_.WriteTo(ref output, _map_mapInt32Float_codec); + mapInt32Double_.WriteTo(ref output, _map_mapInt32Double_codec); + mapBoolBool_.WriteTo(ref output, _map_mapBoolBool_codec); + mapInt32Enum_.WriteTo(ref output, _map_mapInt32Enum_codec); + mapInt32ForeignMessage_.WriteTo(ref output, _map_mapInt32ForeignMessage_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -1761,12 +1865,26 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else type_.WriteTo(output, _map_type_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + type_.WriteTo(ref output, _map_type_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -1922,12 +2040,26 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else entry_.WriteTo(output, _map_entry_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + entry_.WriteTo(ref output, _map_entry_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs index eb22955dc3..de1ece351a 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs @@ -2561,6 +2561,9 @@ namespace ProtobufTestMessages.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasOptionalInt32) { output.WriteRawTag(8); output.WriteInt32(OptionalInt32); @@ -2836,7 +2839,289 @@ namespace ProtobufTestMessages.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasOptionalInt32) { + output.WriteRawTag(8); + output.WriteInt32(OptionalInt32); + } + if (HasOptionalInt64) { + output.WriteRawTag(16); + output.WriteInt64(OptionalInt64); + } + if (HasOptionalUint32) { + output.WriteRawTag(24); + output.WriteUInt32(OptionalUint32); + } + if (HasOptionalUint64) { + output.WriteRawTag(32); + output.WriteUInt64(OptionalUint64); + } + if (HasOptionalSint32) { + output.WriteRawTag(40); + output.WriteSInt32(OptionalSint32); + } + if (HasOptionalSint64) { + output.WriteRawTag(48); + output.WriteSInt64(OptionalSint64); + } + if (HasOptionalFixed32) { + output.WriteRawTag(61); + output.WriteFixed32(OptionalFixed32); + } + if (HasOptionalFixed64) { + output.WriteRawTag(65); + output.WriteFixed64(OptionalFixed64); + } + if (HasOptionalSfixed32) { + output.WriteRawTag(77); + output.WriteSFixed32(OptionalSfixed32); + } + if (HasOptionalSfixed64) { + output.WriteRawTag(81); + output.WriteSFixed64(OptionalSfixed64); + } + if (HasOptionalFloat) { + output.WriteRawTag(93); + output.WriteFloat(OptionalFloat); + } + if (HasOptionalDouble) { + output.WriteRawTag(97); + output.WriteDouble(OptionalDouble); + } + if (HasOptionalBool) { + output.WriteRawTag(104); + output.WriteBool(OptionalBool); + } + if (HasOptionalString) { + output.WriteRawTag(114); + output.WriteString(OptionalString); + } + if (HasOptionalBytes) { + output.WriteRawTag(122); + output.WriteBytes(OptionalBytes); + } + if (optionalNestedMessage_ != null) { + output.WriteRawTag(146, 1); + output.WriteMessage(OptionalNestedMessage); + } + if (optionalForeignMessage_ != null) { + output.WriteRawTag(154, 1); + output.WriteMessage(OptionalForeignMessage); + } + if (HasOptionalNestedEnum) { + output.WriteRawTag(168, 1); + output.WriteEnum((int) OptionalNestedEnum); + } + if (HasOptionalForeignEnum) { + output.WriteRawTag(176, 1); + output.WriteEnum((int) OptionalForeignEnum); + } + if (HasOptionalStringPiece) { + output.WriteRawTag(194, 1); + output.WriteString(OptionalStringPiece); + } + if (HasOptionalCord) { + output.WriteRawTag(202, 1); + output.WriteString(OptionalCord); + } + if (recursiveMessage_ != null) { + output.WriteRawTag(218, 1); + output.WriteMessage(RecursiveMessage); + } + repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec); + repeatedInt64_.WriteTo(ref output, _repeated_repeatedInt64_codec); + repeatedUint32_.WriteTo(ref output, _repeated_repeatedUint32_codec); + repeatedUint64_.WriteTo(ref output, _repeated_repeatedUint64_codec); + repeatedSint32_.WriteTo(ref output, _repeated_repeatedSint32_codec); + repeatedSint64_.WriteTo(ref output, _repeated_repeatedSint64_codec); + repeatedFixed32_.WriteTo(ref output, _repeated_repeatedFixed32_codec); + repeatedFixed64_.WriteTo(ref output, _repeated_repeatedFixed64_codec); + repeatedSfixed32_.WriteTo(ref output, _repeated_repeatedSfixed32_codec); + repeatedSfixed64_.WriteTo(ref output, _repeated_repeatedSfixed64_codec); + repeatedFloat_.WriteTo(ref output, _repeated_repeatedFloat_codec); + repeatedDouble_.WriteTo(ref output, _repeated_repeatedDouble_codec); + repeatedBool_.WriteTo(ref output, _repeated_repeatedBool_codec); + repeatedString_.WriteTo(ref output, _repeated_repeatedString_codec); + repeatedBytes_.WriteTo(ref output, _repeated_repeatedBytes_codec); + repeatedNestedMessage_.WriteTo(ref output, _repeated_repeatedNestedMessage_codec); + repeatedForeignMessage_.WriteTo(ref output, _repeated_repeatedForeignMessage_codec); + repeatedNestedEnum_.WriteTo(ref output, _repeated_repeatedNestedEnum_codec); + repeatedForeignEnum_.WriteTo(ref output, _repeated_repeatedForeignEnum_codec); + repeatedStringPiece_.WriteTo(ref output, _repeated_repeatedStringPiece_codec); + repeatedCord_.WriteTo(ref output, _repeated_repeatedCord_codec); + mapInt32Int32_.WriteTo(ref output, _map_mapInt32Int32_codec); + mapInt64Int64_.WriteTo(ref output, _map_mapInt64Int64_codec); + mapUint32Uint32_.WriteTo(ref output, _map_mapUint32Uint32_codec); + mapUint64Uint64_.WriteTo(ref output, _map_mapUint64Uint64_codec); + mapSint32Sint32_.WriteTo(ref output, _map_mapSint32Sint32_codec); + mapSint64Sint64_.WriteTo(ref output, _map_mapSint64Sint64_codec); + mapFixed32Fixed32_.WriteTo(ref output, _map_mapFixed32Fixed32_codec); + mapFixed64Fixed64_.WriteTo(ref output, _map_mapFixed64Fixed64_codec); + mapSfixed32Sfixed32_.WriteTo(ref output, _map_mapSfixed32Sfixed32_codec); + mapSfixed64Sfixed64_.WriteTo(ref output, _map_mapSfixed64Sfixed64_codec); + mapInt32Float_.WriteTo(ref output, _map_mapInt32Float_codec); + mapInt32Double_.WriteTo(ref output, _map_mapInt32Double_codec); + mapBoolBool_.WriteTo(ref output, _map_mapBoolBool_codec); + mapStringString_.WriteTo(ref output, _map_mapStringString_codec); + mapStringBytes_.WriteTo(ref output, _map_mapStringBytes_codec); + mapStringNestedMessage_.WriteTo(ref output, _map_mapStringNestedMessage_codec); + mapStringForeignMessage_.WriteTo(ref output, _map_mapStringForeignMessage_codec); + mapStringNestedEnum_.WriteTo(ref output, _map_mapStringNestedEnum_codec); + mapStringForeignEnum_.WriteTo(ref output, _map_mapStringForeignEnum_codec); + packedInt32_.WriteTo(ref output, _repeated_packedInt32_codec); + packedInt64_.WriteTo(ref output, _repeated_packedInt64_codec); + packedUint32_.WriteTo(ref output, _repeated_packedUint32_codec); + packedUint64_.WriteTo(ref output, _repeated_packedUint64_codec); + packedSint32_.WriteTo(ref output, _repeated_packedSint32_codec); + packedSint64_.WriteTo(ref output, _repeated_packedSint64_codec); + packedFixed32_.WriteTo(ref output, _repeated_packedFixed32_codec); + packedFixed64_.WriteTo(ref output, _repeated_packedFixed64_codec); + packedSfixed32_.WriteTo(ref output, _repeated_packedSfixed32_codec); + packedSfixed64_.WriteTo(ref output, _repeated_packedSfixed64_codec); + packedFloat_.WriteTo(ref output, _repeated_packedFloat_codec); + packedDouble_.WriteTo(ref output, _repeated_packedDouble_codec); + packedBool_.WriteTo(ref output, _repeated_packedBool_codec); + packedNestedEnum_.WriteTo(ref output, _repeated_packedNestedEnum_codec); + unpackedInt32_.WriteTo(ref output, _repeated_unpackedInt32_codec); + unpackedInt64_.WriteTo(ref output, _repeated_unpackedInt64_codec); + unpackedUint32_.WriteTo(ref output, _repeated_unpackedUint32_codec); + unpackedUint64_.WriteTo(ref output, _repeated_unpackedUint64_codec); + unpackedSint32_.WriteTo(ref output, _repeated_unpackedSint32_codec); + unpackedSint64_.WriteTo(ref output, _repeated_unpackedSint64_codec); + unpackedFixed32_.WriteTo(ref output, _repeated_unpackedFixed32_codec); + unpackedFixed64_.WriteTo(ref output, _repeated_unpackedFixed64_codec); + unpackedSfixed32_.WriteTo(ref output, _repeated_unpackedSfixed32_codec); + unpackedSfixed64_.WriteTo(ref output, _repeated_unpackedSfixed64_codec); + unpackedFloat_.WriteTo(ref output, _repeated_unpackedFloat_codec); + unpackedDouble_.WriteTo(ref output, _repeated_unpackedDouble_codec); + unpackedBool_.WriteTo(ref output, _repeated_unpackedBool_codec); + unpackedNestedEnum_.WriteTo(ref output, _repeated_unpackedNestedEnum_codec); + if (HasOneofUint32) { + output.WriteRawTag(248, 6); + output.WriteUInt32(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + output.WriteRawTag(130, 7); + output.WriteMessage(OneofNestedMessage); + } + if (HasOneofString) { + output.WriteRawTag(138, 7); + output.WriteString(OneofString); + } + if (HasOneofBytes) { + output.WriteRawTag(146, 7); + output.WriteBytes(OneofBytes); + } + if (HasOneofBool) { + output.WriteRawTag(152, 7); + output.WriteBool(OneofBool); + } + if (HasOneofUint64) { + output.WriteRawTag(160, 7); + output.WriteUInt64(OneofUint64); + } + if (HasOneofFloat) { + output.WriteRawTag(173, 7); + output.WriteFloat(OneofFloat); + } + if (HasOneofDouble) { + output.WriteRawTag(177, 7); + output.WriteDouble(OneofDouble); + } + if (HasOneofEnum) { + output.WriteRawTag(184, 7); + output.WriteEnum((int) OneofEnum); + } + if (HasData) { + output.WriteRawTag(203, 12); + output.WriteGroup(Data); + output.WriteRawTag(204, 12); + } + if (HasFieldname1) { + output.WriteRawTag(136, 25); + output.WriteInt32(Fieldname1); + } + if (HasFieldName2) { + output.WriteRawTag(144, 25); + output.WriteInt32(FieldName2); + } + if (HasFieldName3) { + output.WriteRawTag(152, 25); + output.WriteInt32(FieldName3); + } + if (HasFieldName4) { + output.WriteRawTag(160, 25); + output.WriteInt32(FieldName4); + } + if (HasField0Name5) { + output.WriteRawTag(168, 25); + output.WriteInt32(Field0Name5); + } + if (HasField0Name6) { + output.WriteRawTag(176, 25); + output.WriteInt32(Field0Name6); + } + if (HasFieldName7) { + output.WriteRawTag(184, 25); + output.WriteInt32(FieldName7); + } + if (HasFieldName8) { + output.WriteRawTag(192, 25); + output.WriteInt32(FieldName8); + } + if (HasFieldName9) { + output.WriteRawTag(200, 25); + output.WriteInt32(FieldName9); + } + if (HasFieldName10) { + output.WriteRawTag(208, 25); + output.WriteInt32(FieldName10); + } + if (HasFIELDNAME11) { + output.WriteRawTag(216, 25); + output.WriteInt32(FIELDNAME11); + } + if (HasFIELDName12) { + output.WriteRawTag(224, 25); + output.WriteInt32(FIELDName12); + } + if (HasFieldName13) { + output.WriteRawTag(232, 25); + output.WriteInt32(FieldName13); + } + if (HasFieldName14) { + output.WriteRawTag(240, 25); + output.WriteInt32(FieldName14); + } + if (HasFieldName15) { + output.WriteRawTag(248, 25); + output.WriteInt32(FieldName15); + } + if (HasFieldName16) { + output.WriteRawTag(128, 26); + output.WriteInt32(FieldName16); + } + if (HasFieldName17) { + output.WriteRawTag(136, 26); + output.WriteInt32(FieldName17); + } + if (HasFieldName18) { + output.WriteRawTag(144, 26); + output.WriteInt32(FieldName18); + } + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -4561,6 +4846,9 @@ namespace ProtobufTestMessages.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasA) { output.WriteRawTag(8); output.WriteInt32(A); @@ -4572,8 +4860,26 @@ namespace ProtobufTestMessages.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (corecursive_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Corecursive); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -4788,6 +5094,9 @@ namespace ProtobufTestMessages.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasGroupInt32) { output.WriteRawTag(208, 12); output.WriteInt32(GroupInt32); @@ -4799,8 +5108,26 @@ namespace ProtobufTestMessages.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasGroupInt32) { + output.WriteRawTag(208, 12); + output.WriteInt32(GroupInt32); + } + if (HasGroupUint32) { + output.WriteRawTag(216, 12); + output.WriteUInt32(GroupUint32); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -4963,13 +5290,29 @@ namespace ProtobufTestMessages.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_extensions != null) { _extensions.WriteTo(output); } if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -5145,6 +5488,9 @@ namespace ProtobufTestMessages.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasStr) { output.WriteRawTag(202, 1); output.WriteString(Str); @@ -5152,7 +5498,21 @@ namespace ProtobufTestMessages.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasStr) { + output.WriteRawTag(202, 1); + output.WriteString(Str); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -5324,6 +5684,9 @@ namespace ProtobufTestMessages.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasI) { output.WriteRawTag(72); output.WriteInt32(I); @@ -5331,7 +5694,21 @@ namespace ProtobufTestMessages.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasI) { + output.WriteRawTag(72); + output.WriteInt32(I); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -5508,6 +5885,9 @@ namespace ProtobufTestMessages.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasC) { output.WriteRawTag(8); output.WriteInt32(C); @@ -5515,7 +5895,21 @@ namespace ProtobufTestMessages.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasC) { + output.WriteRawTag(8); + output.WriteInt32(C); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -5782,6 +6176,9 @@ namespace ProtobufTestMessages.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasOptionalInt32) { output.WriteRawTag(200, 62); output.WriteInt32(OptionalInt32); @@ -5807,8 +6204,40 @@ namespace ProtobufTestMessages.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasOptionalInt32) { + output.WriteRawTag(200, 62); + output.WriteInt32(OptionalInt32); + } + if (HasOptionalString) { + output.WriteRawTag(210, 62); + output.WriteString(OptionalString); + } + if (nestedMessage_ != null) { + output.WriteRawTag(218, 62); + output.WriteMessage(NestedMessage); + } + if (HasOptionalGroup) { + output.WriteRawTag(227, 62); + output.WriteGroup(OptionalGroup); + output.WriteRawTag(228, 62); + } + if (HasOptionalBool) { + output.WriteRawTag(240, 62); + output.WriteBool(OptionalBool); + } + repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -6058,6 +6487,9 @@ namespace ProtobufTestMessages.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasA) { output.WriteRawTag(8); output.WriteInt32(A); @@ -6065,8 +6497,22 @@ namespace ProtobufTestMessages.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs index ebdab60e4a..6f915cb79b 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs @@ -2452,6 +2452,9 @@ namespace ProtobufTestMessages.Proto3 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (OptionalInt32 != 0) { output.WriteRawTag(8); output.WriteInt32(OptionalInt32); @@ -2798,8 +2801,361 @@ namespace ProtobufTestMessages.Proto3 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (OptionalInt32 != 0) { + output.WriteRawTag(8); + output.WriteInt32(OptionalInt32); + } + if (OptionalInt64 != 0L) { + output.WriteRawTag(16); + output.WriteInt64(OptionalInt64); + } + if (OptionalUint32 != 0) { + output.WriteRawTag(24); + output.WriteUInt32(OptionalUint32); + } + if (OptionalUint64 != 0UL) { + output.WriteRawTag(32); + output.WriteUInt64(OptionalUint64); + } + if (OptionalSint32 != 0) { + output.WriteRawTag(40); + output.WriteSInt32(OptionalSint32); + } + if (OptionalSint64 != 0L) { + output.WriteRawTag(48); + output.WriteSInt64(OptionalSint64); + } + if (OptionalFixed32 != 0) { + output.WriteRawTag(61); + output.WriteFixed32(OptionalFixed32); + } + if (OptionalFixed64 != 0UL) { + output.WriteRawTag(65); + output.WriteFixed64(OptionalFixed64); + } + if (OptionalSfixed32 != 0) { + output.WriteRawTag(77); + output.WriteSFixed32(OptionalSfixed32); + } + if (OptionalSfixed64 != 0L) { + output.WriteRawTag(81); + output.WriteSFixed64(OptionalSfixed64); + } + if (OptionalFloat != 0F) { + output.WriteRawTag(93); + output.WriteFloat(OptionalFloat); + } + if (OptionalDouble != 0D) { + output.WriteRawTag(97); + output.WriteDouble(OptionalDouble); + } + if (OptionalBool != false) { + output.WriteRawTag(104); + output.WriteBool(OptionalBool); + } + if (OptionalString.Length != 0) { + output.WriteRawTag(114); + output.WriteString(OptionalString); + } + if (OptionalBytes.Length != 0) { + output.WriteRawTag(122); + output.WriteBytes(OptionalBytes); + } + if (optionalNestedMessage_ != null) { + output.WriteRawTag(146, 1); + output.WriteMessage(OptionalNestedMessage); + } + if (optionalForeignMessage_ != null) { + output.WriteRawTag(154, 1); + output.WriteMessage(OptionalForeignMessage); + } + if (OptionalNestedEnum != global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum.Foo) { + output.WriteRawTag(168, 1); + output.WriteEnum((int) OptionalNestedEnum); + } + if (OptionalForeignEnum != global::ProtobufTestMessages.Proto3.ForeignEnum.ForeignFoo) { + output.WriteRawTag(176, 1); + output.WriteEnum((int) OptionalForeignEnum); + } + if (OptionalAliasedEnum != global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.AliasedEnum.AliasFoo) { + output.WriteRawTag(184, 1); + output.WriteEnum((int) OptionalAliasedEnum); + } + if (OptionalStringPiece.Length != 0) { + output.WriteRawTag(194, 1); + output.WriteString(OptionalStringPiece); + } + if (OptionalCord.Length != 0) { + output.WriteRawTag(202, 1); + output.WriteString(OptionalCord); + } + if (recursiveMessage_ != null) { + output.WriteRawTag(218, 1); + output.WriteMessage(RecursiveMessage); + } + repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec); + repeatedInt64_.WriteTo(ref output, _repeated_repeatedInt64_codec); + repeatedUint32_.WriteTo(ref output, _repeated_repeatedUint32_codec); + repeatedUint64_.WriteTo(ref output, _repeated_repeatedUint64_codec); + repeatedSint32_.WriteTo(ref output, _repeated_repeatedSint32_codec); + repeatedSint64_.WriteTo(ref output, _repeated_repeatedSint64_codec); + repeatedFixed32_.WriteTo(ref output, _repeated_repeatedFixed32_codec); + repeatedFixed64_.WriteTo(ref output, _repeated_repeatedFixed64_codec); + repeatedSfixed32_.WriteTo(ref output, _repeated_repeatedSfixed32_codec); + repeatedSfixed64_.WriteTo(ref output, _repeated_repeatedSfixed64_codec); + repeatedFloat_.WriteTo(ref output, _repeated_repeatedFloat_codec); + repeatedDouble_.WriteTo(ref output, _repeated_repeatedDouble_codec); + repeatedBool_.WriteTo(ref output, _repeated_repeatedBool_codec); + repeatedString_.WriteTo(ref output, _repeated_repeatedString_codec); + repeatedBytes_.WriteTo(ref output, _repeated_repeatedBytes_codec); + repeatedNestedMessage_.WriteTo(ref output, _repeated_repeatedNestedMessage_codec); + repeatedForeignMessage_.WriteTo(ref output, _repeated_repeatedForeignMessage_codec); + repeatedNestedEnum_.WriteTo(ref output, _repeated_repeatedNestedEnum_codec); + repeatedForeignEnum_.WriteTo(ref output, _repeated_repeatedForeignEnum_codec); + repeatedStringPiece_.WriteTo(ref output, _repeated_repeatedStringPiece_codec); + repeatedCord_.WriteTo(ref output, _repeated_repeatedCord_codec); + mapInt32Int32_.WriteTo(ref output, _map_mapInt32Int32_codec); + mapInt64Int64_.WriteTo(ref output, _map_mapInt64Int64_codec); + mapUint32Uint32_.WriteTo(ref output, _map_mapUint32Uint32_codec); + mapUint64Uint64_.WriteTo(ref output, _map_mapUint64Uint64_codec); + mapSint32Sint32_.WriteTo(ref output, _map_mapSint32Sint32_codec); + mapSint64Sint64_.WriteTo(ref output, _map_mapSint64Sint64_codec); + mapFixed32Fixed32_.WriteTo(ref output, _map_mapFixed32Fixed32_codec); + mapFixed64Fixed64_.WriteTo(ref output, _map_mapFixed64Fixed64_codec); + mapSfixed32Sfixed32_.WriteTo(ref output, _map_mapSfixed32Sfixed32_codec); + mapSfixed64Sfixed64_.WriteTo(ref output, _map_mapSfixed64Sfixed64_codec); + mapInt32Float_.WriteTo(ref output, _map_mapInt32Float_codec); + mapInt32Double_.WriteTo(ref output, _map_mapInt32Double_codec); + mapBoolBool_.WriteTo(ref output, _map_mapBoolBool_codec); + mapStringString_.WriteTo(ref output, _map_mapStringString_codec); + mapStringBytes_.WriteTo(ref output, _map_mapStringBytes_codec); + mapStringNestedMessage_.WriteTo(ref output, _map_mapStringNestedMessage_codec); + mapStringForeignMessage_.WriteTo(ref output, _map_mapStringForeignMessage_codec); + mapStringNestedEnum_.WriteTo(ref output, _map_mapStringNestedEnum_codec); + mapStringForeignEnum_.WriteTo(ref output, _map_mapStringForeignEnum_codec); + packedInt32_.WriteTo(ref output, _repeated_packedInt32_codec); + packedInt64_.WriteTo(ref output, _repeated_packedInt64_codec); + packedUint32_.WriteTo(ref output, _repeated_packedUint32_codec); + packedUint64_.WriteTo(ref output, _repeated_packedUint64_codec); + packedSint32_.WriteTo(ref output, _repeated_packedSint32_codec); + packedSint64_.WriteTo(ref output, _repeated_packedSint64_codec); + packedFixed32_.WriteTo(ref output, _repeated_packedFixed32_codec); + packedFixed64_.WriteTo(ref output, _repeated_packedFixed64_codec); + packedSfixed32_.WriteTo(ref output, _repeated_packedSfixed32_codec); + packedSfixed64_.WriteTo(ref output, _repeated_packedSfixed64_codec); + packedFloat_.WriteTo(ref output, _repeated_packedFloat_codec); + packedDouble_.WriteTo(ref output, _repeated_packedDouble_codec); + packedBool_.WriteTo(ref output, _repeated_packedBool_codec); + packedNestedEnum_.WriteTo(ref output, _repeated_packedNestedEnum_codec); + unpackedInt32_.WriteTo(ref output, _repeated_unpackedInt32_codec); + unpackedInt64_.WriteTo(ref output, _repeated_unpackedInt64_codec); + unpackedUint32_.WriteTo(ref output, _repeated_unpackedUint32_codec); + unpackedUint64_.WriteTo(ref output, _repeated_unpackedUint64_codec); + unpackedSint32_.WriteTo(ref output, _repeated_unpackedSint32_codec); + unpackedSint64_.WriteTo(ref output, _repeated_unpackedSint64_codec); + unpackedFixed32_.WriteTo(ref output, _repeated_unpackedFixed32_codec); + unpackedFixed64_.WriteTo(ref output, _repeated_unpackedFixed64_codec); + unpackedSfixed32_.WriteTo(ref output, _repeated_unpackedSfixed32_codec); + unpackedSfixed64_.WriteTo(ref output, _repeated_unpackedSfixed64_codec); + unpackedFloat_.WriteTo(ref output, _repeated_unpackedFloat_codec); + unpackedDouble_.WriteTo(ref output, _repeated_unpackedDouble_codec); + unpackedBool_.WriteTo(ref output, _repeated_unpackedBool_codec); + unpackedNestedEnum_.WriteTo(ref output, _repeated_unpackedNestedEnum_codec); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { + output.WriteRawTag(248, 6); + output.WriteUInt32(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + output.WriteRawTag(130, 7); + output.WriteMessage(OneofNestedMessage); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { + output.WriteRawTag(138, 7); + output.WriteString(OneofString); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { + output.WriteRawTag(146, 7); + output.WriteBytes(OneofBytes); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBool) { + output.WriteRawTag(152, 7); + output.WriteBool(OneofBool); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint64) { + output.WriteRawTag(160, 7); + output.WriteUInt64(OneofUint64); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofFloat) { + output.WriteRawTag(173, 7); + output.WriteFloat(OneofFloat); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofDouble) { + output.WriteRawTag(177, 7); + output.WriteDouble(OneofDouble); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofEnum) { + output.WriteRawTag(184, 7); + output.WriteEnum((int) OneofEnum); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNullValue) { + output.WriteRawTag(192, 7); + output.WriteEnum((int) OneofNullValue); + } + if (optionalBoolWrapper_ != null) { + _single_optionalBoolWrapper_codec.WriteTagAndValue(ref output, OptionalBoolWrapper); + } + if (optionalInt32Wrapper_ != null) { + _single_optionalInt32Wrapper_codec.WriteTagAndValue(ref output, OptionalInt32Wrapper); + } + if (optionalInt64Wrapper_ != null) { + _single_optionalInt64Wrapper_codec.WriteTagAndValue(ref output, OptionalInt64Wrapper); + } + if (optionalUint32Wrapper_ != null) { + _single_optionalUint32Wrapper_codec.WriteTagAndValue(ref output, OptionalUint32Wrapper); + } + if (optionalUint64Wrapper_ != null) { + _single_optionalUint64Wrapper_codec.WriteTagAndValue(ref output, OptionalUint64Wrapper); + } + if (optionalFloatWrapper_ != null) { + _single_optionalFloatWrapper_codec.WriteTagAndValue(ref output, OptionalFloatWrapper); + } + if (optionalDoubleWrapper_ != null) { + _single_optionalDoubleWrapper_codec.WriteTagAndValue(ref output, OptionalDoubleWrapper); + } + if (optionalStringWrapper_ != null) { + _single_optionalStringWrapper_codec.WriteTagAndValue(ref output, OptionalStringWrapper); + } + if (optionalBytesWrapper_ != null) { + _single_optionalBytesWrapper_codec.WriteTagAndValue(ref output, OptionalBytesWrapper); + } + repeatedBoolWrapper_.WriteTo(ref output, _repeated_repeatedBoolWrapper_codec); + repeatedInt32Wrapper_.WriteTo(ref output, _repeated_repeatedInt32Wrapper_codec); + repeatedInt64Wrapper_.WriteTo(ref output, _repeated_repeatedInt64Wrapper_codec); + repeatedUint32Wrapper_.WriteTo(ref output, _repeated_repeatedUint32Wrapper_codec); + repeatedUint64Wrapper_.WriteTo(ref output, _repeated_repeatedUint64Wrapper_codec); + repeatedFloatWrapper_.WriteTo(ref output, _repeated_repeatedFloatWrapper_codec); + repeatedDoubleWrapper_.WriteTo(ref output, _repeated_repeatedDoubleWrapper_codec); + repeatedStringWrapper_.WriteTo(ref output, _repeated_repeatedStringWrapper_codec); + repeatedBytesWrapper_.WriteTo(ref output, _repeated_repeatedBytesWrapper_codec); + if (optionalDuration_ != null) { + output.WriteRawTag(234, 18); + output.WriteMessage(OptionalDuration); + } + if (optionalTimestamp_ != null) { + output.WriteRawTag(242, 18); + output.WriteMessage(OptionalTimestamp); + } + if (optionalFieldMask_ != null) { + output.WriteRawTag(250, 18); + output.WriteMessage(OptionalFieldMask); + } + if (optionalStruct_ != null) { + output.WriteRawTag(130, 19); + output.WriteMessage(OptionalStruct); + } + if (optionalAny_ != null) { + output.WriteRawTag(138, 19); + output.WriteMessage(OptionalAny); + } + if (optionalValue_ != null) { + output.WriteRawTag(146, 19); + output.WriteMessage(OptionalValue); + } + if (OptionalNullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) { + output.WriteRawTag(152, 19); + output.WriteEnum((int) OptionalNullValue); + } + repeatedDuration_.WriteTo(ref output, _repeated_repeatedDuration_codec); + repeatedTimestamp_.WriteTo(ref output, _repeated_repeatedTimestamp_codec); + repeatedFieldmask_.WriteTo(ref output, _repeated_repeatedFieldmask_codec); + repeatedAny_.WriteTo(ref output, _repeated_repeatedAny_codec); + repeatedValue_.WriteTo(ref output, _repeated_repeatedValue_codec); + repeatedListValue_.WriteTo(ref output, _repeated_repeatedListValue_codec); + repeatedStruct_.WriteTo(ref output, _repeated_repeatedStruct_codec); + if (Fieldname1 != 0) { + output.WriteRawTag(136, 25); + output.WriteInt32(Fieldname1); + } + if (FieldName2 != 0) { + output.WriteRawTag(144, 25); + output.WriteInt32(FieldName2); + } + if (FieldName3 != 0) { + output.WriteRawTag(152, 25); + output.WriteInt32(FieldName3); + } + if (FieldName4 != 0) { + output.WriteRawTag(160, 25); + output.WriteInt32(FieldName4); + } + if (Field0Name5 != 0) { + output.WriteRawTag(168, 25); + output.WriteInt32(Field0Name5); + } + if (Field0Name6 != 0) { + output.WriteRawTag(176, 25); + output.WriteInt32(Field0Name6); + } + if (FieldName7 != 0) { + output.WriteRawTag(184, 25); + output.WriteInt32(FieldName7); + } + if (FieldName8 != 0) { + output.WriteRawTag(192, 25); + output.WriteInt32(FieldName8); + } + if (FieldName9 != 0) { + output.WriteRawTag(200, 25); + output.WriteInt32(FieldName9); + } + if (FieldName10 != 0) { + output.WriteRawTag(208, 25); + output.WriteInt32(FieldName10); + } + if (FIELDNAME11 != 0) { + output.WriteRawTag(216, 25); + output.WriteInt32(FIELDNAME11); + } + if (FIELDName12 != 0) { + output.WriteRawTag(224, 25); + output.WriteInt32(FIELDName12); + } + if (FieldName13 != 0) { + output.WriteRawTag(232, 25); + output.WriteInt32(FieldName13); + } + if (FieldName14 != 0) { + output.WriteRawTag(240, 25); + output.WriteInt32(FieldName14); + } + if (FieldName15 != 0) { + output.WriteRawTag(248, 25); + output.WriteInt32(FieldName15); + } + if (FieldName16 != 0) { + output.WriteRawTag(128, 26); + output.WriteInt32(FieldName16); + } + if (FieldName17 != 0) { + output.WriteRawTag(136, 26); + output.WriteInt32(FieldName17); + } + if (FieldName18 != 0) { + output.WriteRawTag(144, 26); + output.WriteInt32(FieldName18); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -5004,6 +5360,9 @@ namespace ProtobufTestMessages.Proto3 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (A != 0) { output.WriteRawTag(8); output.WriteInt32(A); @@ -5015,7 +5374,25 @@ namespace ProtobufTestMessages.Proto3 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (A != 0) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (corecursive_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Corecursive); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -5191,6 +5568,9 @@ namespace ProtobufTestMessages.Proto3 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (C != 0) { output.WriteRawTag(8); output.WriteInt32(C); @@ -5198,7 +5578,21 @@ namespace ProtobufTestMessages.Proto3 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (C != 0) { + output.WriteRawTag(8); + output.WriteInt32(C); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs b/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs index 373f569df3..a843c4ae8b 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs @@ -2822,6 +2822,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasOptionalInt32) { output.WriteRawTag(8); output.WriteInt32(OptionalInt32); @@ -3051,7 +3054,243 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasOptionalInt32) { + output.WriteRawTag(8); + output.WriteInt32(OptionalInt32); + } + if (HasOptionalInt64) { + output.WriteRawTag(16); + output.WriteInt64(OptionalInt64); + } + if (HasOptionalUint32) { + output.WriteRawTag(24); + output.WriteUInt32(OptionalUint32); + } + if (HasOptionalUint64) { + output.WriteRawTag(32); + output.WriteUInt64(OptionalUint64); + } + if (HasOptionalSint32) { + output.WriteRawTag(40); + output.WriteSInt32(OptionalSint32); + } + if (HasOptionalSint64) { + output.WriteRawTag(48); + output.WriteSInt64(OptionalSint64); + } + if (HasOptionalFixed32) { + output.WriteRawTag(61); + output.WriteFixed32(OptionalFixed32); + } + if (HasOptionalFixed64) { + output.WriteRawTag(65); + output.WriteFixed64(OptionalFixed64); + } + if (HasOptionalSfixed32) { + output.WriteRawTag(77); + output.WriteSFixed32(OptionalSfixed32); + } + if (HasOptionalSfixed64) { + output.WriteRawTag(81); + output.WriteSFixed64(OptionalSfixed64); + } + if (HasOptionalFloat) { + output.WriteRawTag(93); + output.WriteFloat(OptionalFloat); + } + if (HasOptionalDouble) { + output.WriteRawTag(97); + output.WriteDouble(OptionalDouble); + } + if (HasOptionalBool) { + output.WriteRawTag(104); + output.WriteBool(OptionalBool); + } + if (HasOptionalString) { + output.WriteRawTag(114); + output.WriteString(OptionalString); + } + if (HasOptionalBytes) { + output.WriteRawTag(122); + output.WriteBytes(OptionalBytes); + } + if (HasOptionalGroup) { + output.WriteRawTag(131, 1); + output.WriteGroup(OptionalGroup); + output.WriteRawTag(132, 1); + } + if (optionalNestedMessage_ != null) { + output.WriteRawTag(146, 1); + output.WriteMessage(OptionalNestedMessage); + } + if (optionalForeignMessage_ != null) { + output.WriteRawTag(154, 1); + output.WriteMessage(OptionalForeignMessage); + } + if (optionalImportMessage_ != null) { + output.WriteRawTag(162, 1); + output.WriteMessage(OptionalImportMessage); + } + if (HasOptionalNestedEnum) { + output.WriteRawTag(168, 1); + output.WriteEnum((int) OptionalNestedEnum); + } + if (HasOptionalForeignEnum) { + output.WriteRawTag(176, 1); + output.WriteEnum((int) OptionalForeignEnum); + } + if (HasOptionalImportEnum) { + output.WriteRawTag(184, 1); + output.WriteEnum((int) OptionalImportEnum); + } + if (HasOptionalStringPiece) { + output.WriteRawTag(194, 1); + output.WriteString(OptionalStringPiece); + } + if (HasOptionalCord) { + output.WriteRawTag(202, 1); + output.WriteString(OptionalCord); + } + if (optionalPublicImportMessage_ != null) { + output.WriteRawTag(210, 1); + output.WriteMessage(OptionalPublicImportMessage); + } + if (optionalLazyMessage_ != null) { + output.WriteRawTag(218, 1); + output.WriteMessage(OptionalLazyMessage); + } + repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec); + repeatedInt64_.WriteTo(ref output, _repeated_repeatedInt64_codec); + repeatedUint32_.WriteTo(ref output, _repeated_repeatedUint32_codec); + repeatedUint64_.WriteTo(ref output, _repeated_repeatedUint64_codec); + repeatedSint32_.WriteTo(ref output, _repeated_repeatedSint32_codec); + repeatedSint64_.WriteTo(ref output, _repeated_repeatedSint64_codec); + repeatedFixed32_.WriteTo(ref output, _repeated_repeatedFixed32_codec); + repeatedFixed64_.WriteTo(ref output, _repeated_repeatedFixed64_codec); + repeatedSfixed32_.WriteTo(ref output, _repeated_repeatedSfixed32_codec); + repeatedSfixed64_.WriteTo(ref output, _repeated_repeatedSfixed64_codec); + repeatedFloat_.WriteTo(ref output, _repeated_repeatedFloat_codec); + repeatedDouble_.WriteTo(ref output, _repeated_repeatedDouble_codec); + repeatedBool_.WriteTo(ref output, _repeated_repeatedBool_codec); + repeatedString_.WriteTo(ref output, _repeated_repeatedString_codec); + repeatedBytes_.WriteTo(ref output, _repeated_repeatedBytes_codec); + repeatedGroup_.WriteTo(ref output, _repeated_repeatedGroup_codec); + repeatedNestedMessage_.WriteTo(ref output, _repeated_repeatedNestedMessage_codec); + repeatedForeignMessage_.WriteTo(ref output, _repeated_repeatedForeignMessage_codec); + repeatedImportMessage_.WriteTo(ref output, _repeated_repeatedImportMessage_codec); + repeatedNestedEnum_.WriteTo(ref output, _repeated_repeatedNestedEnum_codec); + repeatedForeignEnum_.WriteTo(ref output, _repeated_repeatedForeignEnum_codec); + repeatedImportEnum_.WriteTo(ref output, _repeated_repeatedImportEnum_codec); + repeatedStringPiece_.WriteTo(ref output, _repeated_repeatedStringPiece_codec); + repeatedCord_.WriteTo(ref output, _repeated_repeatedCord_codec); + repeatedLazyMessage_.WriteTo(ref output, _repeated_repeatedLazyMessage_codec); + if (HasDefaultInt32) { + output.WriteRawTag(232, 3); + output.WriteInt32(DefaultInt32); + } + if (HasDefaultInt64) { + output.WriteRawTag(240, 3); + output.WriteInt64(DefaultInt64); + } + if (HasDefaultUint32) { + output.WriteRawTag(248, 3); + output.WriteUInt32(DefaultUint32); + } + if (HasDefaultUint64) { + output.WriteRawTag(128, 4); + output.WriteUInt64(DefaultUint64); + } + if (HasDefaultSint32) { + output.WriteRawTag(136, 4); + output.WriteSInt32(DefaultSint32); + } + if (HasDefaultSint64) { + output.WriteRawTag(144, 4); + output.WriteSInt64(DefaultSint64); + } + if (HasDefaultFixed32) { + output.WriteRawTag(157, 4); + output.WriteFixed32(DefaultFixed32); + } + if (HasDefaultFixed64) { + output.WriteRawTag(161, 4); + output.WriteFixed64(DefaultFixed64); + } + if (HasDefaultSfixed32) { + output.WriteRawTag(173, 4); + output.WriteSFixed32(DefaultSfixed32); + } + if (HasDefaultSfixed64) { + output.WriteRawTag(177, 4); + output.WriteSFixed64(DefaultSfixed64); + } + if (HasDefaultFloat) { + output.WriteRawTag(189, 4); + output.WriteFloat(DefaultFloat); + } + if (HasDefaultDouble) { + output.WriteRawTag(193, 4); + output.WriteDouble(DefaultDouble); + } + if (HasDefaultBool) { + output.WriteRawTag(200, 4); + output.WriteBool(DefaultBool); + } + if (HasDefaultString) { + output.WriteRawTag(210, 4); + output.WriteString(DefaultString); + } + if (HasDefaultBytes) { + output.WriteRawTag(218, 4); + output.WriteBytes(DefaultBytes); + } + if (HasDefaultNestedEnum) { + output.WriteRawTag(136, 5); + output.WriteEnum((int) DefaultNestedEnum); + } + if (HasDefaultForeignEnum) { + output.WriteRawTag(144, 5); + output.WriteEnum((int) DefaultForeignEnum); + } + if (HasDefaultImportEnum) { + output.WriteRawTag(152, 5); + output.WriteEnum((int) DefaultImportEnum); + } + if (HasDefaultStringPiece) { + output.WriteRawTag(162, 5); + output.WriteString(DefaultStringPiece); + } + if (HasDefaultCord) { + output.WriteRawTag(170, 5); + output.WriteString(DefaultCord); + } + if (HasOneofUint32) { + output.WriteRawTag(248, 6); + output.WriteUInt32(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + output.WriteRawTag(130, 7); + output.WriteMessage(OneofNestedMessage); + } + if (HasOneofString) { + output.WriteRawTag(138, 7); + output.WriteString(OneofString); + } + if (HasOneofBytes) { + output.WriteRawTag(146, 7); + output.WriteBytes(OneofBytes); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -4269,6 +4508,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasBb) { output.WriteRawTag(8); output.WriteInt32(Bb); @@ -4276,7 +4518,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasBb) { + output.WriteRawTag(8); + output.WriteInt32(Bb); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -4439,6 +4695,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasA) { output.WriteRawTag(136, 1); output.WriteInt32(A); @@ -4446,7 +4705,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(136, 1); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -4613,6 +4886,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasA) { output.WriteRawTag(248, 2); output.WriteInt32(A); @@ -4620,7 +4896,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(248, 2); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -4807,6 +5097,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (child_ != null) { output.WriteRawTag(10); output.WriteMessage(Child); @@ -4819,8 +5112,27 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (child_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Child); + } + if (payload_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Payload); + } + repeatedChild_.WriteTo(ref output, _repeated_repeatedChild_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -5081,6 +5393,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasDeprecatedInt32) { output.WriteRawTag(8); output.WriteInt32(DeprecatedInt32); @@ -5092,8 +5407,26 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasDeprecatedInt32) { + output.WriteRawTag(8); + output.WriteInt32(DeprecatedInt32); + } + if (HasDeprecatedInt32InOneof) { + output.WriteRawTag(16); + output.WriteInt32(DeprecatedInt32InOneof); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -5244,10 +5577,23 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -5427,6 +5773,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasC) { output.WriteRawTag(8); output.WriteInt32(C); @@ -5438,7 +5787,25 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasC) { + output.WriteRawTag(8); + output.WriteInt32(C); + } + if (HasD) { + output.WriteRawTag(16); + output.WriteInt32(D); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -5586,10 +5953,23 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -5718,14 +6098,30 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_extensions != null) { _extensions.WriteTo(output); } if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -5903,6 +6299,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasA) { output.WriteRawTag(136, 1); output.WriteInt32(A); @@ -5910,7 +6309,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(136, 1); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -6077,6 +6490,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasA) { output.WriteRawTag(248, 2); output.WriteInt32(A); @@ -6084,8 +6500,22 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(248, 2); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -6275,6 +6705,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasOptionalGroup) { output.WriteRawTag(131, 1); output.WriteGroup(OptionalGroup); @@ -6287,8 +6720,27 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasOptionalGroup) { + output.WriteRawTag(131, 1); + output.WriteGroup(OptionalGroup); + output.WriteRawTag(132, 1); + } + if (HasOptionalForeignEnum) { + output.WriteRawTag(176, 1); + output.WriteEnum((int) OptionalForeignEnum); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -6475,6 +6927,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasA) { output.WriteRawTag(136, 1); output.WriteInt32(A); @@ -6482,7 +6937,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(136, 1); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -6634,13 +7103,29 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_extensions != null) { _extensions.WriteTo(output); } if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -6790,11 +7275,24 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -6944,6 +7442,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasA) { output.WriteRawTag(136, 1); output.WriteInt32(A); @@ -6951,8 +7452,22 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(136, 1); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -7913,116 +8428,260 @@ namespace Google.Protobuf.TestProtos.Proto2 { _hasBits1 |= 1; c_ = value; } - } - /// Gets whether the "c" field is set - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool HasC { - get { return (_hasBits1 & 1) != 0; } - } - /// Clears the value of the "c" field - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void ClearC() { - _hasBits1 &= ~1; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as TestRequired); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(TestRequired other) { - if (ReferenceEquals(other, null)) { - return false; + } + /// Gets whether the "c" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasC { + get { return (_hasBits1 & 1) != 0; } + } + /// Clears the value of the "c" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearC() { + _hasBits1 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestRequired); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestRequired other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (A != other.A) return false; + if (Dummy2 != other.Dummy2) return false; + if (B != other.B) return false; + if (Dummy4 != other.Dummy4) return false; + if (Dummy5 != other.Dummy5) return false; + if (Dummy6 != other.Dummy6) return false; + if (Dummy7 != other.Dummy7) return false; + if (Dummy8 != other.Dummy8) return false; + if (Dummy9 != other.Dummy9) return false; + if (Dummy10 != other.Dummy10) return false; + if (Dummy11 != other.Dummy11) return false; + if (Dummy12 != other.Dummy12) return false; + if (Dummy13 != other.Dummy13) return false; + if (Dummy14 != other.Dummy14) return false; + if (Dummy15 != other.Dummy15) return false; + if (Dummy16 != other.Dummy16) return false; + if (Dummy17 != other.Dummy17) return false; + if (Dummy18 != other.Dummy18) return false; + if (Dummy19 != other.Dummy19) return false; + if (Dummy20 != other.Dummy20) return false; + if (Dummy21 != other.Dummy21) return false; + if (Dummy22 != other.Dummy22) return false; + if (Dummy23 != other.Dummy23) return false; + if (Dummy24 != other.Dummy24) return false; + if (Dummy25 != other.Dummy25) return false; + if (Dummy26 != other.Dummy26) return false; + if (Dummy27 != other.Dummy27) return false; + if (Dummy28 != other.Dummy28) return false; + if (Dummy29 != other.Dummy29) return false; + if (Dummy30 != other.Dummy30) return false; + if (Dummy31 != other.Dummy31) return false; + if (Dummy32 != other.Dummy32) return false; + if (C != other.C) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (HasA) hash ^= A.GetHashCode(); + if (HasDummy2) hash ^= Dummy2.GetHashCode(); + if (HasB) hash ^= B.GetHashCode(); + if (HasDummy4) hash ^= Dummy4.GetHashCode(); + if (HasDummy5) hash ^= Dummy5.GetHashCode(); + if (HasDummy6) hash ^= Dummy6.GetHashCode(); + if (HasDummy7) hash ^= Dummy7.GetHashCode(); + if (HasDummy8) hash ^= Dummy8.GetHashCode(); + if (HasDummy9) hash ^= Dummy9.GetHashCode(); + if (HasDummy10) hash ^= Dummy10.GetHashCode(); + if (HasDummy11) hash ^= Dummy11.GetHashCode(); + if (HasDummy12) hash ^= Dummy12.GetHashCode(); + if (HasDummy13) hash ^= Dummy13.GetHashCode(); + if (HasDummy14) hash ^= Dummy14.GetHashCode(); + if (HasDummy15) hash ^= Dummy15.GetHashCode(); + if (HasDummy16) hash ^= Dummy16.GetHashCode(); + if (HasDummy17) hash ^= Dummy17.GetHashCode(); + if (HasDummy18) hash ^= Dummy18.GetHashCode(); + if (HasDummy19) hash ^= Dummy19.GetHashCode(); + if (HasDummy20) hash ^= Dummy20.GetHashCode(); + if (HasDummy21) hash ^= Dummy21.GetHashCode(); + if (HasDummy22) hash ^= Dummy22.GetHashCode(); + if (HasDummy23) hash ^= Dummy23.GetHashCode(); + if (HasDummy24) hash ^= Dummy24.GetHashCode(); + if (HasDummy25) hash ^= Dummy25.GetHashCode(); + if (HasDummy26) hash ^= Dummy26.GetHashCode(); + if (HasDummy27) hash ^= Dummy27.GetHashCode(); + if (HasDummy28) hash ^= Dummy28.GetHashCode(); + if (HasDummy29) hash ^= Dummy29.GetHashCode(); + if (HasDummy30) hash ^= Dummy30.GetHashCode(); + if (HasDummy31) hash ^= Dummy31.GetHashCode(); + if (HasDummy32) hash ^= Dummy32.GetHashCode(); + if (HasC) hash ^= C.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasA) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (HasDummy2) { + output.WriteRawTag(16); + output.WriteInt32(Dummy2); + } + if (HasB) { + output.WriteRawTag(24); + output.WriteInt32(B); + } + if (HasDummy4) { + output.WriteRawTag(32); + output.WriteInt32(Dummy4); + } + if (HasDummy5) { + output.WriteRawTag(40); + output.WriteInt32(Dummy5); + } + if (HasDummy6) { + output.WriteRawTag(48); + output.WriteInt32(Dummy6); + } + if (HasDummy7) { + output.WriteRawTag(56); + output.WriteInt32(Dummy7); + } + if (HasDummy8) { + output.WriteRawTag(64); + output.WriteInt32(Dummy8); + } + if (HasDummy9) { + output.WriteRawTag(72); + output.WriteInt32(Dummy9); + } + if (HasDummy10) { + output.WriteRawTag(80); + output.WriteInt32(Dummy10); + } + if (HasDummy11) { + output.WriteRawTag(88); + output.WriteInt32(Dummy11); + } + if (HasDummy12) { + output.WriteRawTag(96); + output.WriteInt32(Dummy12); + } + if (HasDummy13) { + output.WriteRawTag(104); + output.WriteInt32(Dummy13); + } + if (HasDummy14) { + output.WriteRawTag(112); + output.WriteInt32(Dummy14); + } + if (HasDummy15) { + output.WriteRawTag(120); + output.WriteInt32(Dummy15); + } + if (HasDummy16) { + output.WriteRawTag(128, 1); + output.WriteInt32(Dummy16); + } + if (HasDummy17) { + output.WriteRawTag(136, 1); + output.WriteInt32(Dummy17); + } + if (HasDummy18) { + output.WriteRawTag(144, 1); + output.WriteInt32(Dummy18); + } + if (HasDummy19) { + output.WriteRawTag(152, 1); + output.WriteInt32(Dummy19); + } + if (HasDummy20) { + output.WriteRawTag(160, 1); + output.WriteInt32(Dummy20); + } + if (HasDummy21) { + output.WriteRawTag(168, 1); + output.WriteInt32(Dummy21); + } + if (HasDummy22) { + output.WriteRawTag(176, 1); + output.WriteInt32(Dummy22); + } + if (HasDummy23) { + output.WriteRawTag(184, 1); + output.WriteInt32(Dummy23); + } + if (HasDummy24) { + output.WriteRawTag(192, 1); + output.WriteInt32(Dummy24); + } + if (HasDummy25) { + output.WriteRawTag(200, 1); + output.WriteInt32(Dummy25); + } + if (HasDummy26) { + output.WriteRawTag(208, 1); + output.WriteInt32(Dummy26); } - if (ReferenceEquals(other, this)) { - return true; + if (HasDummy27) { + output.WriteRawTag(216, 1); + output.WriteInt32(Dummy27); + } + if (HasDummy28) { + output.WriteRawTag(224, 1); + output.WriteInt32(Dummy28); + } + if (HasDummy29) { + output.WriteRawTag(232, 1); + output.WriteInt32(Dummy29); + } + if (HasDummy30) { + output.WriteRawTag(240, 1); + output.WriteInt32(Dummy30); + } + if (HasDummy31) { + output.WriteRawTag(248, 1); + output.WriteInt32(Dummy31); + } + if (HasDummy32) { + output.WriteRawTag(128, 2); + output.WriteInt32(Dummy32); + } + if (HasC) { + output.WriteRawTag(136, 2); + output.WriteInt32(C); } - if (A != other.A) return false; - if (Dummy2 != other.Dummy2) return false; - if (B != other.B) return false; - if (Dummy4 != other.Dummy4) return false; - if (Dummy5 != other.Dummy5) return false; - if (Dummy6 != other.Dummy6) return false; - if (Dummy7 != other.Dummy7) return false; - if (Dummy8 != other.Dummy8) return false; - if (Dummy9 != other.Dummy9) return false; - if (Dummy10 != other.Dummy10) return false; - if (Dummy11 != other.Dummy11) return false; - if (Dummy12 != other.Dummy12) return false; - if (Dummy13 != other.Dummy13) return false; - if (Dummy14 != other.Dummy14) return false; - if (Dummy15 != other.Dummy15) return false; - if (Dummy16 != other.Dummy16) return false; - if (Dummy17 != other.Dummy17) return false; - if (Dummy18 != other.Dummy18) return false; - if (Dummy19 != other.Dummy19) return false; - if (Dummy20 != other.Dummy20) return false; - if (Dummy21 != other.Dummy21) return false; - if (Dummy22 != other.Dummy22) return false; - if (Dummy23 != other.Dummy23) return false; - if (Dummy24 != other.Dummy24) return false; - if (Dummy25 != other.Dummy25) return false; - if (Dummy26 != other.Dummy26) return false; - if (Dummy27 != other.Dummy27) return false; - if (Dummy28 != other.Dummy28) return false; - if (Dummy29 != other.Dummy29) return false; - if (Dummy30 != other.Dummy30) return false; - if (Dummy31 != other.Dummy31) return false; - if (Dummy32 != other.Dummy32) return false; - if (C != other.C) return false; - return Equals(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (HasA) hash ^= A.GetHashCode(); - if (HasDummy2) hash ^= Dummy2.GetHashCode(); - if (HasB) hash ^= B.GetHashCode(); - if (HasDummy4) hash ^= Dummy4.GetHashCode(); - if (HasDummy5) hash ^= Dummy5.GetHashCode(); - if (HasDummy6) hash ^= Dummy6.GetHashCode(); - if (HasDummy7) hash ^= Dummy7.GetHashCode(); - if (HasDummy8) hash ^= Dummy8.GetHashCode(); - if (HasDummy9) hash ^= Dummy9.GetHashCode(); - if (HasDummy10) hash ^= Dummy10.GetHashCode(); - if (HasDummy11) hash ^= Dummy11.GetHashCode(); - if (HasDummy12) hash ^= Dummy12.GetHashCode(); - if (HasDummy13) hash ^= Dummy13.GetHashCode(); - if (HasDummy14) hash ^= Dummy14.GetHashCode(); - if (HasDummy15) hash ^= Dummy15.GetHashCode(); - if (HasDummy16) hash ^= Dummy16.GetHashCode(); - if (HasDummy17) hash ^= Dummy17.GetHashCode(); - if (HasDummy18) hash ^= Dummy18.GetHashCode(); - if (HasDummy19) hash ^= Dummy19.GetHashCode(); - if (HasDummy20) hash ^= Dummy20.GetHashCode(); - if (HasDummy21) hash ^= Dummy21.GetHashCode(); - if (HasDummy22) hash ^= Dummy22.GetHashCode(); - if (HasDummy23) hash ^= Dummy23.GetHashCode(); - if (HasDummy24) hash ^= Dummy24.GetHashCode(); - if (HasDummy25) hash ^= Dummy25.GetHashCode(); - if (HasDummy26) hash ^= Dummy26.GetHashCode(); - if (HasDummy27) hash ^= Dummy27.GetHashCode(); - if (HasDummy28) hash ^= Dummy28.GetHashCode(); - if (HasDummy29) hash ^= Dummy29.GetHashCode(); - if (HasDummy30) hash ^= Dummy30.GetHashCode(); - if (HasDummy31) hash ^= Dummy31.GetHashCode(); - if (HasDummy32) hash ^= Dummy32.GetHashCode(); - if (HasC) hash ^= C.GetHashCode(); if (_unknownFields != null) { - hash ^= _unknownFields.GetHashCode(); + _unknownFields.WriteTo(output); } - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { if (HasA) { output.WriteRawTag(8); output.WriteInt32(A); @@ -8156,9 +8815,10 @@ namespace Google.Protobuf.TestProtos.Proto2 { output.WriteInt32(C); } if (_unknownFields != null) { - _unknownFields.WriteTo(output); + _unknownFields.WriteTo(ref output); } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -8807,6 +9467,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (optionalMessage_ != null) { output.WriteRawTag(10); output.WriteMessage(OptionalMessage); @@ -8819,7 +9482,26 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (optionalMessage_ != null) { + output.WriteRawTag(10); + output.WriteMessage(OptionalMessage); + } + repeatedMessage_.WriteTo(ref output, _repeated_repeatedMessage_codec); + if (HasDummy) { + output.WriteRawTag(24); + output.WriteInt32(Dummy); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -9027,6 +9709,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (optionalMessage_ != null) { output.WriteRawTag(10); output.WriteMessage(OptionalMessage); @@ -9039,7 +9724,26 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (optionalMessage_ != null) { + output.WriteRawTag(10); + output.WriteMessage(OptionalMessage); + } + repeatedMessage_.WriteTo(ref output, _repeated_repeatedMessage_codec); + if (requiredMessage_ != null) { + output.WriteRawTag(26); + output.WriteMessage(RequiredMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -9232,6 +9936,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (foreignNested_ != null) { output.WriteRawTag(10); output.WriteMessage(ForeignNested); @@ -9239,7 +9946,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (foreignNested_ != null) { + output.WriteRawTag(10); + output.WriteMessage(ForeignNested); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -9385,10 +10106,23 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -9521,13 +10255,29 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_extensions != null) { _extensions.WriteTo(output); } if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -9686,13 +10436,29 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_extensions != null) { _extensions.WriteTo(output); } if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -9905,6 +10671,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasA) { output.WriteRawTag(8); output.WriteInt32(A); @@ -9916,7 +10685,25 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (HasBb) { + output.WriteRawTag(248, 255, 255, 255, 7); + output.WriteInt32(Bb); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -10106,7 +10893,27 @@ namespace Google.Protobuf.TestProtos.Proto2 { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (a_ != null) { + output.WriteRawTag(10); + output.WriteMessage(A); + } + if (HasI) { + output.WriteRawTag(16); + output.WriteInt32(I); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { if (a_ != null) { output.WriteRawTag(10); output.WriteMessage(A); @@ -10116,9 +10923,10 @@ namespace Google.Protobuf.TestProtos.Proto2 { output.WriteInt32(I); } if (_unknownFields != null) { - _unknownFields.WriteTo(output); + _unknownFields.WriteTo(ref output); } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -10316,6 +11124,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (bb_ != null) { output.WriteRawTag(10); output.WriteMessage(Bb); @@ -10328,7 +11139,26 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (bb_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Bb); + } + if (HasSubGroup) { + output.WriteRawTag(19); + output.WriteGroup(SubGroup); + output.WriteRawTag(20); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -10510,6 +11340,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (b_ != null) { output.WriteRawTag(10); output.WriteMessage(B); @@ -10517,7 +11350,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (b_ != null) { + output.WriteRawTag(10); + output.WriteMessage(B); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -10691,6 +11538,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (subMessage_ != null) { output.WriteRawTag(26); output.WriteMessage(SubMessage); @@ -10702,7 +11552,25 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (subMessage_ != null) { + output.WriteRawTag(26); + output.WriteMessage(SubMessage); + } + if (notInThisScc_ != null) { + output.WriteRawTag(34); + output.WriteMessage(NotInThisScc); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -10920,6 +11788,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (a_ != null) { output.WriteRawTag(10); output.WriteMessage(A); @@ -10931,7 +11802,25 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (a_ != null) { + output.WriteRawTag(10); + output.WriteMessage(A); + } + if (HasOptionalInt32) { + output.WriteRawTag(16); + output.WriteInt32(OptionalInt32); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -11102,6 +11991,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (subMessage_ != null) { output.WriteRawTag(10); output.WriteMessage(SubMessage); @@ -11109,7 +12001,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (subMessage_ != null) { + output.WriteRawTag(10); + output.WriteMessage(SubMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -11278,6 +12184,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasSubGroup) { output.WriteRawTag(11); output.WriteGroup(SubGroup); @@ -11286,7 +12195,22 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasSubGroup) { + output.WriteRawTag(11); + output.WriteGroup(SubGroup); + output.WriteRawTag(12); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -11460,6 +12384,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasI) { output.WriteRawTag(16); output.WriteInt32(I); @@ -11467,7 +12394,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasI) { + output.WriteRawTag(16); + output.WriteInt32(I); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -11701,6 +12642,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasA) { output.WriteRawTag(8); output.WriteInt32(A); @@ -11718,7 +12662,31 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (HasFoo) { + output.WriteRawTag(19); + output.WriteGroup(Foo); + output.WriteRawTag(20); + } + if (HasBar) { + output.WriteRawTag(27); + output.WriteGroup(Bar); + output.WriteRawTag(28); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -11929,6 +12897,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasA) { output.WriteRawTag(8); output.WriteInt32(A); @@ -11936,7 +12907,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -12103,6 +13088,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasA) { output.WriteRawTag(8); output.WriteInt32(A); @@ -12110,7 +13098,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -12270,6 +13272,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (subMessage_ != null) { output.WriteRawTag(10); output.WriteMessage(SubMessage); @@ -12277,7 +13282,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (subMessage_ != null) { + output.WriteRawTag(10); + output.WriteMessage(SubMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -12434,6 +13453,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (subMessage_ != null) { output.WriteRawTag(10); output.WriteMessage(SubMessage); @@ -12441,7 +13463,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (subMessage_ != null) { + output.WriteRawTag(10); + output.WriteMessage(SubMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -12601,6 +13637,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (optionalNestedMessage_ != null) { output.WriteRawTag(10); output.WriteMessage(OptionalNestedMessage); @@ -12608,7 +13647,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (optionalNestedMessage_ != null) { + output.WriteRawTag(10); + output.WriteMessage(OptionalNestedMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -12779,12 +13832,27 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else nestedmessageRepeatedInt32_.WriteTo(output, _repeated_nestedmessageRepeatedInt32_codec); nestedmessageRepeatedForeignmessage_.WriteTo(output, _repeated_nestedmessageRepeatedForeignmessage_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + nestedmessageRepeatedInt32_.WriteTo(ref output, _repeated_nestedmessageRepeatedInt32_codec); + nestedmessageRepeatedForeignmessage_.WriteTo(ref output, _repeated_nestedmessageRepeatedForeignmessage_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -13161,6 +14229,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasPrimitiveField) { output.WriteRawTag(8); output.WriteInt32(PrimitiveField); @@ -13194,7 +14265,47 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasPrimitiveField) { + output.WriteRawTag(8); + output.WriteInt32(PrimitiveField); + } + if (HasStringField) { + output.WriteRawTag(18); + output.WriteString(StringField); + } + if (HasEnumField) { + output.WriteRawTag(24); + output.WriteEnum((int) EnumField); + } + if (messageField_ != null) { + output.WriteRawTag(34); + output.WriteMessage(MessageField); + } + if (HasStringPieceField) { + output.WriteRawTag(42); + output.WriteString(StringPieceField); + } + if (HasCordField) { + output.WriteRawTag(50); + output.WriteString(CordField); + } + repeatedPrimitiveField_.WriteTo(ref output, _repeated_repeatedPrimitiveField_codec); + repeatedStringField_.WriteTo(ref output, _repeated_repeatedStringField_codec); + repeatedEnumField_.WriteTo(ref output, _repeated_repeatedEnumField_codec); + repeatedMessageField_.WriteTo(ref output, _repeated_repeatedMessageField_codec); + repeatedStringPieceField_.WriteTo(ref output, _repeated_repeatedStringPieceField_codec); + repeatedCordField_.WriteTo(ref output, _repeated_repeatedCordField_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -13580,6 +14691,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasMyInt) { output.WriteRawTag(8); output.WriteInt64(MyInt); @@ -13602,7 +14716,36 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasMyInt) { + output.WriteRawTag(8); + output.WriteInt64(MyInt); + } + if (HasMyString) { + output.WriteRawTag(90); + output.WriteString(MyString); + } + if (HasMyFloat) { + output.WriteRawTag(173, 6); + output.WriteFloat(MyFloat); + } + if (optionalNestedMessage_ != null) { + output.WriteRawTag(194, 12); + output.WriteMessage(OptionalNestedMessage); + } + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -13880,6 +15023,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasBb) { output.WriteRawTag(8); output.WriteInt32(Bb); @@ -13891,7 +15037,25 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasBb) { + output.WriteRawTag(8); + output.WriteInt32(Bb); + } + if (HasOo) { + output.WriteRawTag(16); + output.WriteInt64(Oo); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -14070,6 +15234,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasMyString) { output.WriteRawTag(10); output.WriteString(MyString); @@ -14077,7 +15244,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasMyString) { + output.WriteRawTag(10); + output.WriteString(MyString); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -14246,6 +15427,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasMyString) { output.WriteRawTag(10); output.WriteString(MyString); @@ -14253,7 +15437,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasMyString) { + output.WriteRawTag(10); + output.WriteString(MyString); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -14415,6 +15613,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasMyString) { output.WriteRawTag(10); output.WriteString(MyString); @@ -14422,7 +15623,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasMyString) { + output.WriteRawTag(10); + output.WriteString(MyString); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -15326,6 +16541,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasEscapedBytes) { output.WriteRawTag(10); output.WriteBytes(EscapedBytes); @@ -15437,7 +16655,125 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasEscapedBytes) { + output.WriteRawTag(10); + output.WriteBytes(EscapedBytes); + } + if (HasLargeUint32) { + output.WriteRawTag(16); + output.WriteUInt32(LargeUint32); + } + if (HasLargeUint64) { + output.WriteRawTag(24); + output.WriteUInt64(LargeUint64); + } + if (HasSmallInt32) { + output.WriteRawTag(32); + output.WriteInt32(SmallInt32); + } + if (HasSmallInt64) { + output.WriteRawTag(40); + output.WriteInt64(SmallInt64); + } + if (HasUtf8String) { + output.WriteRawTag(50); + output.WriteString(Utf8String); + } + if (HasZeroFloat) { + output.WriteRawTag(61); + output.WriteFloat(ZeroFloat); + } + if (HasOneFloat) { + output.WriteRawTag(69); + output.WriteFloat(OneFloat); + } + if (HasSmallFloat) { + output.WriteRawTag(77); + output.WriteFloat(SmallFloat); + } + if (HasNegativeOneFloat) { + output.WriteRawTag(85); + output.WriteFloat(NegativeOneFloat); + } + if (HasNegativeFloat) { + output.WriteRawTag(93); + output.WriteFloat(NegativeFloat); + } + if (HasLargeFloat) { + output.WriteRawTag(101); + output.WriteFloat(LargeFloat); + } + if (HasSmallNegativeFloat) { + output.WriteRawTag(109); + output.WriteFloat(SmallNegativeFloat); + } + if (HasInfDouble) { + output.WriteRawTag(113); + output.WriteDouble(InfDouble); + } + if (HasNegInfDouble) { + output.WriteRawTag(121); + output.WriteDouble(NegInfDouble); + } + if (HasNanDouble) { + output.WriteRawTag(129, 1); + output.WriteDouble(NanDouble); + } + if (HasInfFloat) { + output.WriteRawTag(141, 1); + output.WriteFloat(InfFloat); + } + if (HasNegInfFloat) { + output.WriteRawTag(149, 1); + output.WriteFloat(NegInfFloat); + } + if (HasNanFloat) { + output.WriteRawTag(157, 1); + output.WriteFloat(NanFloat); + } + if (HasCppTrigraph) { + output.WriteRawTag(162, 1); + output.WriteString(CppTrigraph); + } + if (HasReallySmallInt32) { + output.WriteRawTag(168, 1); + output.WriteInt32(ReallySmallInt32); + } + if (HasReallySmallInt64) { + output.WriteRawTag(176, 1); + output.WriteInt64(ReallySmallInt64); + } + if (HasStringWithZero) { + output.WriteRawTag(186, 1); + output.WriteString(StringWithZero); + } + if (HasBytesWithZero) { + output.WriteRawTag(194, 1); + output.WriteBytes(BytesWithZero); + } + if (HasStringPieceWithZero) { + output.WriteRawTag(202, 1); + output.WriteString(StringPieceWithZero); + } + if (HasCordWithZero) { + output.WriteRawTag(210, 1); + output.WriteString(CordWithZero); + } + if (HasReplacementString) { + output.WriteRawTag(218, 1); + output.WriteString(ReplacementString); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -15964,6 +17300,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasSparseEnum) { output.WriteRawTag(8); output.WriteEnum((int) SparseEnum); @@ -15971,7 +17310,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasSparseEnum) { + output.WriteRawTag(8); + output.WriteEnum((int) SparseEnum); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -16134,6 +17487,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasData) { output.WriteRawTag(10); output.WriteString(Data); @@ -16141,7 +17497,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasData) { + output.WriteRawTag(10); + output.WriteString(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -16288,11 +17658,25 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else data_.WriteTo(output, _repeated_data_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + data_.WriteTo(ref output, _repeated_data_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -16447,15 +17831,32 @@ namespace Google.Protobuf.TestProtos.Proto2 { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasData) { + output.WriteRawTag(10); + output.WriteBytes(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { if (HasData) { output.WriteRawTag(10); output.WriteBytes(Data); } if (_unknownFields != null) { - _unknownFields.WriteTo(output); + _unknownFields.WriteTo(ref output); } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -16602,11 +18003,25 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else data_.WriteTo(output, _repeated_data_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + data_.WriteTo(ref output, _repeated_data_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -16768,6 +18183,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasData) { output.WriteRawTag(8); output.WriteInt32(Data); @@ -16775,7 +18193,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasData) { + output.WriteRawTag(8); + output.WriteInt32(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -16938,6 +18370,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasData) { output.WriteRawTag(8); output.WriteUInt32(Data); @@ -16945,7 +18380,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasData) { + output.WriteRawTag(8); + output.WriteUInt32(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -17108,6 +18557,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasData) { output.WriteRawTag(8); output.WriteInt64(Data); @@ -17115,7 +18567,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasData) { + output.WriteRawTag(8); + output.WriteInt64(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -17278,6 +18744,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasData) { output.WriteRawTag(8); output.WriteUInt64(Data); @@ -17285,7 +18754,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasData) { + output.WriteRawTag(8); + output.WriteUInt64(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -17448,6 +18931,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasData) { output.WriteRawTag(8); output.WriteBool(Data); @@ -17455,7 +18941,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasData) { + output.WriteRawTag(8); + output.WriteBool(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -17718,6 +19218,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasFooInt) { output.WriteRawTag(8); output.WriteInt32(FooInt); @@ -17738,7 +19241,34 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasFooInt) { + output.WriteRawTag(8); + output.WriteInt32(FooInt); + } + if (HasFooString) { + output.WriteRawTag(18); + output.WriteString(FooString); + } + if (fooCase_ == FooOneofCase.FooMessage) { + output.WriteRawTag(26); + output.WriteMessage(FooMessage); + } + if (HasFooGroup) { + output.WriteRawTag(35); + output.WriteGroup(FooGroup); + output.WriteRawTag(36); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -18000,6 +19530,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasA) { output.WriteRawTag(40); output.WriteInt32(A); @@ -18011,7 +19544,25 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(40); + output.WriteInt32(A); + } + if (HasB) { + output.WriteRawTag(50); + output.WriteString(B); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -18261,6 +19812,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasFooInt) { output.WriteRawTag(8); output.WriteInt32(FooInt); @@ -18281,7 +19835,34 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasFooInt) { + output.WriteRawTag(8); + output.WriteInt32(FooInt); + } + if (HasFooString) { + output.WriteRawTag(18); + output.WriteString(FooString); + } + if (fooMessage_ != null) { + output.WriteRawTag(26); + output.WriteMessage(FooMessage); + } + if (HasFooGroup) { + output.WriteRawTag(35); + output.WriteGroup(FooGroup); + output.WriteRawTag(36); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -18532,6 +20113,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasA) { output.WriteRawTag(40); output.WriteInt32(A); @@ -18543,7 +20127,25 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(40); + output.WriteInt32(A); + } + if (HasB) { + output.WriteRawTag(50); + output.WriteString(B); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -19209,7 +20811,88 @@ namespace Google.Protobuf.TestProtos.Proto2 { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasFooInt) { + output.WriteRawTag(8); + output.WriteInt32(FooInt); + } + if (HasFooString) { + output.WriteRawTag(18); + output.WriteString(FooString); + } + if (HasFooCord) { + output.WriteRawTag(26); + output.WriteString(FooCord); + } + if (HasFooStringPiece) { + output.WriteRawTag(34); + output.WriteString(FooStringPiece); + } + if (HasFooBytes) { + output.WriteRawTag(42); + output.WriteBytes(FooBytes); + } + if (HasFooEnum) { + output.WriteRawTag(48); + output.WriteEnum((int) FooEnum); + } + if (fooCase_ == FooOneofCase.FooMessage) { + output.WriteRawTag(58); + output.WriteMessage(FooMessage); + } + if (HasFooGroup) { + output.WriteRawTag(67); + output.WriteGroup(FooGroup); + output.WriteRawTag(68); + } + if (fooCase_ == FooOneofCase.FooLazyMessage) { + output.WriteRawTag(90); + output.WriteMessage(FooLazyMessage); + } + if (HasBarInt) { + output.WriteRawTag(96); + output.WriteInt32(BarInt); + } + if (HasBarString) { + output.WriteRawTag(106); + output.WriteString(BarString); + } + if (HasBarCord) { + output.WriteRawTag(114); + output.WriteString(BarCord); + } + if (HasBarStringPiece) { + output.WriteRawTag(122); + output.WriteString(BarStringPiece); + } + if (HasBarBytes) { + output.WriteRawTag(130, 1); + output.WriteBytes(BarBytes); + } + if (HasBarEnum) { + output.WriteRawTag(136, 1); + output.WriteEnum((int) BarEnum); + } + if (HasBazInt) { + output.WriteRawTag(144, 1); + output.WriteInt32(BazInt); + } + if (HasBazString) { + output.WriteRawTag(154, 1); + output.WriteString(BazString); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { if (HasFooInt) { output.WriteRawTag(8); output.WriteInt32(FooInt); @@ -19280,9 +20963,10 @@ namespace Google.Protobuf.TestProtos.Proto2 { output.WriteString(BazString); } if (_unknownFields != null) { - _unknownFields.WriteTo(output); + _unknownFields.WriteTo(ref output); } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -19752,6 +21436,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasA) { output.WriteRawTag(72); output.WriteInt32(A); @@ -19763,7 +21450,25 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(72); + output.WriteInt32(A); + } + if (HasB) { + output.WriteRawTag(82); + output.WriteString(B); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -19957,6 +21662,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasQuxInt) { output.WriteRawTag(8); output.WriteInt64(QuxInt); @@ -19965,7 +21673,22 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasQuxInt) { + output.WriteRawTag(8); + output.WriteInt64(QuxInt); + } + corgeInt_.WriteTo(ref output, _repeated_corgeInt_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -20213,6 +21936,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasFooInt) { output.WriteRawTag(8); output.WriteInt32(FooInt); @@ -20228,7 +21954,29 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasFooInt) { + output.WriteRawTag(8); + output.WriteInt32(FooInt); + } + if (HasFooString) { + output.WriteRawTag(18); + output.WriteString(FooString); + } + if (fooCase_ == FooOneofCase.FooMessage) { + output.WriteRawTag(26); + output.WriteMessage(FooMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -20437,6 +22185,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasRequiredDouble) { output.WriteRawTag(9); output.WriteDouble(RequiredDouble); @@ -20444,7 +22195,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasRequiredDouble) { + output.WriteRawTag(9); + output.WriteDouble(RequiredDouble); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -20596,11 +22361,25 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else foo_.WriteTo(output, _map_foo_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + foo_.WriteTo(ref output, _map_foo_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -20761,6 +22540,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasRequiredInt32) { output.WriteRawTag(8); output.WriteInt32(RequiredInt32); @@ -20768,7 +22550,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasRequiredInt32) { + output.WriteRawTag(8); + output.WriteInt32(RequiredInt32); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -21089,6 +22885,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else packedInt32_.WriteTo(output, _repeated_packedInt32_codec); packedInt64_.WriteTo(output, _repeated_packedInt64_codec); packedUint32_.WriteTo(output, _repeated_packedUint32_codec); @@ -21106,7 +22905,31 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + packedInt32_.WriteTo(ref output, _repeated_packedInt32_codec); + packedInt64_.WriteTo(ref output, _repeated_packedInt64_codec); + packedUint32_.WriteTo(ref output, _repeated_packedUint32_codec); + packedUint64_.WriteTo(ref output, _repeated_packedUint64_codec); + packedSint32_.WriteTo(ref output, _repeated_packedSint32_codec); + packedSint64_.WriteTo(ref output, _repeated_packedSint64_codec); + packedFixed32_.WriteTo(ref output, _repeated_packedFixed32_codec); + packedFixed64_.WriteTo(ref output, _repeated_packedFixed64_codec); + packedSfixed32_.WriteTo(ref output, _repeated_packedSfixed32_codec); + packedSfixed64_.WriteTo(ref output, _repeated_packedSfixed64_codec); + packedFloat_.WriteTo(ref output, _repeated_packedFloat_codec); + packedDouble_.WriteTo(ref output, _repeated_packedDouble_codec); + packedBool_.WriteTo(ref output, _repeated_packedBool_codec); + packedEnum_.WriteTo(ref output, _repeated_packedEnum_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -21580,6 +23403,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else unpackedInt32_.WriteTo(output, _repeated_unpackedInt32_codec); unpackedInt64_.WriteTo(output, _repeated_unpackedInt64_codec); unpackedUint32_.WriteTo(output, _repeated_unpackedUint32_codec); @@ -21597,7 +23423,31 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + unpackedInt32_.WriteTo(ref output, _repeated_unpackedInt32_codec); + unpackedInt64_.WriteTo(ref output, _repeated_unpackedInt64_codec); + unpackedUint32_.WriteTo(ref output, _repeated_unpackedUint32_codec); + unpackedUint64_.WriteTo(ref output, _repeated_unpackedUint64_codec); + unpackedSint32_.WriteTo(ref output, _repeated_unpackedSint32_codec); + unpackedSint64_.WriteTo(ref output, _repeated_unpackedSint64_codec); + unpackedFixed32_.WriteTo(ref output, _repeated_unpackedFixed32_codec); + unpackedFixed64_.WriteTo(ref output, _repeated_unpackedFixed64_codec); + unpackedSfixed32_.WriteTo(ref output, _repeated_unpackedSfixed32_codec); + unpackedSfixed64_.WriteTo(ref output, _repeated_unpackedSfixed64_codec); + unpackedFloat_.WriteTo(ref output, _repeated_unpackedFloat_codec); + unpackedDouble_.WriteTo(ref output, _repeated_unpackedDouble_codec); + unpackedBool_.WriteTo(ref output, _repeated_unpackedBool_codec); + unpackedEnum_.WriteTo(ref output, _repeated_unpackedEnum_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -21894,13 +23744,29 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_extensions != null) { _extensions.WriteTo(output); } if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -22059,13 +23925,29 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_extensions != null) { _extensions.WriteTo(output); } if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -22357,6 +24239,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasScalarExtension) { output.WriteRawTag(133, 125); output.WriteFixed32(ScalarExtension); @@ -22382,7 +24267,39 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasScalarExtension) { + output.WriteRawTag(133, 125); + output.WriteFixed32(ScalarExtension); + } + if (HasEnumExtension) { + output.WriteRawTag(136, 125); + output.WriteEnum((int) EnumExtension); + } + if (HasDynamicEnumExtension) { + output.WriteRawTag(144, 125); + output.WriteEnum((int) DynamicEnumExtension); + } + if (messageExtension_ != null) { + output.WriteRawTag(154, 125); + output.WriteMessage(MessageExtension); + } + if (dynamicMessageExtension_ != null) { + output.WriteRawTag(162, 125); + output.WriteMessage(DynamicMessageExtension); + } + repeatedExtension_.WriteTo(ref output, _repeated_repeatedExtension_codec); + packedExtension_.WriteTo(ref output, _repeated_packedExtension_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -22649,6 +24566,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasDynamicField) { output.WriteRawTag(160, 131, 1); output.WriteInt32(DynamicField); @@ -22656,7 +24576,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasDynamicField) { + output.WriteRawTag(160, 131, 1); + output.WriteInt32(DynamicField); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -22887,6 +24821,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else repeatedFixed32_.WriteTo(output, _repeated_repeatedFixed32_codec); repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec); repeatedFixed64_.WriteTo(output, _repeated_repeatedFixed64_codec); @@ -22896,7 +24833,23 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + repeatedFixed32_.WriteTo(ref output, _repeated_repeatedFixed32_codec); + repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec); + repeatedFixed64_.WriteTo(ref output, _repeated_repeatedFixed64_codec); + repeatedInt64_.WriteTo(ref output, _repeated_repeatedInt64_codec); + repeatedFloat_.WriteTo(ref output, _repeated_repeatedFloat_codec); + repeatedUint64_.WriteTo(ref output, _repeated_repeatedUint64_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -23179,6 +25132,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (requiredAllTypes_ != null) { output.WriteRawTag(10); output.WriteMessage(RequiredAllTypes); @@ -23200,7 +25156,35 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (requiredAllTypes_ != null) { + output.WriteRawTag(10); + output.WriteMessage(RequiredAllTypes); + } + if (optionalAllTypes_ != null) { + output.WriteRawTag(18); + output.WriteMessage(OptionalAllTypes); + } + repeatedAllTypes_.WriteTo(ref output, _repeated_repeatedAllTypes_codec); + if (HasOptionalGroup) { + output.WriteRawTag(83); + output.WriteGroup(OptionalGroup); + output.WriteRawTag(84); + } + repeatedGroup_.WriteTo(ref output, _repeated_repeatedGroup_codec); + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -23539,6 +25523,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else field1_.WriteTo(output, _repeated_field1_codec); field2_.WriteTo(output, _repeated_field2_codec); field3_.WriteTo(output, _repeated_field3_codec); @@ -23549,7 +25536,24 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + field1_.WriteTo(ref output, _repeated_field1_codec); + field2_.WriteTo(ref output, _repeated_field2_codec); + field3_.WriteTo(ref output, _repeated_field3_codec); + group1_.WriteTo(ref output, _repeated_group1_codec); + group2_.WriteTo(ref output, _repeated_group2_codec); + ext1_.WriteTo(ref output, _repeated_ext1_codec); + ext2_.WriteTo(ref output, _repeated_ext2_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -23755,6 +25759,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (field1_ != null) { output.WriteRawTag(90); output.WriteMessage(Field1); @@ -23762,7 +25769,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (field1_ != null) { + output.WriteRawTag(90); + output.WriteMessage(Field1); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -23923,6 +25944,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (field1_ != null) { output.WriteRawTag(170, 1); output.WriteMessage(Field1); @@ -23930,7 +25954,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (field1_ != null) { + output.WriteRawTag(170, 1); + output.WriteMessage(Field1); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -24096,6 +26134,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (optionalGroupAllTypes_ != null) { output.WriteRawTag(90); output.WriteMessage(OptionalGroupAllTypes); @@ -24103,7 +26144,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (optionalGroupAllTypes_ != null) { + output.WriteRawTag(90); + output.WriteMessage(OptionalGroupAllTypes); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -24264,6 +26319,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (repeatedGroupAllTypes_ != null) { output.WriteRawTag(170, 1); output.WriteMessage(RepeatedGroupAllTypes); @@ -24271,7 +26329,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (repeatedGroupAllTypes_ != null) { + output.WriteRawTag(170, 1); + output.WriteMessage(RepeatedGroupAllTypes); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -24463,6 +26535,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasA) { output.WriteRawTag(10); output.WriteString(A); @@ -24470,7 +26545,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasA) { + output.WriteRawTag(10); + output.WriteString(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -24607,10 +26696,23 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -24730,10 +26832,23 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -24853,10 +26968,23 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -24976,10 +27104,23 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -25099,10 +27240,23 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -25222,10 +27376,23 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -25509,6 +27676,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasFieldName1) { output.WriteRawTag(8); output.WriteInt32(FieldName1); @@ -25536,7 +27706,41 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasFieldName1) { + output.WriteRawTag(8); + output.WriteInt32(FieldName1); + } + if (HasFieldName2) { + output.WriteRawTag(16); + output.WriteInt32(FieldName2); + } + if (HasFieldName3) { + output.WriteRawTag(24); + output.WriteInt32(FieldName3); + } + if (HasFieldName4) { + output.WriteRawTag(32); + output.WriteInt32(FieldName4); + } + if (HasFIELDNAME5) { + output.WriteRawTag(40); + output.WriteInt32(FIELDNAME5); + } + if (HasFieldName6) { + output.WriteRawTag(48); + output.WriteInt32(FieldName6); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -26087,6 +28291,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasOptionalInt32) { output.WriteRawTag(128, 199, 255, 255, 15); output.WriteInt32(OptionalInt32); @@ -26141,7 +28348,68 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasOptionalInt32) { + output.WriteRawTag(128, 199, 255, 255, 15); + output.WriteInt32(OptionalInt32); + } + if (HasFixed32) { + output.WriteRawTag(136, 199, 255, 255, 15); + output.WriteInt32(Fixed32); + } + repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec); + packedInt32_.WriteTo(ref output, _repeated_packedInt32_codec); + if (HasOptionalEnum) { + output.WriteRawTag(160, 199, 255, 255, 15); + output.WriteEnum((int) OptionalEnum); + } + if (HasOptionalString) { + output.WriteRawTag(170, 199, 255, 255, 15); + output.WriteString(OptionalString); + } + if (HasOptionalBytes) { + output.WriteRawTag(178, 199, 255, 255, 15); + output.WriteBytes(OptionalBytes); + } + if (optionalMessage_ != null) { + output.WriteRawTag(186, 199, 255, 255, 15); + output.WriteMessage(OptionalMessage); + } + if (HasOptionalGroup) { + output.WriteRawTag(195, 199, 255, 255, 15); + output.WriteGroup(OptionalGroup); + output.WriteRawTag(196, 199, 255, 255, 15); + } + stringStringMap_.WriteTo(ref output, _map_stringStringMap_codec); + if (HasOneofUint32) { + output.WriteRawTag(216, 199, 255, 255, 15); + output.WriteUInt32(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofTestAllTypes) { + output.WriteRawTag(226, 199, 255, 255, 15); + output.WriteMessage(OneofTestAllTypes); + } + if (HasOneofString) { + output.WriteRawTag(234, 199, 255, 255, 15); + output.WriteString(OneofString); + } + if (HasOneofBytes) { + output.WriteRawTag(242, 199, 255, 255, 15); + output.WriteBytes(OneofBytes); + } + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -26544,6 +28812,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasGroupA) { output.WriteRawTag(200, 199, 255, 255, 15); output.WriteInt32(GroupA); @@ -26551,7 +28822,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasGroupA) { + output.WriteRawTag(200, 199, 255, 255, 15); + output.WriteInt32(GroupA); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -26948,6 +29233,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasField1) { output.WriteRawTag(8); output.WriteInt32(Field1); @@ -26990,7 +29278,56 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasField1) { + output.WriteRawTag(8); + output.WriteInt32(Field1); + } + if (HasField2) { + output.WriteRawTag(16); + output.WriteInt32(Field2); + } + if (HasField3) { + output.WriteRawTag(24); + output.WriteInt32(Field3); + } + if (HasField4) { + output.WriteRawTag(32); + output.WriteInt32(Field4); + } + if (HasField6) { + output.WriteRawTag(48); + output.WriteInt32(Field6); + } + if (HasField7) { + output.WriteRawTag(56); + output.WriteInt32(Field7); + } + if (HasField8) { + output.WriteRawTag(64); + output.WriteInt32(Field8); + } + if (HasField9) { + output.WriteRawTag(72); + output.WriteInt32(Field9); + } + if (HasField10) { + output.WriteRawTag(80); + output.WriteInt32(Field10); + } + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestCustomOptionsProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestCustomOptionsProto3.cs index 26455da906..84a4a7eda2 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestCustomOptionsProto3.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestCustomOptionsProto3.cs @@ -379,6 +379,9 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Field1.Length != 0) { output.WriteRawTag(10); output.WriteString(Field1); @@ -390,7 +393,25 @@ namespace UnitTest.Issues.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Field1.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Field1); + } + if (anOneofCase_ == AnOneofOneofCase.OneofField) { + output.WriteRawTag(16); + output.WriteInt32(OneofField); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -558,11 +579,24 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -681,10 +715,23 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -804,11 +851,24 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -927,10 +987,23 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1050,10 +1123,23 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1186,11 +1272,24 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -1309,10 +1408,23 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1432,11 +1544,24 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -1555,11 +1680,24 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -1678,11 +1816,24 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -1801,10 +1952,23 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1979,6 +2143,9 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Foo != 0) { output.WriteRawTag(8); output.WriteInt32(Foo); @@ -1995,7 +2162,30 @@ namespace UnitTest.Issues.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Foo != 0) { + output.WriteRawTag(8); + output.WriteInt32(Foo); + } + if (Foo2 != 0) { + output.WriteRawTag(16); + output.WriteInt32(Foo2); + } + if (Foo3 != 0) { + output.WriteRawTag(24); + output.WriteInt32(Foo3); + } + foo4_.WriteTo(ref output, _repeated_foo4_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -2224,6 +2414,9 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (bar_ != null) { output.WriteRawTag(10); output.WriteMessage(Bar); @@ -2240,7 +2433,30 @@ namespace UnitTest.Issues.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (bar_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Bar); + } + if (Baz != 0) { + output.WriteRawTag(16); + output.WriteInt32(Baz); + } + if (fred_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Fred); + } + barney_.WriteTo(ref output, _repeated_barney_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -2446,6 +2662,9 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Waldo != 0) { output.WriteRawTag(8); output.WriteInt32(Waldo); @@ -2453,8 +2672,22 @@ namespace UnitTest.Issues.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Waldo != 0) { + output.WriteRawTag(8); + output.WriteInt32(Waldo); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -2615,6 +2848,9 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Qux != 0) { output.WriteRawTag(8); output.WriteInt32(Qux); @@ -2622,8 +2858,22 @@ namespace UnitTest.Issues.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Qux != 0) { + output.WriteRawTag(8); + output.WriteInt32(Qux); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -2759,11 +3009,24 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -2930,6 +3193,9 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (I != 0) { output.WriteRawTag(8); output.WriteInt32(I); @@ -2945,7 +3211,29 @@ namespace UnitTest.Issues.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (I != 0) { + output.WriteRawTag(8); + output.WriteInt32(I); + } + if (S.Length != 0) { + output.WriteRawTag(18); + output.WriteString(S); + } + if (sub_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Sub); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -3130,6 +3418,9 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Fieldname != 0) { output.WriteRawTag(8); output.WriteInt32(Fieldname); @@ -3137,8 +3428,22 @@ namespace UnitTest.Issues.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Fieldname != 0) { + output.WriteRawTag(8); + output.WriteInt32(Fieldname); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -3274,11 +3579,24 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -3418,6 +3736,9 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (NestedField != 0) { output.WriteRawTag(8); output.WriteInt32(NestedField); @@ -3425,7 +3746,21 @@ namespace UnitTest.Issues.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (NestedField != 0) { + output.WriteRawTag(8); + output.WriteInt32(NestedField); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.cs index 6ac9f11069..14b054ccbb 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.cs @@ -157,6 +157,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasD) { output.WriteRawTag(8); output.WriteInt32(D); @@ -164,7 +167,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasD) { + output.WriteRawTag(8); + output.WriteInt32(D); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportProto3.cs index 99575b1a3d..ecdf40979c 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportProto3.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportProto3.cs @@ -133,6 +133,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (D != 0) { output.WriteRawTag(8); output.WriteInt32(D); @@ -140,7 +143,21 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (D != 0) { + output.WriteRawTag(8); + output.WriteInt32(D); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublic.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublic.cs index 9bdcf1d686..24c29e9708 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublic.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublic.cs @@ -135,6 +135,9 @@ namespace Google.Protobuf.TestProtos.Proto2 { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasE) { output.WriteRawTag(8); output.WriteInt32(E); @@ -142,7 +145,21 @@ namespace Google.Protobuf.TestProtos.Proto2 { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasE) { + output.WriteRawTag(8); + output.WriteInt32(E); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublicProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublicProto3.cs index dba9165f44..2d77a639fa 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublicProto3.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublicProto3.cs @@ -121,6 +121,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (E != 0) { output.WriteRawTag(8); output.WriteInt32(E); @@ -128,7 +131,21 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (E != 0) { + output.WriteRawTag(8); + output.WriteInt32(E); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936B.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936B.cs index 660dbbdda3..e22bf0f8ff 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936B.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936B.cs @@ -106,10 +106,23 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936C.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936C.cs index b7498d6f23..21d36300f8 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936C.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936C.cs @@ -122,6 +122,9 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (foo_ != null) { output.WriteRawTag(10); output.WriteMessage(Foo); @@ -129,7 +132,21 @@ namespace UnitTest.Issues.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (foo_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Foo); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs index f5c46a9503..e09191a65c 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs @@ -24,36 +24,41 @@ namespace UnitTest.Issues.TestProtos { static UnittestIssuesReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( - "ChV1bml0dGVzdF9pc3N1ZXMucHJvdG8SD3VuaXR0ZXN0X2lzc3VlcyInCghJ", - "c3N1ZTMwNxobCgpOZXN0ZWRPbmNlGg0KC05lc3RlZFR3aWNlIrABChNOZWdh", - "dGl2ZUVudW1NZXNzYWdlEiwKBXZhbHVlGAEgASgOMh0udW5pdHRlc3RfaXNz", - "dWVzLk5lZ2F0aXZlRW51bRIxCgZ2YWx1ZXMYAiADKA4yHS51bml0dGVzdF9p", - "c3N1ZXMuTmVnYXRpdmVFbnVtQgIQABI4Cg1wYWNrZWRfdmFsdWVzGAMgAygO", - "Mh0udW5pdHRlc3RfaXNzdWVzLk5lZ2F0aXZlRW51bUICEAEiEQoPRGVwcmVj", - "YXRlZENoaWxkIrkCChdEZXByZWNhdGVkRmllbGRzTWVzc2FnZRIaCg5Qcmlt", - "aXRpdmVWYWx1ZRgBIAEoBUICGAESGgoOUHJpbWl0aXZlQXJyYXkYAiADKAVC", - "AhgBEjoKDE1lc3NhZ2VWYWx1ZRgDIAEoCzIgLnVuaXR0ZXN0X2lzc3Vlcy5E", - "ZXByZWNhdGVkQ2hpbGRCAhgBEjoKDE1lc3NhZ2VBcnJheRgEIAMoCzIgLnVu", - "aXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkQ2hpbGRCAhgBEjYKCUVudW1WYWx1", - "ZRgFIAEoDjIfLnVuaXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkRW51bUICGAES", - "NgoJRW51bUFycmF5GAYgAygOMh8udW5pdHRlc3RfaXNzdWVzLkRlcHJlY2F0", - "ZWRFbnVtQgIYASIZCglJdGVtRmllbGQSDAoEaXRlbRgBIAEoBSJECg1SZXNl", - "cnZlZE5hbWVzEg0KBXR5cGVzGAEgASgFEhIKCmRlc2NyaXB0b3IYAiABKAUa", - "EAoOU29tZU5lc3RlZFR5cGUioAEKFVRlc3RKc29uRmllbGRPcmRlcmluZxIT", - "CgtwbGFpbl9pbnQzMhgEIAEoBRITCglvMV9zdHJpbmcYAiABKAlIABISCghv", - "MV9pbnQzMhgFIAEoBUgAEhQKDHBsYWluX3N0cmluZxgBIAEoCRISCghvMl9p", - "bnQzMhgGIAEoBUgBEhMKCW8yX3N0cmluZxgDIAEoCUgBQgQKAm8xQgQKAm8y", - "IksKDFRlc3RKc29uTmFtZRIMCgRuYW1lGAEgASgJEhkKC2Rlc2NyaXB0aW9u", - "GAIgASgJUgRkZXNjEhIKBGd1aWQYAyABKAlSBGV4aWQifwoMT25lb2ZNZXJn", - "aW5nEg4KBHRleHQYASABKAlIABI2CgZuZXN0ZWQYAiABKAsyJC51bml0dGVz", - "dF9pc3N1ZXMuT25lb2ZNZXJnaW5nLk5lc3RlZEgAGh4KBk5lc3RlZBIJCgF4", - "GAEgASgFEgkKAXkYAiABKAVCBwoFdmFsdWUqVQoMTmVnYXRpdmVFbnVtEhYK", - "Ek5FR0FUSVZFX0VOVU1fWkVSTxAAEhYKCUZpdmVCZWxvdxD7//////////8B", - "EhUKCE1pbnVzT25lEP///////////wEqLgoORGVwcmVjYXRlZEVudW0SEwoP", - "REVQUkVDQVRFRF9aRVJPEAASBwoDb25lEAFCHaoCGlVuaXRUZXN0Lklzc3Vl", - "cy5UZXN0UHJvdG9zYgZwcm90bzM=")); + "ChV1bml0dGVzdF9pc3N1ZXMucHJvdG8SD3VuaXR0ZXN0X2lzc3VlcxocZ29v", + "Z2xlL3Byb3RvYnVmL3N0cnVjdC5wcm90byInCghJc3N1ZTMwNxobCgpOZXN0", + "ZWRPbmNlGg0KC05lc3RlZFR3aWNlIrABChNOZWdhdGl2ZUVudW1NZXNzYWdl", + "EiwKBXZhbHVlGAEgASgOMh0udW5pdHRlc3RfaXNzdWVzLk5lZ2F0aXZlRW51", + "bRIxCgZ2YWx1ZXMYAiADKA4yHS51bml0dGVzdF9pc3N1ZXMuTmVnYXRpdmVF", + "bnVtQgIQABI4Cg1wYWNrZWRfdmFsdWVzGAMgAygOMh0udW5pdHRlc3RfaXNz", + "dWVzLk5lZ2F0aXZlRW51bUICEAEiEQoPRGVwcmVjYXRlZENoaWxkIrkCChdE", + "ZXByZWNhdGVkRmllbGRzTWVzc2FnZRIaCg5QcmltaXRpdmVWYWx1ZRgBIAEo", + "BUICGAESGgoOUHJpbWl0aXZlQXJyYXkYAiADKAVCAhgBEjoKDE1lc3NhZ2VW", + "YWx1ZRgDIAEoCzIgLnVuaXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkQ2hpbGRC", + "AhgBEjoKDE1lc3NhZ2VBcnJheRgEIAMoCzIgLnVuaXR0ZXN0X2lzc3Vlcy5E", + "ZXByZWNhdGVkQ2hpbGRCAhgBEjYKCUVudW1WYWx1ZRgFIAEoDjIfLnVuaXR0", + "ZXN0X2lzc3Vlcy5EZXByZWNhdGVkRW51bUICGAESNgoJRW51bUFycmF5GAYg", + "AygOMh8udW5pdHRlc3RfaXNzdWVzLkRlcHJlY2F0ZWRFbnVtQgIYASIZCglJ", + "dGVtRmllbGQSDAoEaXRlbRgBIAEoBSJECg1SZXNlcnZlZE5hbWVzEg0KBXR5", + "cGVzGAEgASgFEhIKCmRlc2NyaXB0b3IYAiABKAUaEAoOU29tZU5lc3RlZFR5", + "cGUioAEKFVRlc3RKc29uRmllbGRPcmRlcmluZxITCgtwbGFpbl9pbnQzMhgE", + "IAEoBRITCglvMV9zdHJpbmcYAiABKAlIABISCghvMV9pbnQzMhgFIAEoBUgA", + "EhQKDHBsYWluX3N0cmluZxgBIAEoCRISCghvMl9pbnQzMhgGIAEoBUgBEhMK", + "CW8yX3N0cmluZxgDIAEoCUgBQgQKAm8xQgQKAm8yIksKDFRlc3RKc29uTmFt", + "ZRIMCgRuYW1lGAEgASgJEhkKC2Rlc2NyaXB0aW9uGAIgASgJUgRkZXNjEhIK", + "BGd1aWQYAyABKAlSBGV4aWQifwoMT25lb2ZNZXJnaW5nEg4KBHRleHQYASAB", + "KAlIABI2CgZuZXN0ZWQYAiABKAsyJC51bml0dGVzdF9pc3N1ZXMuT25lb2ZN", + "ZXJnaW5nLk5lc3RlZEgAGh4KBk5lc3RlZBIJCgF4GAEgASgFEgkKAXkYAiAB", + "KAVCBwoFdmFsdWUiawoWTnVsbFZhbHVlT3V0c2lkZVN0cnVjdBIWCgxzdHJp", + "bmdfdmFsdWUYASABKAlIABIwCgpudWxsX3ZhbHVlGAIgASgOMhouZ29vZ2xl", + "LnByb3RvYnVmLk51bGxWYWx1ZUgAQgcKBXZhbHVlIkUKE051bGxWYWx1ZU5v", + "dEluT25lb2YSLgoKbnVsbF92YWx1ZRgCIAEoDjIaLmdvb2dsZS5wcm90b2J1", + "Zi5OdWxsVmFsdWUqVQoMTmVnYXRpdmVFbnVtEhYKEk5FR0FUSVZFX0VOVU1f", + "WkVSTxAAEhYKCUZpdmVCZWxvdxD7//////////8BEhUKCE1pbnVzT25lEP//", + "/////////wEqLgoORGVwcmVjYXRlZEVudW0SEwoPREVQUkVDQVRFRF9aRVJP", + "EAASBwoDb25lEAFCHaoCGlVuaXRUZXN0Lklzc3Vlcy5UZXN0UHJvdG9zYgZw", + "cm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, - new pbr::FileDescriptor[] { }, + new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::UnitTest.Issues.TestProtos.NegativeEnum), typeof(global::UnitTest.Issues.TestProtos.DeprecatedEnum), }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307), global::UnitTest.Issues.TestProtos.Issue307.Parser, null, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce), global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Parser, null, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice), global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice.Parser, null, null, null, null, null)})}), new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NegativeEnumMessage), global::UnitTest.Issues.TestProtos.NegativeEnumMessage.Parser, new[]{ "Value", "Values", "PackedValues" }, null, null, null, null), @@ -63,7 +68,9 @@ namespace UnitTest.Issues.TestProtos { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames), global::UnitTest.Issues.TestProtos.ReservedNames.Parser, new[]{ "Types_", "Descriptor_" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames.Types.SomeNestedType), global::UnitTest.Issues.TestProtos.ReservedNames.Types.SomeNestedType.Parser, null, null, null, null, null)}), new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.TestJsonFieldOrdering), global::UnitTest.Issues.TestProtos.TestJsonFieldOrdering.Parser, new[]{ "PlainInt32", "O1String", "O1Int32", "PlainString", "O2Int32", "O2String" }, new[]{ "O1", "O2" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.TestJsonName), global::UnitTest.Issues.TestProtos.TestJsonName.Parser, new[]{ "Name", "Description", "Guid" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.OneofMerging), global::UnitTest.Issues.TestProtos.OneofMerging.Parser, new[]{ "Text", "Nested" }, new[]{ "Value" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested), global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested.Parser, new[]{ "X", "Y" }, null, null, null, null)}) + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.OneofMerging), global::UnitTest.Issues.TestProtos.OneofMerging.Parser, new[]{ "Text", "Nested" }, new[]{ "Value" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested), global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested.Parser, new[]{ "X", "Y" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NullValueOutsideStruct), global::UnitTest.Issues.TestProtos.NullValueOutsideStruct.Parser, new[]{ "StringValue", "NullValue" }, new[]{ "Value" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NullValueNotInOneof), global::UnitTest.Issues.TestProtos.NullValueNotInOneof.Parser, new[]{ "NullValue" }, null, null, null, null) })); } #endregion @@ -157,10 +164,23 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -282,10 +302,23 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -407,10 +440,23 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -580,6 +626,9 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.Zero) { output.WriteRawTag(8); output.WriteEnum((int) Value); @@ -589,7 +638,23 @@ namespace UnitTest.Issues.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.Zero) { + output.WriteRawTag(8); + output.WriteEnum((int) Value); + } + values_.WriteTo(ref output, _repeated_values_codec); + packedValues_.WriteTo(ref output, _repeated_packedValues_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -747,10 +812,23 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -957,6 +1035,9 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (PrimitiveValue != 0) { output.WriteRawTag(8); output.WriteInt32(PrimitiveValue); @@ -975,7 +1056,32 @@ namespace UnitTest.Issues.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (PrimitiveValue != 0) { + output.WriteRawTag(8); + output.WriteInt32(PrimitiveValue); + } + primitiveArray_.WriteTo(ref output, _repeated_primitiveArray_codec); + if (messageValue_ != null) { + output.WriteRawTag(26); + output.WriteMessage(MessageValue); + } + messageArray_.WriteTo(ref output, _repeated_messageArray_codec); + if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DeprecatedZero) { + output.WriteRawTag(40); + output.WriteEnum((int) EnumValue); + } + enumArray_.WriteTo(ref output, _repeated_enumArray_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1197,6 +1303,9 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Item != 0) { output.WriteRawTag(8); output.WriteInt32(Item); @@ -1204,7 +1313,21 @@ namespace UnitTest.Issues.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Item != 0) { + output.WriteRawTag(8); + output.WriteInt32(Item); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1366,6 +1489,9 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Types_ != 0) { output.WriteRawTag(8); output.WriteInt32(Types_); @@ -1377,7 +1503,25 @@ namespace UnitTest.Issues.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Types_ != 0) { + output.WriteRawTag(8); + output.WriteInt32(Types_); + } + if (Descriptor_ != 0) { + output.WriteRawTag(16); + output.WriteInt32(Descriptor_); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1530,10 +1674,23 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1810,6 +1967,9 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (PlainString.Length != 0) { output.WriteRawTag(10); output.WriteString(PlainString); @@ -1837,7 +1997,41 @@ namespace UnitTest.Issues.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (PlainString.Length != 0) { + output.WriteRawTag(10); + output.WriteString(PlainString); + } + if (o1Case_ == O1OneofCase.O1String) { + output.WriteRawTag(18); + output.WriteString(O1String); + } + if (o2Case_ == O2OneofCase.O2String) { + output.WriteRawTag(26); + output.WriteString(O2String); + } + if (PlainInt32 != 0) { + output.WriteRawTag(32); + output.WriteInt32(PlainInt32); + } + if (o1Case_ == O1OneofCase.O1Int32) { + output.WriteRawTag(40); + output.WriteInt32(O1Int32); + } + if (o2Case_ == O2OneofCase.O2Int32) { + output.WriteRawTag(48); + output.WriteInt32(O2Int32); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -2092,6 +2286,9 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); @@ -2107,7 +2304,29 @@ namespace UnitTest.Issues.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (Description.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Description); + } + if (Guid.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Guid); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -2330,6 +2549,9 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (valueCase_ == ValueOneofCase.Text) { output.WriteRawTag(10); output.WriteString(Text); @@ -2341,7 +2563,25 @@ namespace UnitTest.Issues.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (valueCase_ == ValueOneofCase.Text) { + output.WriteRawTag(10); + output.WriteString(Text); + } + if (valueCase_ == ValueOneofCase.Nested) { + output.WriteRawTag(18); + output.WriteMessage(Nested); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -2535,6 +2775,9 @@ namespace UnitTest.Issues.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (X != 0) { output.WriteRawTag(8); output.WriteInt32(X); @@ -2546,7 +2789,25 @@ namespace UnitTest.Issues.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (X != 0) { + output.WriteRawTag(8); + output.WriteInt32(X); + } + if (Y != 0) { + output.WriteRawTag(16); + output.WriteInt32(Y); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -2630,6 +2891,419 @@ namespace UnitTest.Issues.TestProtos { } + public sealed partial class NullValueOutsideStruct : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NullValueOutsideStruct()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[9]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NullValueOutsideStruct() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NullValueOutsideStruct(NullValueOutsideStruct other) : this() { + switch (other.ValueCase) { + case ValueOneofCase.StringValue: + StringValue = other.StringValue; + break; + case ValueOneofCase.NullValue: + NullValue = other.NullValue; + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NullValueOutsideStruct Clone() { + return new NullValueOutsideStruct(this); + } + + /// Field number for the "string_value" field. + public const int StringValueFieldNumber = 1; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string StringValue { + get { return valueCase_ == ValueOneofCase.StringValue ? (string) value_ : ""; } + set { + value_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + valueCase_ = ValueOneofCase.StringValue; + } + } + + /// Field number for the "null_value" field. + public const int NullValueFieldNumber = 2; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.WellKnownTypes.NullValue NullValue { + get { return valueCase_ == ValueOneofCase.NullValue ? (global::Google.Protobuf.WellKnownTypes.NullValue) value_ : global::Google.Protobuf.WellKnownTypes.NullValue.NullValue; } + set { + value_ = value; + valueCase_ = ValueOneofCase.NullValue; + } + } + + private object value_; + /// Enum of possible cases for the "value" oneof. + public enum ValueOneofCase { + None = 0, + StringValue = 1, + NullValue = 2, + } + private ValueOneofCase valueCase_ = ValueOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ValueOneofCase ValueCase { + get { return valueCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearValue() { + valueCase_ = ValueOneofCase.None; + value_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NullValueOutsideStruct); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NullValueOutsideStruct other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (StringValue != other.StringValue) return false; + if (NullValue != other.NullValue) return false; + if (ValueCase != other.ValueCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (valueCase_ == ValueOneofCase.StringValue) hash ^= StringValue.GetHashCode(); + if (valueCase_ == ValueOneofCase.NullValue) hash ^= NullValue.GetHashCode(); + hash ^= (int) valueCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (valueCase_ == ValueOneofCase.StringValue) { + output.WriteRawTag(10); + output.WriteString(StringValue); + } + if (valueCase_ == ValueOneofCase.NullValue) { + output.WriteRawTag(16); + output.WriteEnum((int) NullValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (valueCase_ == ValueOneofCase.StringValue) { + output.WriteRawTag(10); + output.WriteString(StringValue); + } + if (valueCase_ == ValueOneofCase.NullValue) { + output.WriteRawTag(16); + output.WriteEnum((int) NullValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (valueCase_ == ValueOneofCase.StringValue) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(StringValue); + } + if (valueCase_ == ValueOneofCase.NullValue) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) NullValue); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NullValueOutsideStruct other) { + if (other == null) { + return; + } + switch (other.ValueCase) { + case ValueOneofCase.StringValue: + StringValue = other.StringValue; + break; + case ValueOneofCase.NullValue: + NullValue = other.NullValue; + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + StringValue = input.ReadString(); + break; + } + case 16: { + value_ = input.ReadEnum(); + valueCase_ = ValueOneofCase.NullValue; + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + StringValue = input.ReadString(); + break; + } + case 16: { + value_ = input.ReadEnum(); + valueCase_ = ValueOneofCase.NullValue; + break; + } + } + } + } + #endif + + } + + public sealed partial class NullValueNotInOneof : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NullValueNotInOneof()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[10]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NullValueNotInOneof() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NullValueNotInOneof(NullValueNotInOneof other) : this() { + nullValue_ = other.nullValue_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NullValueNotInOneof Clone() { + return new NullValueNotInOneof(this); + } + + /// Field number for the "null_value" field. + public const int NullValueFieldNumber = 2; + private global::Google.Protobuf.WellKnownTypes.NullValue nullValue_ = global::Google.Protobuf.WellKnownTypes.NullValue.NullValue; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Google.Protobuf.WellKnownTypes.NullValue NullValue { + get { return nullValue_; } + set { + nullValue_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NullValueNotInOneof); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NullValueNotInOneof other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (NullValue != other.NullValue) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (NullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) hash ^= NullValue.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (NullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) { + output.WriteRawTag(16); + output.WriteEnum((int) NullValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (NullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) { + output.WriteRawTag(16); + output.WriteEnum((int) NullValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (NullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) NullValue); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NullValueNotInOneof other) { + if (other == null) { + return; + } + if (other.NullValue != global::Google.Protobuf.WellKnownTypes.NullValue.NullValue) { + NullValue = other.NullValue; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 16: { + NullValue = (global::Google.Protobuf.WellKnownTypes.NullValue) input.ReadEnum(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 16: { + NullValue = (global::Google.Protobuf.WellKnownTypes.NullValue) input.ReadEnum(); + break; + } + } + } + } + #endif + + } + #endregion } diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs index 468e48bd05..b81eb57383 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs @@ -1019,6 +1019,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (SingleInt32 != 0) { output.WriteRawTag(8); output.WriteInt32(SingleInt32); @@ -1148,8 +1151,144 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (SingleInt32 != 0) { + output.WriteRawTag(8); + output.WriteInt32(SingleInt32); + } + if (SingleInt64 != 0L) { + output.WriteRawTag(16); + output.WriteInt64(SingleInt64); + } + if (SingleUint32 != 0) { + output.WriteRawTag(24); + output.WriteUInt32(SingleUint32); + } + if (SingleUint64 != 0UL) { + output.WriteRawTag(32); + output.WriteUInt64(SingleUint64); + } + if (SingleSint32 != 0) { + output.WriteRawTag(40); + output.WriteSInt32(SingleSint32); + } + if (SingleSint64 != 0L) { + output.WriteRawTag(48); + output.WriteSInt64(SingleSint64); + } + if (SingleFixed32 != 0) { + output.WriteRawTag(61); + output.WriteFixed32(SingleFixed32); + } + if (SingleFixed64 != 0UL) { + output.WriteRawTag(65); + output.WriteFixed64(SingleFixed64); + } + if (SingleSfixed32 != 0) { + output.WriteRawTag(77); + output.WriteSFixed32(SingleSfixed32); + } + if (SingleSfixed64 != 0L) { + output.WriteRawTag(81); + output.WriteSFixed64(SingleSfixed64); + } + if (SingleFloat != 0F) { + output.WriteRawTag(93); + output.WriteFloat(SingleFloat); + } + if (SingleDouble != 0D) { + output.WriteRawTag(97); + output.WriteDouble(SingleDouble); + } + if (SingleBool != false) { + output.WriteRawTag(104); + output.WriteBool(SingleBool); + } + if (SingleString.Length != 0) { + output.WriteRawTag(114); + output.WriteString(SingleString); + } + if (SingleBytes.Length != 0) { + output.WriteRawTag(122); + output.WriteBytes(SingleBytes); + } + if (singleNestedMessage_ != null) { + output.WriteRawTag(146, 1); + output.WriteMessage(SingleNestedMessage); + } + if (singleForeignMessage_ != null) { + output.WriteRawTag(154, 1); + output.WriteMessage(SingleForeignMessage); + } + if (singleImportMessage_ != null) { + output.WriteRawTag(162, 1); + output.WriteMessage(SingleImportMessage); + } + if (SingleNestedEnum != global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.Unspecified) { + output.WriteRawTag(168, 1); + output.WriteEnum((int) SingleNestedEnum); + } + if (SingleForeignEnum != global::Google.Protobuf.TestProtos.ForeignEnum.ForeignUnspecified) { + output.WriteRawTag(176, 1); + output.WriteEnum((int) SingleForeignEnum); + } + if (SingleImportEnum != global::Google.Protobuf.TestProtos.ImportEnum.Unspecified) { + output.WriteRawTag(184, 1); + output.WriteEnum((int) SingleImportEnum); + } + if (singlePublicImportMessage_ != null) { + output.WriteRawTag(210, 1); + output.WriteMessage(SinglePublicImportMessage); + } + repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec); + repeatedInt64_.WriteTo(ref output, _repeated_repeatedInt64_codec); + repeatedUint32_.WriteTo(ref output, _repeated_repeatedUint32_codec); + repeatedUint64_.WriteTo(ref output, _repeated_repeatedUint64_codec); + repeatedSint32_.WriteTo(ref output, _repeated_repeatedSint32_codec); + repeatedSint64_.WriteTo(ref output, _repeated_repeatedSint64_codec); + repeatedFixed32_.WriteTo(ref output, _repeated_repeatedFixed32_codec); + repeatedFixed64_.WriteTo(ref output, _repeated_repeatedFixed64_codec); + repeatedSfixed32_.WriteTo(ref output, _repeated_repeatedSfixed32_codec); + repeatedSfixed64_.WriteTo(ref output, _repeated_repeatedSfixed64_codec); + repeatedFloat_.WriteTo(ref output, _repeated_repeatedFloat_codec); + repeatedDouble_.WriteTo(ref output, _repeated_repeatedDouble_codec); + repeatedBool_.WriteTo(ref output, _repeated_repeatedBool_codec); + repeatedString_.WriteTo(ref output, _repeated_repeatedString_codec); + repeatedBytes_.WriteTo(ref output, _repeated_repeatedBytes_codec); + repeatedNestedMessage_.WriteTo(ref output, _repeated_repeatedNestedMessage_codec); + repeatedForeignMessage_.WriteTo(ref output, _repeated_repeatedForeignMessage_codec); + repeatedImportMessage_.WriteTo(ref output, _repeated_repeatedImportMessage_codec); + repeatedNestedEnum_.WriteTo(ref output, _repeated_repeatedNestedEnum_codec); + repeatedForeignEnum_.WriteTo(ref output, _repeated_repeatedForeignEnum_codec); + repeatedImportEnum_.WriteTo(ref output, _repeated_repeatedImportEnum_codec); + repeatedPublicImportMessage_.WriteTo(ref output, _repeated_repeatedPublicImportMessage_codec); + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { + output.WriteRawTag(248, 6); + output.WriteUInt32(OneofUint32); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + output.WriteRawTag(130, 7); + output.WriteMessage(OneofNestedMessage); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { + output.WriteRawTag(138, 7); + output.WriteString(OneofString); + } + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { + output.WriteRawTag(146, 7); + output.WriteBytes(OneofBytes); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -1968,6 +2107,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Bb != 0) { output.WriteRawTag(8); output.WriteInt32(Bb); @@ -1975,7 +2117,21 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Bb != 0) { + output.WriteRawTag(8); + output.WriteInt32(Bb); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -2158,6 +2314,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (child_ != null) { output.WriteRawTag(10); output.WriteMessage(Child); @@ -2170,8 +2329,27 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (child_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Child); + } + if (payload_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Payload); + } + repeatedChild_.WriteTo(ref output, _repeated_repeatedChild_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -2361,6 +2539,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (DeprecatedInt32 != 0) { output.WriteRawTag(8); output.WriteInt32(DeprecatedInt32); @@ -2368,8 +2549,22 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (DeprecatedInt32 != 0) { + output.WriteRawTag(8); + output.WriteInt32(DeprecatedInt32); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -2520,6 +2715,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (C != 0) { output.WriteRawTag(8); output.WriteInt32(C); @@ -2527,8 +2725,22 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (C != 0) { + output.WriteRawTag(8); + output.WriteInt32(C); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -2661,10 +2873,23 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -2801,6 +3026,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (foreignNested_ != null) { output.WriteRawTag(10); output.WriteMessage(ForeignNested); @@ -2808,7 +3036,21 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (foreignNested_ != null) { + output.WriteRawTag(10); + output.WriteMessage(ForeignNested); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -2986,6 +3228,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (A != 0) { output.WriteRawTag(8); output.WriteInt32(A); @@ -2997,8 +3242,26 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (A != 0) { + output.WriteRawTag(8); + output.WriteInt32(A); + } + if (Bb != 0) { + output.WriteRawTag(248, 255, 255, 255, 7); + output.WriteInt32(Bb); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -3173,6 +3436,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (a_ != null) { output.WriteRawTag(10); output.WriteMessage(A); @@ -3184,7 +3450,25 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (a_ != null) { + output.WriteRawTag(10); + output.WriteMessage(A); + } + if (I != 0) { + output.WriteRawTag(16); + output.WriteInt32(I); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -3358,6 +3642,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (bb_ != null) { output.WriteRawTag(10); output.WriteMessage(Bb); @@ -3365,8 +3652,22 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (bb_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Bb); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -3536,6 +3837,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (a_ != null) { output.WriteRawTag(10); output.WriteMessage(A); @@ -3547,8 +3851,26 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (a_ != null) { + output.WriteRawTag(10); + output.WriteMessage(A); + } + if (OptionalInt32 != 0) { + output.WriteRawTag(16); + output.WriteInt32(OptionalInt32); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -3718,6 +4040,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Value != global::Google.Protobuf.TestProtos.TestEnumWithDupValue.Unspecified) { output.WriteRawTag(8); output.WriteEnum((int) Value); @@ -3725,7 +4050,21 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value != global::Google.Protobuf.TestProtos.TestEnumWithDupValue.Unspecified) { + output.WriteRawTag(8); + output.WriteEnum((int) Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -3971,6 +4310,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (PrimitiveField != 0) { output.WriteRawTag(8); output.WriteInt32(PrimitiveField); @@ -3994,8 +4336,38 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (PrimitiveField != 0) { + output.WriteRawTag(8); + output.WriteInt32(PrimitiveField); + } + if (StringField.Length != 0) { + output.WriteRawTag(18); + output.WriteString(StringField); + } + if (EnumField != global::Google.Protobuf.TestProtos.ForeignEnum.ForeignUnspecified) { + output.WriteRawTag(24); + output.WriteEnum((int) EnumField); + } + if (messageField_ != null) { + output.WriteRawTag(34); + output.WriteMessage(MessageField); + } + repeatedPrimitiveField_.WriteTo(ref output, _repeated_repeatedPrimitiveField_codec); + repeatedStringField_.WriteTo(ref output, _repeated_repeatedStringField_codec); + repeatedEnumField_.WriteTo(ref output, _repeated_repeatedEnumField_codec); + repeatedMessageField_.WriteTo(ref output, _repeated_repeatedMessageField_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -4283,6 +4655,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (MyInt != 0L) { output.WriteRawTag(8); output.WriteInt64(MyInt); @@ -4302,7 +4677,33 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (MyInt != 0L) { + output.WriteRawTag(8); + output.WriteInt64(MyInt); + } + if (MyString.Length != 0) { + output.WriteRawTag(90); + output.WriteString(MyString); + } + if (MyFloat != 0F) { + output.WriteRawTag(173, 6); + output.WriteFloat(MyFloat); + } + if (singleNestedMessage_ != null) { + output.WriteRawTag(194, 12); + output.WriteMessage(SingleNestedMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -4522,6 +4923,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Bb != 0) { output.WriteRawTag(8); output.WriteInt32(Bb); @@ -4533,8 +4937,26 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Bb != 0) { + output.WriteRawTag(8); + output.WriteInt32(Bb); + } + if (Oo != 0L) { + output.WriteRawTag(16); + output.WriteInt64(Oo); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -4700,6 +5122,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.Unspecified) { output.WriteRawTag(8); output.WriteEnum((int) SparseEnum); @@ -4707,8 +5132,22 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.Unspecified) { + output.WriteRawTag(8); + output.WriteEnum((int) SparseEnum); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -4858,6 +5297,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Data.Length != 0) { output.WriteRawTag(10); output.WriteString(Data); @@ -4865,8 +5307,22 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Data.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -5012,11 +5468,25 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else data_.WriteTo(output, _repeated_data_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + data_.WriteTo(ref output, _repeated_data_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -5159,15 +5629,32 @@ namespace Google.Protobuf.TestProtos { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Data.Length != 0) { + output.WriteRawTag(10); + output.WriteBytes(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { if (Data.Length != 0) { output.WriteRawTag(10); output.WriteBytes(Data); } if (_unknownFields != null) { - _unknownFields.WriteTo(output); + _unknownFields.WriteTo(ref output); } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -5315,6 +5802,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Data.Length != 0) { output.WriteRawTag(10); output.WriteBytes(Data); @@ -5322,7 +5812,21 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Data.Length != 0) { + output.WriteRawTag(10); + output.WriteBytes(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -5473,6 +5977,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Data != 0) { output.WriteRawTag(8); output.WriteInt32(Data); @@ -5480,7 +5987,21 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Data != 0) { + output.WriteRawTag(8); + output.WriteInt32(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -5628,6 +6149,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Data != 0) { output.WriteRawTag(8); output.WriteUInt32(Data); @@ -5635,7 +6159,21 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Data != 0) { + output.WriteRawTag(8); + output.WriteUInt32(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -5783,6 +6321,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Data != 0L) { output.WriteRawTag(8); output.WriteInt64(Data); @@ -5790,7 +6331,21 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Data != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -5938,6 +6493,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Data != 0UL) { output.WriteRawTag(8); output.WriteUInt64(Data); @@ -5945,7 +6503,21 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Data != 0UL) { + output.WriteRawTag(8); + output.WriteUInt64(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -6093,6 +6665,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Data != false) { output.WriteRawTag(8); output.WriteBool(Data); @@ -6100,7 +6675,21 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Data != false) { + output.WriteRawTag(8); + output.WriteBool(Data); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -6310,6 +6899,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (fooCase_ == FooOneofCase.FooInt) { output.WriteRawTag(8); output.WriteInt32(FooInt); @@ -6325,7 +6917,29 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (fooCase_ == FooOneofCase.FooInt) { + output.WriteRawTag(8); + output.WriteInt32(FooInt); + } + if (fooCase_ == FooOneofCase.FooString) { + output.WriteRawTag(18); + output.WriteString(FooString); + } + if (fooCase_ == FooOneofCase.FooMessage) { + output.WriteRawTag(26); + output.WriteMessage(FooMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -6685,6 +7299,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else packedInt32_.WriteTo(output, _repeated_packedInt32_codec); packedInt64_.WriteTo(output, _repeated_packedInt64_codec); packedUint32_.WriteTo(output, _repeated_packedUint32_codec); @@ -6702,7 +7319,31 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + packedInt32_.WriteTo(ref output, _repeated_packedInt32_codec); + packedInt64_.WriteTo(ref output, _repeated_packedInt64_codec); + packedUint32_.WriteTo(ref output, _repeated_packedUint32_codec); + packedUint64_.WriteTo(ref output, _repeated_packedUint64_codec); + packedSint32_.WriteTo(ref output, _repeated_packedSint32_codec); + packedSint64_.WriteTo(ref output, _repeated_packedSint64_codec); + packedFixed32_.WriteTo(ref output, _repeated_packedFixed32_codec); + packedFixed64_.WriteTo(ref output, _repeated_packedFixed64_codec); + packedSfixed32_.WriteTo(ref output, _repeated_packedSfixed32_codec); + packedSfixed64_.WriteTo(ref output, _repeated_packedSfixed64_codec); + packedFloat_.WriteTo(ref output, _repeated_packedFloat_codec); + packedDouble_.WriteTo(ref output, _repeated_packedDouble_codec); + packedBool_.WriteTo(ref output, _repeated_packedBool_codec); + packedEnum_.WriteTo(ref output, _repeated_packedEnum_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -7176,6 +7817,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else unpackedInt32_.WriteTo(output, _repeated_unpackedInt32_codec); unpackedInt64_.WriteTo(output, _repeated_unpackedInt64_codec); unpackedUint32_.WriteTo(output, _repeated_unpackedUint32_codec); @@ -7193,7 +7837,31 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + unpackedInt32_.WriteTo(ref output, _repeated_unpackedInt32_codec); + unpackedInt64_.WriteTo(ref output, _repeated_unpackedInt64_codec); + unpackedUint32_.WriteTo(ref output, _repeated_unpackedUint32_codec); + unpackedUint64_.WriteTo(ref output, _repeated_unpackedUint64_codec); + unpackedSint32_.WriteTo(ref output, _repeated_unpackedSint32_codec); + unpackedSint64_.WriteTo(ref output, _repeated_unpackedSint64_codec); + unpackedFixed32_.WriteTo(ref output, _repeated_unpackedFixed32_codec); + unpackedFixed64_.WriteTo(ref output, _repeated_unpackedFixed64_codec); + unpackedSfixed32_.WriteTo(ref output, _repeated_unpackedSfixed32_codec); + unpackedSfixed64_.WriteTo(ref output, _repeated_unpackedSfixed64_codec); + unpackedFloat_.WriteTo(ref output, _repeated_unpackedFloat_codec); + unpackedDouble_.WriteTo(ref output, _repeated_unpackedDouble_codec); + unpackedBool_.WriteTo(ref output, _repeated_unpackedBool_codec); + unpackedEnum_.WriteTo(ref output, _repeated_unpackedEnum_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -7573,6 +8241,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else repeatedFixed32_.WriteTo(output, _repeated_repeatedFixed32_codec); repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec); repeatedFixed64_.WriteTo(output, _repeated_repeatedFixed64_codec); @@ -7582,7 +8253,23 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + repeatedFixed32_.WriteTo(ref output, _repeated_repeatedFixed32_codec); + repeatedInt32_.WriteTo(ref output, _repeated_repeatedInt32_codec); + repeatedFixed64_.WriteTo(ref output, _repeated_repeatedFixed64_codec); + repeatedInt64_.WriteTo(ref output, _repeated_repeatedInt64_codec); + repeatedFloat_.WriteTo(ref output, _repeated_repeatedFloat_codec); + repeatedUint64_.WriteTo(ref output, _repeated_repeatedUint64_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -7791,6 +8478,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (A.Length != 0) { output.WriteRawTag(10); output.WriteString(A); @@ -7798,7 +8488,21 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (A.Length != 0) { + output.WriteRawTag(10); + output.WriteString(A); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -7935,10 +8639,23 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -8058,10 +8775,23 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -8181,10 +8911,23 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -8304,10 +9047,23 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -8427,10 +9183,23 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -8550,10 +9319,23 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -8673,10 +9455,23 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -8816,6 +9611,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Text.Length != 0) { output.WriteRawTag(10); output.WriteString(Text); @@ -8823,7 +9621,21 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Text.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Text); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -8989,6 +9801,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (NestedText.Length != 0) { output.WriteRawTag(10); output.WriteString(NestedText); @@ -8996,7 +9811,21 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (NestedText.Length != 0) { + output.WriteRawTag(10); + output.WriteString(NestedText); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs index c8cd7f7aa3..451709f4dd 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs @@ -622,6 +622,9 @@ namespace ProtobufUnittest { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasOptionalInt32) { output.WriteRawTag(8); output.WriteInt32(OptionalInt32); @@ -709,7 +712,101 @@ namespace ProtobufUnittest { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasOptionalInt32) { + output.WriteRawTag(8); + output.WriteInt32(OptionalInt32); + } + if (HasOptionalInt64) { + output.WriteRawTag(16); + output.WriteInt64(OptionalInt64); + } + if (HasOptionalUint32) { + output.WriteRawTag(24); + output.WriteUInt32(OptionalUint32); + } + if (HasOptionalUint64) { + output.WriteRawTag(32); + output.WriteUInt64(OptionalUint64); + } + if (HasOptionalSint32) { + output.WriteRawTag(40); + output.WriteSInt32(OptionalSint32); + } + if (HasOptionalSint64) { + output.WriteRawTag(48); + output.WriteSInt64(OptionalSint64); + } + if (HasOptionalFixed32) { + output.WriteRawTag(61); + output.WriteFixed32(OptionalFixed32); + } + if (HasOptionalFixed64) { + output.WriteRawTag(65); + output.WriteFixed64(OptionalFixed64); + } + if (HasOptionalSfixed32) { + output.WriteRawTag(77); + output.WriteSFixed32(OptionalSfixed32); + } + if (HasOptionalSfixed64) { + output.WriteRawTag(81); + output.WriteSFixed64(OptionalSfixed64); + } + if (HasOptionalFloat) { + output.WriteRawTag(93); + output.WriteFloat(OptionalFloat); + } + if (HasOptionalDouble) { + output.WriteRawTag(97); + output.WriteDouble(OptionalDouble); + } + if (HasOptionalBool) { + output.WriteRawTag(104); + output.WriteBool(OptionalBool); + } + if (HasOptionalString) { + output.WriteRawTag(114); + output.WriteString(OptionalString); + } + if (HasOptionalBytes) { + output.WriteRawTag(122); + output.WriteBytes(OptionalBytes); + } + if (HasOptionalCord) { + output.WriteRawTag(130, 1); + output.WriteString(OptionalCord); + } + if (optionalNestedMessage_ != null) { + output.WriteRawTag(146, 1); + output.WriteMessage(OptionalNestedMessage); + } + if (lazyNestedMessage_ != null) { + output.WriteRawTag(154, 1); + output.WriteMessage(LazyNestedMessage); + } + if (HasOptionalNestedEnum) { + output.WriteRawTag(168, 1); + output.WriteEnum((int) OptionalNestedEnum); + } + if (SingularInt32 != 0) { + output.WriteRawTag(176, 1); + output.WriteInt32(SingularInt32); + } + if (SingularInt64 != 0L) { + output.WriteRawTag(184, 1); + output.WriteInt64(SingularInt64); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1186,6 +1283,9 @@ namespace ProtobufUnittest { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasBb) { output.WriteRawTag(8); output.WriteInt32(Bb); @@ -1193,8 +1293,22 @@ namespace ProtobufUnittest { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasBb) { + output.WriteRawTag(8); + output.WriteInt32(Bb); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestSelfreferentialOptions.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestSelfreferentialOptions.cs index 4365368acc..7ed1580ab2 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestSelfreferentialOptions.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestSelfreferentialOptions.cs @@ -203,6 +203,9 @@ namespace UnitTest.Issues.TestProtos.SelfreferentialOptions { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasIntOpt) { output.WriteRawTag(8); output.WriteInt32(IntOpt); @@ -217,7 +220,28 @@ namespace UnitTest.Issues.TestProtos.SelfreferentialOptions { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasIntOpt) { + output.WriteRawTag(8); + output.WriteInt32(IntOpt); + } + if (HasFoo) { + output.WriteRawTag(16); + output.WriteInt32(Foo); + } + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs index 30c906cd40..996e928cfd 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs @@ -535,6 +535,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (anyField_ != null) { output.WriteRawTag(10); output.WriteMessage(AnyField); @@ -605,7 +608,84 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (anyField_ != null) { + output.WriteRawTag(10); + output.WriteMessage(AnyField); + } + if (apiField_ != null) { + output.WriteRawTag(18); + output.WriteMessage(ApiField); + } + if (durationField_ != null) { + output.WriteRawTag(26); + output.WriteMessage(DurationField); + } + if (emptyField_ != null) { + output.WriteRawTag(34); + output.WriteMessage(EmptyField); + } + if (fieldMaskField_ != null) { + output.WriteRawTag(42); + output.WriteMessage(FieldMaskField); + } + if (sourceContextField_ != null) { + output.WriteRawTag(50); + output.WriteMessage(SourceContextField); + } + if (structField_ != null) { + output.WriteRawTag(58); + output.WriteMessage(StructField); + } + if (timestampField_ != null) { + output.WriteRawTag(66); + output.WriteMessage(TimestampField); + } + if (typeField_ != null) { + output.WriteRawTag(74); + output.WriteMessage(TypeField); + } + if (doubleField_ != null) { + _single_doubleField_codec.WriteTagAndValue(ref output, DoubleField); + } + if (floatField_ != null) { + _single_floatField_codec.WriteTagAndValue(ref output, FloatField); + } + if (int64Field_ != null) { + _single_int64Field_codec.WriteTagAndValue(ref output, Int64Field); + } + if (uint64Field_ != null) { + _single_uint64Field_codec.WriteTagAndValue(ref output, Uint64Field); + } + if (int32Field_ != null) { + _single_int32Field_codec.WriteTagAndValue(ref output, Int32Field); + } + if (uint32Field_ != null) { + _single_uint32Field_codec.WriteTagAndValue(ref output, Uint32Field); + } + if (boolField_ != null) { + _single_boolField_codec.WriteTagAndValue(ref output, BoolField); + } + if (stringField_ != null) { + _single_stringField_codec.WriteTagAndValue(ref output, StringField); + } + if (bytesField_ != null) { + _single_bytesField_codec.WriteTagAndValue(ref output, BytesField); + } + if (valueField_ != null) { + output.WriteRawTag(154, 1); + output.WriteMessage(ValueField); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1393,6 +1473,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else anyField_.WriteTo(output, _repeated_anyField_codec); apiField_.WriteTo(output, _repeated_apiField_codec); durationField_.WriteTo(output, _repeated_durationField_codec); @@ -1414,7 +1497,35 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + anyField_.WriteTo(ref output, _repeated_anyField_codec); + apiField_.WriteTo(ref output, _repeated_apiField_codec); + durationField_.WriteTo(ref output, _repeated_durationField_codec); + emptyField_.WriteTo(ref output, _repeated_emptyField_codec); + fieldMaskField_.WriteTo(ref output, _repeated_fieldMaskField_codec); + sourceContextField_.WriteTo(ref output, _repeated_sourceContextField_codec); + structField_.WriteTo(ref output, _repeated_structField_codec); + timestampField_.WriteTo(ref output, _repeated_timestampField_codec); + typeField_.WriteTo(ref output, _repeated_typeField_codec); + doubleField_.WriteTo(ref output, _repeated_doubleField_codec); + floatField_.WriteTo(ref output, _repeated_floatField_codec); + int64Field_.WriteTo(ref output, _repeated_int64Field_codec); + uint64Field_.WriteTo(ref output, _repeated_uint64Field_codec); + int32Field_.WriteTo(ref output, _repeated_int32Field_codec); + uint32Field_.WriteTo(ref output, _repeated_uint32Field_codec); + boolField_.WriteTo(ref output, _repeated_boolField_codec); + stringField_.WriteTo(ref output, _repeated_stringField_codec); + bytesField_.WriteTo(ref output, _repeated_bytesField_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -2051,6 +2162,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (oneofFieldCase_ == OneofFieldOneofCase.AnyField) { output.WriteRawTag(10); output.WriteMessage(AnyField); @@ -2117,7 +2231,80 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (oneofFieldCase_ == OneofFieldOneofCase.AnyField) { + output.WriteRawTag(10); + output.WriteMessage(AnyField); + } + if (oneofFieldCase_ == OneofFieldOneofCase.ApiField) { + output.WriteRawTag(18); + output.WriteMessage(ApiField); + } + if (oneofFieldCase_ == OneofFieldOneofCase.DurationField) { + output.WriteRawTag(26); + output.WriteMessage(DurationField); + } + if (oneofFieldCase_ == OneofFieldOneofCase.EmptyField) { + output.WriteRawTag(34); + output.WriteMessage(EmptyField); + } + if (oneofFieldCase_ == OneofFieldOneofCase.FieldMaskField) { + output.WriteRawTag(42); + output.WriteMessage(FieldMaskField); + } + if (oneofFieldCase_ == OneofFieldOneofCase.SourceContextField) { + output.WriteRawTag(50); + output.WriteMessage(SourceContextField); + } + if (oneofFieldCase_ == OneofFieldOneofCase.StructField) { + output.WriteRawTag(58); + output.WriteMessage(StructField); + } + if (oneofFieldCase_ == OneofFieldOneofCase.TimestampField) { + output.WriteRawTag(66); + output.WriteMessage(TimestampField); + } + if (oneofFieldCase_ == OneofFieldOneofCase.TypeField) { + output.WriteRawTag(74); + output.WriteMessage(TypeField); + } + if (oneofFieldCase_ == OneofFieldOneofCase.DoubleField) { + _oneof_doubleField_codec.WriteTagAndValue(ref output, (double?) oneofField_); + } + if (oneofFieldCase_ == OneofFieldOneofCase.FloatField) { + _oneof_floatField_codec.WriteTagAndValue(ref output, (float?) oneofField_); + } + if (oneofFieldCase_ == OneofFieldOneofCase.Int64Field) { + _oneof_int64Field_codec.WriteTagAndValue(ref output, (long?) oneofField_); + } + if (oneofFieldCase_ == OneofFieldOneofCase.Uint64Field) { + _oneof_uint64Field_codec.WriteTagAndValue(ref output, (ulong?) oneofField_); + } + if (oneofFieldCase_ == OneofFieldOneofCase.Int32Field) { + _oneof_int32Field_codec.WriteTagAndValue(ref output, (int?) oneofField_); + } + if (oneofFieldCase_ == OneofFieldOneofCase.Uint32Field) { + _oneof_uint32Field_codec.WriteTagAndValue(ref output, (uint?) oneofField_); + } + if (oneofFieldCase_ == OneofFieldOneofCase.BoolField) { + _oneof_boolField_codec.WriteTagAndValue(ref output, (bool?) oneofField_); + } + if (oneofFieldCase_ == OneofFieldOneofCase.StringField) { + _oneof_stringField_codec.WriteTagAndValue(ref output, (string) oneofField_); + } + if (oneofFieldCase_ == OneofFieldOneofCase.BytesField) { + _oneof_bytesField_codec.WriteTagAndValue(ref output, (pb::ByteString) oneofField_); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -2848,6 +3035,9 @@ namespace Google.Protobuf.TestProtos { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else anyField_.WriteTo(output, _map_anyField_codec); apiField_.WriteTo(output, _map_apiField_codec); durationField_.WriteTo(output, _map_durationField_codec); @@ -2869,8 +3059,36 @@ namespace Google.Protobuf.TestProtos { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + anyField_.WriteTo(ref output, _map_anyField_codec); + apiField_.WriteTo(ref output, _map_apiField_codec); + durationField_.WriteTo(ref output, _map_durationField_codec); + emptyField_.WriteTo(ref output, _map_emptyField_codec); + fieldMaskField_.WriteTo(ref output, _map_fieldMaskField_codec); + sourceContextField_.WriteTo(ref output, _map_sourceContextField_codec); + structField_.WriteTo(ref output, _map_structField_codec); + timestampField_.WriteTo(ref output, _map_timestampField_codec); + typeField_.WriteTo(ref output, _map_typeField_codec); + doubleField_.WriteTo(ref output, _map_doubleField_codec); + floatField_.WriteTo(ref output, _map_floatField_codec); + int64Field_.WriteTo(ref output, _map_int64Field_codec); + uint64Field_.WriteTo(ref output, _map_uint64Field_codec); + int32Field_.WriteTo(ref output, _map_int32Field_codec); + uint32Field_.WriteTo(ref output, _map_uint32Field_codec); + boolField_.WriteTo(ref output, _map_boolField_codec); + stringField_.WriteTo(ref output, _map_stringField_codec); + bytesField_.WriteTo(ref output, _map_bytesField_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; diff --git a/csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs b/csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs new file mode 100644 index 0000000000..8e42d13dab --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs @@ -0,0 +1,225 @@ +#region Copyright notice and license +// 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. +#endregion + +using System; +using System.Buffers; +using System.Diagnostics; + +namespace Google.Protobuf.Buffers +{ + /// + /// Represents a heap-based, array-backed output sink into which data can be written. + /// + /// ArrayBufferWriter is originally from corefx, and has been contributed to Protobuf + /// https://github.com/dotnet/runtime/blob/071da4c41aa808c949a773b92dca6f88de9d11f3/src/libraries/Common/src/System/Buffers/ArrayBufferWriter.cs + /// + internal sealed class ArrayBufferWriter : IBufferWriter + { + private T[] _buffer; + private int _index; + + private const int DefaultInitialBufferSize = 256; + + /// + /// Creates an instance of an , in which data can be written to, + /// with the default initial capacity. + /// + public ArrayBufferWriter() + { + _buffer = new T[0]; + _index = 0; + } + + /// + /// Userful for testing writing to buffer writer with a lot of small segments. + /// If set, it limits the max number of bytes by which the buffer grows by at once. + /// + public int? MaxGrowBy { get; set; } + + /// + /// Creates an instance of an , in which data can be written to, + /// with an initial capacity specified. + /// + /// The minimum capacity with which to initialize the underlying buffer. + /// + /// Thrown when is not positive (i.e. less than or equal to 0). + /// + public ArrayBufferWriter(int initialCapacity) + { + if (initialCapacity <= 0) + throw new ArgumentException(nameof(initialCapacity)); + + _buffer = new T[initialCapacity]; + _index = 0; + } + + /// + /// Returns the data written to the underlying buffer so far, as a . + /// + public ReadOnlyMemory WrittenMemory => _buffer.AsMemory(0, _index); + + /// + /// Returns the data written to the underlying buffer so far, as a . + /// + public ReadOnlySpan WrittenSpan => _buffer.AsSpan(0, _index); + + /// + /// Returns the amount of data written to the underlying buffer so far. + /// + public int WrittenCount => _index; + + /// + /// Returns the total amount of space within the underlying buffer. + /// + public int Capacity => _buffer.Length; + + /// + /// Returns the amount of space available that can still be written into without forcing the underlying buffer to grow. + /// + public int FreeCapacity => _buffer.Length - _index; + + /// + /// Clears the data written to the underlying buffer. + /// + /// + /// You must clear the before trying to re-use it. + /// + public void Clear() + { + Debug.Assert(_buffer.Length >= _index); + _buffer.AsSpan(0, _index).Clear(); + _index = 0; + } + + /// + /// Notifies that amount of data was written to the output / + /// + /// + /// Thrown when is negative. + /// + /// + /// Thrown when attempting to advance past the end of the underlying buffer. + /// + /// + /// You must request a new buffer after calling Advance to continue writing more data and cannot write to a previously acquired buffer. + /// + public void Advance(int count) + { + if (count < 0) + throw new ArgumentException(nameof(count)); + + if (_index > _buffer.Length - count) + throw new InvalidOperationException("Advanced past capacity."); + + _index += count; + } + + /// + /// Returns a to write to that is at least the requested length (specified by ). + /// If no is provided (or it's equal to 0), some non-empty buffer is returned. + /// + /// + /// Thrown when is negative. + /// + /// + /// This will never return an empty . + /// + /// + /// There is no guarantee that successive calls will return the same buffer or the same-sized buffer. + /// + /// + /// You must request a new buffer after calling Advance to continue writing more data and cannot write to a previously acquired buffer. + /// + public Memory GetMemory(int sizeHint = 0) + { + CheckAndResizeBuffer(sizeHint); + Debug.Assert(_buffer.Length > _index); + return _buffer.AsMemory(_index); + } + + /// + /// Returns a to write to that is at least the requested length (specified by ). + /// If no is provided (or it's equal to 0), some non-empty buffer is returned. + /// + /// + /// Thrown when is negative. + /// + /// + /// This will never return an empty . + /// + /// + /// There is no guarantee that successive calls will return the same buffer or the same-sized buffer. + /// + /// + /// You must request a new buffer after calling Advance to continue writing more data and cannot write to a previously acquired buffer. + /// + public Span GetSpan(int sizeHint = 0) + { + CheckAndResizeBuffer(sizeHint); + Debug.Assert(_buffer.Length > _index); + return _buffer.AsSpan(_index); + } + + private void CheckAndResizeBuffer(int sizeHint) + { + if (sizeHint < 0) + throw new ArgumentException(nameof(sizeHint)); + + if (sizeHint == 0) + { + sizeHint = 1; + } + + if (sizeHint > FreeCapacity) + { + int growBy = Math.Max(sizeHint, _buffer.Length); + + if (_buffer.Length == 0) + { + growBy = Math.Max(growBy, DefaultInitialBufferSize); + } + + // enable tests that write to small buffer segments + if (MaxGrowBy.HasValue && growBy > MaxGrowBy.Value) + { + growBy = MaxGrowBy.Value; + } + + int newSize = checked(_buffer.Length + growBy); + + Array.Resize(ref _buffer, newSize); + } + + Debug.Assert(FreeCapacity > 0 && FreeCapacity >= sizeHint); + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs index b9ff51521f..1c77e121d3 100644 --- a/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs +++ b/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs @@ -33,6 +33,7 @@ using System; using System.IO; using Google.Protobuf.TestProtos; +using Google.Protobuf.Buffers; using NUnit.Framework; namespace Google.Protobuf @@ -48,22 +49,39 @@ namespace Google.Protobuf // Only do 32-bit write if the value fits in 32 bits. if ((value >> 32) == 0) { + // CodedOutputStream MemoryStream rawOutput = new MemoryStream(); CodedOutputStream output = new CodedOutputStream(rawOutput); output.WriteRawVarint32((uint) value); output.Flush(); Assert.AreEqual(data, rawOutput.ToArray()); + + // IBufferWriter + var bufferWriter = new ArrayBufferWriter(); + WriteContext.Initialize(bufferWriter, out WriteContext ctx); + ctx.WriteUInt32((uint) value); + ctx.Flush(); + Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); + // Also try computing size. Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint32Size((uint) value)); } { + // CodedOutputStream MemoryStream rawOutput = new MemoryStream(); CodedOutputStream output = new CodedOutputStream(rawOutput); output.WriteRawVarint64(value); output.Flush(); Assert.AreEqual(data, rawOutput.ToArray()); + // IBufferWriter + var bufferWriter = new ArrayBufferWriter(); + WriteContext.Initialize(bufferWriter, out WriteContext ctx); + ctx.WriteUInt64(value); + ctx.Flush(); + Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); + // Also try computing size. Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint64Size(value)); } @@ -80,6 +98,13 @@ namespace Google.Protobuf output.WriteRawVarint32((uint) value); output.Flush(); Assert.AreEqual(data, rawOutput.ToArray()); + + var bufferWriter = new ArrayBufferWriter(); + bufferWriter.MaxGrowBy = bufferSize; + WriteContext.Initialize(bufferWriter, out WriteContext ctx); + ctx.WriteUInt32((uint) value); + ctx.Flush(); + Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); } { @@ -88,7 +113,15 @@ namespace Google.Protobuf output.WriteRawVarint64(value); output.Flush(); Assert.AreEqual(data, rawOutput.ToArray()); + + var bufferWriter = new ArrayBufferWriter(); + bufferWriter.MaxGrowBy = bufferSize; + WriteContext.Initialize(bufferWriter, out WriteContext ctx); + ctx.WriteUInt64(value); + ctx.Flush(); + Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); } + } } @@ -133,20 +166,35 @@ namespace Google.Protobuf /// private static void AssertWriteLittleEndian32(byte[] data, uint value) { - MemoryStream rawOutput = new MemoryStream(); - CodedOutputStream output = new CodedOutputStream(rawOutput); - output.WriteRawLittleEndian32(value); - output.Flush(); - Assert.AreEqual(data, rawOutput.ToArray()); + { + var rawOutput = new MemoryStream(); + var output = new CodedOutputStream(rawOutput); + output.WriteRawLittleEndian32(value); + output.Flush(); + Assert.AreEqual(data, rawOutput.ToArray()); + + var bufferWriter = new ArrayBufferWriter(); + WriteContext.Initialize(bufferWriter, out WriteContext ctx); + ctx.WriteFixed32(value); + ctx.Flush(); + Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); + } // Try different buffer sizes. for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2) { - rawOutput = new MemoryStream(); - output = new CodedOutputStream(rawOutput, bufferSize); + var rawOutput = new MemoryStream(); + var output = new CodedOutputStream(rawOutput, bufferSize); output.WriteRawLittleEndian32(value); output.Flush(); Assert.AreEqual(data, rawOutput.ToArray()); + + var bufferWriter = new ArrayBufferWriter(); + bufferWriter.MaxGrowBy = bufferSize; + WriteContext.Initialize(bufferWriter, out WriteContext ctx); + ctx.WriteFixed32(value); + ctx.Flush(); + Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); } } @@ -156,20 +204,35 @@ namespace Google.Protobuf /// private static void AssertWriteLittleEndian64(byte[] data, ulong value) { - MemoryStream rawOutput = new MemoryStream(); - CodedOutputStream output = new CodedOutputStream(rawOutput); - output.WriteRawLittleEndian64(value); - output.Flush(); - Assert.AreEqual(data, rawOutput.ToArray()); + { + var rawOutput = new MemoryStream(); + var output = new CodedOutputStream(rawOutput); + output.WriteRawLittleEndian64(value); + output.Flush(); + Assert.AreEqual(data, rawOutput.ToArray()); + + var bufferWriter = new ArrayBufferWriter(); + WriteContext.Initialize(bufferWriter, out WriteContext ctx); + ctx.WriteFixed64(value); + ctx.Flush(); + Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); + } // Try different block sizes. for (int blockSize = 1; blockSize <= 16; blockSize *= 2) { - rawOutput = new MemoryStream(); - output = new CodedOutputStream(rawOutput, blockSize); + var rawOutput = new MemoryStream(); + var output = new CodedOutputStream(rawOutput, blockSize); output.WriteRawLittleEndian64(value); output.Flush(); Assert.AreEqual(data, rawOutput.ToArray()); + + var bufferWriter = new ArrayBufferWriter(); + bufferWriter.MaxGrowBy = blockSize; + WriteContext.Initialize(bufferWriter, out WriteContext ctx); + ctx.WriteFixed64(value); + ctx.Flush(); + Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); } } @@ -205,41 +268,72 @@ namespace Google.Protobuf message.WriteTo(output); output.Flush(); Assert.AreEqual(rawBytes, rawOutput.ToArray()); + + var bufferWriter = new ArrayBufferWriter(); + bufferWriter.MaxGrowBy = blockSize; + message.WriteTo(bufferWriter); + Assert.AreEqual(rawBytes, bufferWriter.WrittenSpan.ToArray()); } } + + [Test] + public void WriteContext_WritesWithFlushes() + { + TestAllTypes message = SampleMessages.CreateFullTestAllTypes(); + + MemoryStream expectedOutput = new MemoryStream(); + CodedOutputStream output = new CodedOutputStream(expectedOutput); + output.WriteMessage(message); + output.Flush(); + byte[] expectedBytes1 = expectedOutput.ToArray(); + + output.WriteMessage(message); + output.Flush(); + byte[] expectedBytes2 = expectedOutput.ToArray(); + + var bufferWriter = new ArrayBufferWriter(); + WriteContext.Initialize(bufferWriter, out WriteContext ctx); + ctx.WriteMessage(message); + ctx.Flush(); + Assert.AreEqual(expectedBytes1, bufferWriter.WrittenSpan.ToArray()); + + ctx.WriteMessage(message); + ctx.Flush(); + Assert.AreEqual(expectedBytes2, bufferWriter.WrittenSpan.ToArray()); + } [Test] public void EncodeZigZag32() { - Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag32(0)); - Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag32(-1)); - Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag32(1)); - Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag32(-2)); - Assert.AreEqual(0x7FFFFFFEu, CodedOutputStream.EncodeZigZag32(0x3FFFFFFF)); - Assert.AreEqual(0x7FFFFFFFu, CodedOutputStream.EncodeZigZag32(unchecked((int) 0xC0000000))); - Assert.AreEqual(0xFFFFFFFEu, CodedOutputStream.EncodeZigZag32(0x7FFFFFFF)); - Assert.AreEqual(0xFFFFFFFFu, CodedOutputStream.EncodeZigZag32(unchecked((int) 0x80000000))); + Assert.AreEqual(0u, WritingPrimitives.EncodeZigZag32(0)); + Assert.AreEqual(1u, WritingPrimitives.EncodeZigZag32(-1)); + Assert.AreEqual(2u, WritingPrimitives.EncodeZigZag32(1)); + Assert.AreEqual(3u, WritingPrimitives.EncodeZigZag32(-2)); + Assert.AreEqual(0x7FFFFFFEu, WritingPrimitives.EncodeZigZag32(0x3FFFFFFF)); + Assert.AreEqual(0x7FFFFFFFu, WritingPrimitives.EncodeZigZag32(unchecked((int) 0xC0000000))); + Assert.AreEqual(0xFFFFFFFEu, WritingPrimitives.EncodeZigZag32(0x7FFFFFFF)); + Assert.AreEqual(0xFFFFFFFFu, WritingPrimitives.EncodeZigZag32(unchecked((int) 0x80000000))); } [Test] public void EncodeZigZag64() { - Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag64(0)); - Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag64(-1)); - Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag64(1)); - Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag64(-2)); + Assert.AreEqual(0u, WritingPrimitives.EncodeZigZag64(0)); + Assert.AreEqual(1u, WritingPrimitives.EncodeZigZag64(-1)); + Assert.AreEqual(2u, WritingPrimitives.EncodeZigZag64(1)); + Assert.AreEqual(3u, WritingPrimitives.EncodeZigZag64(-2)); Assert.AreEqual(0x000000007FFFFFFEuL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000003FFFFFFFUL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0x000000003FFFFFFFUL))); Assert.AreEqual(0x000000007FFFFFFFuL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFFC0000000UL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0xFFFFFFFFC0000000UL))); Assert.AreEqual(0x00000000FFFFFFFEuL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000007FFFFFFFUL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0x000000007FFFFFFFUL))); Assert.AreEqual(0x00000000FFFFFFFFuL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFF80000000UL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0xFFFFFFFF80000000UL))); Assert.AreEqual(0xFFFFFFFFFFFFFFFEL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0x7FFFFFFFFFFFFFFFUL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0x7FFFFFFFFFFFFFFFUL))); Assert.AreEqual(0xFFFFFFFFFFFFFFFFL, - CodedOutputStream.EncodeZigZag64(unchecked((long) 0x8000000000000000UL))); + WritingPrimitives.EncodeZigZag64(unchecked((long) 0x8000000000000000UL))); } [Test] @@ -247,26 +341,26 @@ namespace Google.Protobuf { // Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1) // were chosen semi-randomly via keyboard bashing. - Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(0))); - Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(1))); - Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-1))); - Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(14927))); - Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-3612))); + Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(0))); + Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(1))); + Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(-1))); + Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(14927))); + Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(-3612))); } [Test] public void RoundTripZigZag64() { - Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(0))); - Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(1))); - Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-1))); - Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(14927))); - Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-3612))); + Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(0))); + Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(1))); + Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-1))); + Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(14927))); + Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-3612))); Assert.AreEqual(856912304801416L, - ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(856912304801416L))); + ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(856912304801416L))); Assert.AreEqual(-75123905439571256L, - ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-75123905439571256L))); + ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-75123905439571256L))); } [Test] @@ -395,7 +489,7 @@ namespace Google.Protobuf Assert.IsTrue(memoryStream.CanWrite); using (var cos = new CodedOutputStream(memoryStream)) { - cos.WriteRawByte(0); + cos.WriteRawBytes(new byte[] {0}); Assert.AreEqual(0, memoryStream.Position); // Not flushed yet } Assert.AreEqual(1, memoryStream.ToArray().Length); // Flushed data from CodedOutputStream to MemoryStream @@ -409,7 +503,7 @@ namespace Google.Protobuf Assert.IsTrue(memoryStream.CanWrite); using (var cos = new CodedOutputStream(memoryStream, true)) { - cos.WriteRawByte(0); + cos.WriteRawBytes(new byte[] {0}); Assert.AreEqual(0, memoryStream.Position); // Not flushed yet } Assert.AreEqual(1, memoryStream.Position); // Flushed data from CodedOutputStream to MemoryStream diff --git a/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs b/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs index 934b780ccc..aceb4a68f7 100644 --- a/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs +++ b/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs @@ -34,6 +34,8 @@ namespace Google.Protobuf message.SetExtension(OptionalBoolExtension, true); var serialized = message.ToByteArray(); + MessageParsingHelpers.AssertWritingMessage(message); + MessageParsingHelpers.AssertReadingMessage( TestAllExtensions.Parser.WithExtensionRegistry(new ExtensionRegistry() { OptionalBoolExtension }), serialized, diff --git a/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs b/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs index 5be0cecd99..7f366926fa 100644 --- a/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs +++ b/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs @@ -124,7 +124,17 @@ namespace Google.Protobuf { var stream = new MemoryStream(); var codedOutput = new CodedOutputStream(stream); - codec.ValueWriter(codedOutput, sampleValue); + WriteContext.Initialize(codedOutput, out WriteContext ctx); + try + { + // only write the value using the codec + codec.ValueWriter(ref ctx, sampleValue); + } + finally + { + ctx.CopyStateTo(codedOutput); + } + codedOutput.Flush(); stream.Position = 0; var codedInput = new CodedInputStream(stream); @@ -175,7 +185,17 @@ namespace Google.Protobuf if (codec.DefaultValue != null) // This part isn't appropriate for message types. { codedOutput = new CodedOutputStream(stream); - codec.ValueWriter(codedOutput, codec.DefaultValue); + WriteContext.Initialize(codedOutput, out WriteContext ctx); + try + { + // only write the value using the codec + codec.ValueWriter(ref ctx, codec.DefaultValue); + } + finally + { + ctx.CopyStateTo(codedOutput); + } + codedOutput.Flush(); Assert.AreNotEqual(0, stream.Position); Assert.AreEqual(stream.Position, codec.ValueSizeCalculator(codec.DefaultValue)); diff --git a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs index 5f90c94cce..1abed60563 100644 --- a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs +++ b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs @@ -344,6 +344,8 @@ namespace Google.Protobuf } }; + MessageParsingHelpers.AssertWritingMessage(message); + MessageParsingHelpers.AssertRoundtrip(Proto2.TestAllTypes.Parser, message); } @@ -359,6 +361,8 @@ namespace Google.Protobuf new RepeatedGroup_extension { A = 30 } }); + MessageParsingHelpers.AssertWritingMessage(message); + MessageParsingHelpers.AssertRoundtrip( TestAllExtensions.Parser.WithExtensionRegistry(new ExtensionRegistry() { UnittestExtensions.OptionalGroupExtension, UnittestExtensions.RepeatedGroupExtension }), message); @@ -370,6 +374,8 @@ namespace Google.Protobuf var message = new TestGroupExtension(); message.SetExtension(TestNestedExtension.Extensions.OptionalGroupExtension, new TestNestedExtension.Types.OptionalGroup_extension { A = 10 }); + MessageParsingHelpers.AssertWritingMessage(message); + MessageParsingHelpers.AssertRoundtrip( TestGroupExtension.Parser.WithExtensionRegistry(new ExtensionRegistry() { TestNestedExtension.Extensions.OptionalGroupExtension }), message); diff --git a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs index 3499e6617d..06af5e9e9a 100644 --- a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs +++ b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs @@ -132,6 +132,8 @@ namespace Google.Protobuf byte[] bytes = message.ToByteArray(); Assert.AreEqual(0, bytes.Length); + MessageParsingHelpers.AssertWritingMessage(message); + MessageParsingHelpers.AssertRoundtrip(TestAllTypes.Parser, message); } @@ -164,7 +166,7 @@ namespace Google.Protobuf SingleUint64 = ulong.MaxValue }; - byte[] bytes = message.ToByteArray(); + MessageParsingHelpers.AssertWritingMessage(message); MessageParsingHelpers.AssertRoundtrip(TestAllTypes.Parser, message); } @@ -198,7 +200,7 @@ namespace Google.Protobuf RepeatedUint64 = { ulong.MaxValue, uint.MinValue } }; - byte[] bytes = message.ToByteArray(); + MessageParsingHelpers.AssertWritingMessage(message); MessageParsingHelpers.AssertRoundtrip(TestAllTypes.Parser, message); } @@ -230,7 +232,7 @@ namespace Google.Protobuf } }; - byte[] bytes = message.ToByteArray(); + MessageParsingHelpers.AssertWritingMessage(message); MessageParsingHelpers.AssertRoundtrip(TestMap.Parser, message); } @@ -246,6 +248,8 @@ namespace Google.Protobuf byte[] bytes = message.ToByteArray(); Assert.AreEqual(2, bytes.Length); // Tag for field entry (1 byte), length of entry (0; 1 byte) + MessageParsingHelpers.AssertWritingMessage(message); + MessageParsingHelpers.AssertReadingMessage( TestMap.Parser, bytes, @@ -660,6 +664,8 @@ namespace Google.Protobuf var bytes = message.ToByteArray(); Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - no string! + MessageParsingHelpers.AssertWritingMessage(message); + MessageParsingHelpers.AssertRoundtrip(TestAllTypes.Parser, message, parsedMessage => { Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, parsedMessage.OneofFieldCase); @@ -675,6 +681,8 @@ namespace Google.Protobuf var bytes = message.ToByteArray(); Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - it's still serialized + MessageParsingHelpers.AssertWritingMessage(message); + MessageParsingHelpers.AssertRoundtrip(TestAllTypes.Parser, message, parsedMessage => { Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, parsedMessage.OneofFieldCase); diff --git a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs index 5e9730b2af..1a650933ef 100644 --- a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs +++ b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs @@ -226,6 +226,28 @@ namespace Google.Protobuf JsonFormatter.Default.Format(new TestMap { MapBoolBool = { { false, true }, { true, false } } })); } + [Test] + public void NullValueOutsideStruct() + { + var message = new NullValueOutsideStruct { NullValue = NullValue.NullValue }; + AssertJson("{ 'nullValue': null }", JsonFormatter.Default.Format(message)); + } + + [Test] + public void NullValueNotInOneof() + { + var message = new NullValueNotInOneof(); + AssertJson("{ }", JsonFormatter.Default.Format(message)); + } + + [Test] + public void NullValueNotInOneof_FormatDefaults() + { + var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithFormatDefaultValues(true)); + var message = new NullValueNotInOneof(); + AssertJson("{ 'nullValue': null }", formatter.Format(message)); + } + [TestCase(1.0, "1")] [TestCase(double.NaN, "'NaN'")] [TestCase(double.PositiveInfinity, "'Infinity'")] diff --git a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs index f9f8cde050..e170fcc5a0 100644 --- a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs +++ b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs @@ -36,6 +36,7 @@ using Google.Protobuf.WellKnownTypes; using NUnit.Framework; using ProtobufTestMessages.Proto2; using System; +using UnitTest.Issues.TestProtos; namespace Google.Protobuf { @@ -974,6 +975,43 @@ namespace Google.Protobuf Assert.AreEqual(expected, actual); } + [Test] + public void NullValueOutsideStruct_NullLiteral() + { + string json = "{ \"nullValue\": null }"; + var message = NullValueOutsideStruct.Parser.ParseJson(json); + Assert.AreEqual(NullValueOutsideStruct.ValueOneofCase.NullValue, message.ValueCase); + } + + [Test] + public void NullValueNotInOneof_NullLiteral() + { + // We'd only normally see this with FormatDefaultValues set to true. + string json = "{ \"nullValue\": null }"; + var message = NullValueNotInOneof.Parser.ParseJson(json); + Assert.AreEqual(NullValue.NullValue, message.NullValue); + } + + // NullValue used to only be converted to the null literal when part of a struct. + // Otherwise, it would end up as a string "NULL_VALUE" (the name of the enum value). + // We still parse that form, for compatibility. + [Test] + public void NullValueOutsideStruct_Compatibility() + { + string json = "{ \"nullValue\": \"NULL_VALUE\" }"; + var message = NullValueOutsideStruct.Parser.ParseJson(json); + Assert.AreEqual(NullValueOutsideStruct.ValueOneofCase.NullValue, message.ValueCase); + } + + [Test] + public void NullValueNotInOneof_Compatibility() + { + // We'd only normally see this with FormatDefaultValues set to true. + string json = "{ \"nullValue\": \"NULL_VALUE\" }"; + var message = NullValueNotInOneof.Parser.ParseJson(json); + Assert.AreEqual(NullValue.NullValue, message.NullValue); + } + /// /// Various tests use strings which have quotes round them for parsing or as the result /// of formatting, but without those quotes being specified in the tests (for the sake of readability). diff --git a/csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs b/csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs index 9c9846c8f5..da7b4a8c07 100644 --- a/csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs +++ b/csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs @@ -35,7 +35,9 @@ using System.Buffers; using pb = global::Google.Protobuf; using pbr = global::Google.Protobuf.Reflection; using NUnit.Framework; - +using System.IO; +using System; +using Google.Protobuf.Buffers; namespace Google.Protobuf { @@ -46,14 +48,14 @@ namespace Google.Protobuf { var message = new ParseContextEnabledMessageB { - A = new LegacyGeneratedCodeMessageA - { - Bb = new ParseContextEnabledMessageB { OptionalInt32 = 12345 } - }, - OptionalInt32 = 6789 + A = new LegacyGeneratedCodeMessageA + { + Bb = new ParseContextEnabledMessageB { OptionalInt32 = 12345 } + }, + OptionalInt32 = 6789 }; var data = message.ToByteArray(); - + // when parsing started using CodedInputStream and a message with legacy generated code // is encountered somewhere in the parse tree, we still need to be able to use its // MergeFrom(CodedInputStream) method to parse correctly. @@ -71,11 +73,11 @@ namespace Google.Protobuf { var message = new ParseContextEnabledMessageB { - A = new LegacyGeneratedCodeMessageA - { - Bb = new ParseContextEnabledMessageB { OptionalInt32 = 12345 } - }, - OptionalInt32 = 6789 + A = new LegacyGeneratedCodeMessageA + { + Bb = new ParseContextEnabledMessageB { OptionalInt32 = 12345 } + }, + OptionalInt32 = 6789 }; var data = message.ToByteArray(); @@ -86,13 +88,65 @@ namespace Google.Protobuf // code up to date. var exception = Assert.Throws(() => { - ParseContext.Initialize(new ReadOnlySequence(data), out ParseContext parseCtx); - var parsed = new ParseContextEnabledMessageB(); - ParsingPrimitivesMessages.ReadRawMessage(ref parseCtx, parsed); + ParseContext.Initialize(new ReadOnlySequence(data), out ParseContext parseCtx); + var parsed = new ParseContextEnabledMessageB(); + ParsingPrimitivesMessages.ReadRawMessage(ref parseCtx, parsed); }); Assert.AreEqual($"Message {typeof(LegacyGeneratedCodeMessageA).Name} doesn't provide the generated method that enables ParseContext-based parsing. You might need to regenerate the generated protobuf code.", exception.Message); } + [Test] + public void IntermixingOfNewAndLegacyGeneratedCodeWorksWithCodedOutputStream() + { + // when serialization started using CodedOutputStream and a message with legacy generated code + // is encountered somewhere in the parse tree, we still need to be able to use its + // WriteTo(CodedOutputStream) method to serialize correctly. + var ms = new MemoryStream(); + var codedOutput = new CodedOutputStream(ms); + var message = new ParseContextEnabledMessageB + { + A = new LegacyGeneratedCodeMessageA + { + Bb = new ParseContextEnabledMessageB { OptionalInt32 = 12345 } + }, + OptionalInt32 = 6789 + }; + message.WriteTo(codedOutput); + codedOutput.Flush(); + + var codedInput = new CodedInputStream(ms.ToArray()); + var parsed = new ParseContextEnabledMessageB(); + codedInput.ReadRawMessage(parsed); + Assert.IsTrue(codedInput.IsAtEnd); + + Assert.AreEqual(12345, parsed.A.Bb.OptionalInt32); + Assert.AreEqual(6789, parsed.OptionalInt32); + } + + [Test] + public void LegacyGeneratedCodeThrowsWithIBufferWriter() + { + // if serialization started using IBufferWriter and we don't have a CodedOutputStream + // instance at hand, we cannot fall back to the legacy WriteTo(CodedOutputStream) + // method and serializatin will fail. As a consequence, one can only use serialization + // to IBufferWriter if all the messages in the parsing tree have their generated + // code up to date. + var message = new ParseContextEnabledMessageB + { + A = new LegacyGeneratedCodeMessageA + { + Bb = new ParseContextEnabledMessageB { OptionalInt32 = 12345 } + }, + OptionalInt32 = 6789 + }; + var exception = Assert.Throws(() => + { + WriteContext.Initialize(new ArrayBufferWriter(), out WriteContext writeCtx); + ((IBufferMessage)message).InternalWriteTo(ref writeCtx); + }); + Assert.AreEqual($"Message {typeof(LegacyGeneratedCodeMessageA).Name} doesn't provide the generated method that enables WriteContext-based serialization. You might need to regenerate the generated protobuf code.", exception.Message); + } + // hand-modified version of a generated message that only provides the legacy // MergeFrom(CodedInputStream) method and doesn't implement IBufferMessage. private sealed partial class LegacyGeneratedCodeMessageA : pb::IMessage { @@ -178,18 +232,27 @@ namespace Google.Protobuf } public void WriteTo(pb::CodedOutputStream output) { - if (a_ != null) { + output.WriteRawMessage(this); + } + + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) + { + if (a_ != null) + { output.WriteRawTag(10); output.WriteMessage(A); } - if (OptionalInt32 != 0) { + if (OptionalInt32 != 0) + { output.WriteRawTag(16); output.WriteInt32(OptionalInt32); } - if (_unknownFields != null) { - _unknownFields.WriteTo(output); + if (_unknownFields != null) + { + _unknownFields.WriteTo(ref output); } } + public int CalculateSize() { int size = 0; if (a_ != null) { diff --git a/csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs b/csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs index ec5f13abc3..36a2f02229 100644 --- a/csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs +++ b/csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs @@ -33,6 +33,7 @@ using NUnit.Framework; using System; using System.Buffers; +using Google.Protobuf.Buffers; namespace Google.Protobuf { @@ -81,6 +82,11 @@ namespace Google.Protobuf { var bytes = message.ToByteArray(); + // also serialize using IBufferWriter and check it leads to the same data + var bufferWriter = new ArrayBufferWriter(); + message.WriteTo(bufferWriter); + Assert.AreEqual(bytes, bufferWriter.WrittenSpan.ToArray(), "Both serialization approaches need to result in the same data."); + // Load content as single segment var parsedBuffer = parser.ParseFrom(new ReadOnlySequence(bytes)); Assert.AreEqual(message, parsedBuffer); @@ -96,5 +102,41 @@ namespace Google.Protobuf Assert.AreEqual(message, parsedStream); additionalAssert?.Invoke(parsedStream); } + + public static void AssertWritingMessage(IMessage message) + { + // serialize using CodedOutputStream + var bytes = message.ToByteArray(); + + int messageSize = message.CalculateSize(); + Assert.AreEqual(message.CalculateSize(), bytes.Length); + + // serialize using IBufferWriter and check it leads to the same output + var bufferWriter = new ArrayBufferWriter(); + message.WriteTo(bufferWriter); + Assert.AreEqual(bytes, bufferWriter.WrittenSpan.ToArray()); + + // serialize into a single span and check it leads to the same output + var singleSpan = new Span(new byte[messageSize]); + message.WriteTo(singleSpan); + Assert.AreEqual(bytes, singleSpan.ToArray()); + + // test for different IBufferWriter.GetSpan() segment sizes + for (int blockSize = 1; blockSize < 256; blockSize *= 2) + { + var segmentedBufferWriter = new ArrayBufferWriter(); + segmentedBufferWriter.MaxGrowBy = blockSize; + message.WriteTo(segmentedBufferWriter); + Assert.AreEqual(bytes, segmentedBufferWriter.WrittenSpan.ToArray()); + } + + // if the full message is small enough, try serializing directly into stack-allocated buffer + if (bytes.Length <= 256) + { + Span stackAllocBuffer = stackalloc byte[bytes.Length]; + message.WriteTo(stackAllocBuffer); + Assert.AreEqual(bytes, stackAllocBuffer.ToArray()); + } + } } } \ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs index 47ff2a18ed..94c4746a80 100644 --- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs +++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs @@ -71,6 +71,8 @@ namespace Google.Protobuf.WellKnownTypes Uint64Field = 4 }; + MessageParsingHelpers.AssertWritingMessage(message); + MessageParsingHelpers.AssertRoundtrip(TestWellKnownTypes.Parser, message, parsed => { Assert.AreEqual("x", parsed.StringField); @@ -101,6 +103,8 @@ namespace Google.Protobuf.WellKnownTypes Uint64Field = 0 }; + MessageParsingHelpers.AssertWritingMessage(message); + MessageParsingHelpers.AssertRoundtrip(TestWellKnownTypes.Parser, message, parsed => { Assert.AreEqual("", parsed.StringField); @@ -144,6 +148,8 @@ namespace Google.Protobuf.WellKnownTypes // Just to test a single value for sanity... Assert.AreEqual("Second", message.StringField[1]); + MessageParsingHelpers.AssertWritingMessage(message); + MessageParsingHelpers.AssertRoundtrip(RepeatedWellKnownTypes.Parser, message); } @@ -169,6 +175,8 @@ namespace Google.Protobuf.WellKnownTypes var message = new RepeatedWellKnownTypes { Int32Field = { 5, 0 } }; var actualBytes = message.ToByteArray(); Assert.AreEqual(expectedBytes, actualBytes); + + MessageParsingHelpers.AssertWritingMessage(message); } [Test] @@ -196,6 +204,8 @@ namespace Google.Protobuf.WellKnownTypes // Just to test a single value for sanity... Assert.AreEqual("Second", message.StringField[12]); + MessageParsingHelpers.AssertWritingMessage(message); + MessageParsingHelpers.AssertRoundtrip(MapWellKnownTypes.Parser, message); } diff --git a/csharp/src/Google.Protobuf.Test/testprotos.pb b/csharp/src/Google.Protobuf.Test/testprotos.pb index 089ef7512a4cce971aeda0027deff69036c06c1a..f7313edc83f9a2337141478398ab6c93f70f827a 100644 GIT binary patch delta 3215 zcmZWrTW?fV6h8ZMX3p$hW_o65VG5-dsD-ve5n4bI3raJ!BNoJ(VvMQUYC~`7v}i-? zQ4taFhGQHWFfl%8q9zhZtcm^yUrc;cV|?++OJag1CVp#Qjwbf)J8P})`_|fP@6N5S zb638}T|aPj?bi3=#RmSZE@>i2TE?JQG`M;E82M#iQV#~)l=C{I2$ z{?Nkw;*$&E7FAnbn4g?^`tj2gT+dorN2=%@uQ6YBMR=D|Gbpzyyn1;;Zn-l>pLG0i zQu(^NZCGVvouji0gEJ4#jL%Ml`~P3xnmld@Du>?xB=z}Ll?;8)yK?i7_wQiqQi=;N z6v}H?rxll8DC@m!W!DF%hw6ijs#Q{Yh|4rbPOb6@u~4K{PSvXfA&O>XgAbfE81YPP zlloLD?jzXk?YjB<2VFes_8U}`=k^v6QE+uO^OQbH2n?x2|%BqL9Ij3)vKLe#%c2#I?d zv_nDy$T$Q-s8{ycL?#JoVG4nyw{C-rMUOk2neM8jZHQYRfp^;peK!zwu~Y1 z5Yp&KL@4j`9xz8DXh`=3n|0@c&g6*Pr8@xd38frD;t{27NW{?Vk>-sqhG`zz)T3KP zETCY^PRoh90Xt2>>A(i;G=cmu5(9O5jX+A42eP+WQU;cRt=k-e#6Y{5CNfE4;P!o1 z0?ifWew#^0R5TL;Cmm5SXO;j6WktILK;Vpu+xA)CoJfo9do3xzpge3z1$+<2z6B%( z>sUIbcgM~v@L6E}W&VH)^&Y?*5+EfYBA#|00nHEC~e&92JC~S)Zx1DAyL|K zx0UcoqSSdnjbeRdD2Kh{75VY#}=M))I@uRiXHMzC}AVECjl%FV6-Kx5Qu0HJy`&@UAw zLSr;ztogJ6CwY^$27t1YaTzV#$-q(4!kt{#sD2mdG7-whyk}Y4%~PNJ%A&`DP1;0) zOiXff3jn}2Y1x3lHW}#0Qv!i)5?7O6^hAJ$PVpJ@q5~oGRG=&+z?3wvRze$`l1keJ zqF7BXauA$TO=cbmj;)`TrZE6mnYNb|2zArSGzNsSX*5P-Oc0pkdCMqJHpc^pP&SuZ z=MZJCCu0${fCp-xFS-`U*?imr)~p;`k>D)HR%nsSu@ze6a%=^O3vuVZMy_+(hlQG) zvC_$DI~UM7ytE_u(JwMimvDafh&(OQxY=S)R>R*KHpmhcG)XHsS}fIxG`Zbp)Z zw9E@y0s!*MaT&F@oHFu=p==rI^xp{xcVl^jx#2(xDBtB`gxaGnJ?kVL(F!;J9{`}R z5-X7UN^FcyWd+8J0zFJCVY@@%T*;by3Kl|}x2aY7KN5tAv&?&)vHV5WI#@0*j<@c< zqo=3x!1Y(7vkY^o$6Nwjr^L&QpJxL1*(Z#%e3_|?{z(Cd!O3$B|9;c>Nue>WCO)M8 z{eX&d3|++;_%Cvf)u&?$B)sxpiUVl7;uw=I@;3VAWGk6owR~nsxa{`^R6&f)Q%NW-(~pC zMYM_>RT=Npg+QPMY<3X2RkpF+LC{v&_8n)lH_m5ou(j+B{?Qxahb~o}YnJ(H@e2`F zf9@C8)t@`)2X2e^9$WkFNAX;u+FTT4>Ay2@- delta 2759 zcmYjTTTE0}6uswhXD$bZfy)3oil7yIFd)MCtRM=3Ft*Yd4G^1Hl3FTQ+V;-%fh2??w5VJL&bg9aqg{OUhib;y5iFDWrb5+SpW9= zsS2-3RVXPPfsYAZC4gK)%ohojQk5!3h@zD;=>o??jCf^5y?P)OcM)uL_N`z2F2jRX zw_24e={nr;MMiERJ_5+k$U2KS(B`yBM5s;Hm=Mz_VG$DBs(h0O&@O!w;z(?l6&6t} zS*-$v{+KWKI|rCjN=V|{?`XHXdB9nx) zFoi(UmDp@!0i~v!ECfr}D?2UnfSM1e1ZIjt50<-Hvc?%eRvtB(91__`f5Hwqs= z8oO}X(+`Z4v^c}OTB`!U!!XyYMAQDzxU(0*vx{Z4Cfrqfr?x z+^A(svjUB-NQ-nqthtpD}+9~PYV8nlTRnV8_=EdT)9gkb{$+k~edPYDFJ z30zHj(PJJOy2LMsFFFu1FL}yP0!+&A)rx6@lTvBBKol!a1r~yHvOb(gjAQGkWY`!0 ztW2593WT~T6*dNhvMDr1V~i1)=4rzyP&Umyi%>RQR%;PuZX#m=wSWg|hR@p;$k|NP z0@iFcvLeAb8(E=6o{g-~BF{!vkT@50?rLN^r+t_!PlZ-mIc?`0I;Zz5?#mm_2jSYp zk#@sNsT^91)8XU`w|{so$eWh%2?_bKa5I2FlQ)|Yry(uyb}az_`Gu&A+FK|KK z0@Uf(2?%#%VRLxHffP_WV`GF`f{dPZoQ`ObhrbU1P*{ugw$1C_H;|C%DNlmrBgV!*zNF3kI<2y_LvQhJ%GIw5E$Aa! z-B^2DjJa*A3|mC4=>KwZm6e6w0pWcW-qnb%L1U%j_DM0;SYmjl!V+q?L}N7&C8hhN WNwKniZ0% public static int ComputeStringSize(String value) { - int byteArraySize = Utf8Encoding.GetByteCount(value); + int byteArraySize = WritingPrimitives.Utf8Encoding.GetByteCount(value); return ComputeLengthSize(byteArraySize) + byteArraySize; } @@ -208,7 +208,7 @@ namespace Google.Protobuf /// public static int ComputeSInt32Size(int value) { - return ComputeRawVarint32Size(EncodeZigZag32(value)); + return ComputeRawVarint32Size(WritingPrimitives.EncodeZigZag32(value)); } /// @@ -217,7 +217,7 @@ namespace Google.Protobuf /// public static int ComputeSInt64Size(long value) { - return ComputeRawVarint64Size(EncodeZigZag64(value)); + return ComputeRawVarint64Size(WritingPrimitives.EncodeZigZag64(value)); } /// diff --git a/csharp/src/Google.Protobuf/CodedOutputStream.cs b/csharp/src/Google.Protobuf/CodedOutputStream.cs index 1d76d27602..20d88ea7dc 100644 --- a/csharp/src/Google.Protobuf/CodedOutputStream.cs +++ b/csharp/src/Google.Protobuf/CodedOutputStream.cs @@ -33,6 +33,7 @@ using Google.Protobuf.Collections; using System; using System.IO; +using System.Security; using System.Text; namespace Google.Protobuf @@ -55,11 +56,9 @@ namespace Google.Protobuf /// and MapField<TKey, TValue> to serialize such fields. /// /// + [SecuritySafeCritical] public sealed partial class CodedOutputStream : IDisposable { - // "Local" copy of Encoding.UTF8, for efficiency. (Yes, it makes a difference.) - internal static readonly Encoding Utf8Encoding = Encoding.UTF8; - /// /// The buffer size used by CreateInstance(Stream). /// @@ -67,8 +66,8 @@ namespace Google.Protobuf private readonly bool leaveOpen; private readonly byte[] buffer; - private readonly int limit; - private int position; + private WriterInternalState state; + private readonly Stream output; #region Construction @@ -90,8 +89,9 @@ namespace Google.Protobuf { this.output = null; this.buffer = ProtoPreconditions.CheckNotNull(buffer, nameof(buffer)); - this.position = offset; - this.limit = offset + length; + this.state.position = offset; + this.state.limit = offset + length; + WriteBufferHelper.Initialize(this, out this.state.writeBufferHelper); leaveOpen = true; // Simple way of avoiding trying to dispose of a null reference } @@ -99,8 +99,9 @@ namespace Google.Protobuf { this.output = ProtoPreconditions.CheckNotNull(output, nameof(output)); this.buffer = buffer; - this.position = 0; - this.limit = buffer.Length; + this.state.position = 0; + this.state.limit = buffer.Length; + WriteBufferHelper.Initialize(this, out this.state.writeBufferHelper); this.leaveOpen = leaveOpen; } @@ -155,9 +156,9 @@ namespace Google.Protobuf { if (output != null) { - return output.Position + position; + return output.Position + state.position; } - return position; + return state.position; } } @@ -169,7 +170,8 @@ namespace Google.Protobuf /// The value to write public void WriteDouble(double value) { - WriteRawLittleEndian64((ulong)BitConverter.DoubleToInt64Bits(value)); + var span = new Span(buffer); + WritingPrimitives.WriteDouble(ref span, ref state, value); } /// @@ -178,23 +180,8 @@ namespace Google.Protobuf /// The value to write public void WriteFloat(float value) { - byte[] rawBytes = BitConverter.GetBytes(value); - if (!BitConverter.IsLittleEndian) - { - ByteArray.Reverse(rawBytes); - } - - if (limit - position >= 4) - { - buffer[position++] = rawBytes[0]; - buffer[position++] = rawBytes[1]; - buffer[position++] = rawBytes[2]; - buffer[position++] = rawBytes[3]; - } - else - { - WriteRawBytes(rawBytes, 0, 4); - } + var span = new Span(buffer); + WritingPrimitives.WriteFloat(ref span, ref state, value); } /// @@ -203,7 +190,8 @@ namespace Google.Protobuf /// The value to write public void WriteUInt64(ulong value) { - WriteRawVarint64(value); + var span = new Span(buffer); + WritingPrimitives.WriteUInt64(ref span, ref state, value); } /// @@ -212,7 +200,8 @@ namespace Google.Protobuf /// The value to write public void WriteInt64(long value) { - WriteRawVarint64((ulong) value); + var span = new Span(buffer); + WritingPrimitives.WriteInt64(ref span, ref state, value); } /// @@ -221,15 +210,8 @@ namespace Google.Protobuf /// The value to write public void WriteInt32(int value) { - if (value >= 0) - { - WriteRawVarint32((uint) value); - } - else - { - // Must sign-extend. - WriteRawVarint64((ulong) value); - } + var span = new Span(buffer); + WritingPrimitives.WriteInt32(ref span, ref state, value); } /// @@ -238,7 +220,8 @@ namespace Google.Protobuf /// The value to write public void WriteFixed64(ulong value) { - WriteRawLittleEndian64(value); + var span = new Span(buffer); + WritingPrimitives.WriteFixed64(ref span, ref state, value); } /// @@ -247,7 +230,8 @@ namespace Google.Protobuf /// The value to write public void WriteFixed32(uint value) { - WriteRawLittleEndian32(value); + var span = new Span(buffer); + WritingPrimitives.WriteFixed32(ref span, ref state, value); } /// @@ -256,7 +240,8 @@ namespace Google.Protobuf /// The value to write public void WriteBool(bool value) { - WriteRawByte(value ? (byte) 1 : (byte) 0); + var span = new Span(buffer); + WritingPrimitives.WriteBool(ref span, ref state, value); } /// @@ -266,41 +251,52 @@ namespace Google.Protobuf /// The value to write public void WriteString(string value) { - // Optimise the case where we have enough space to write - // the string directly to the buffer, which should be common. - int length = Utf8Encoding.GetByteCount(value); - WriteLength(length); - if (limit - position >= length) + var span = new Span(buffer); + WritingPrimitives.WriteString(ref span, ref state, value); + } + + /// + /// Writes a message, without a tag, to the stream. + /// The data is length-prefixed. + /// + /// The value to write + public void WriteMessage(IMessage value) + { + // TODO(jtattermusch): if the message doesn't implement IBufferMessage (and thus does not provide the InternalWriteTo method), + // what we're doing here works fine, but could be more efficient. + // For now, this inefficiency is fine, considering this is only a backward-compatibility scenario (and regenerating the code fixes it). + var span = new Span(buffer); + WriteContext.Initialize(ref span, ref state, out WriteContext ctx); + try { - if (length == value.Length) // Must be all ASCII... - { - for (int i = 0; i < length; i++) - { - buffer[position + i] = (byte)value[i]; - } - } - else - { - Utf8Encoding.GetBytes(value, 0, value.Length, buffer, position); - } - position += length; + WritingPrimitivesMessages.WriteMessage(ref ctx, value); } - else + finally { - byte[] bytes = Utf8Encoding.GetBytes(value); - WriteRawBytes(bytes); + ctx.CopyStateTo(this); } } /// /// Writes a message, without a tag, to the stream. - /// The data is length-prefixed. + /// Only the message data is written, without a length-delimiter. /// /// The value to write - public void WriteMessage(IMessage value) - { - WriteLength(value.CalculateSize()); - value.WriteTo(this); + public void WriteRawMessage(IMessage value) + { + // TODO(jtattermusch): if the message doesn't implement IBufferMessage (and thus does not provide the InternalWriteTo method), + // what we're doing here works fine, but could be more efficient. + // For now, this inefficiency is fine, considering this is only a backward-compatibility scenario (and regenerating the code fixes it). + var span = new Span(buffer); + WriteContext.Initialize(ref span, ref state, out WriteContext ctx); + try + { + WritingPrimitivesMessages.WriteRawMessage(ref ctx, value); + } + finally + { + ctx.CopyStateTo(this); + } } /// @@ -309,7 +305,16 @@ namespace Google.Protobuf /// The value to write public void WriteGroup(IMessage value) { - value.WriteTo(this); + var span = new Span(buffer); + WriteContext.Initialize(ref span, ref state, out WriteContext ctx); + try + { + WritingPrimitivesMessages.WriteGroup(ref ctx, value); + } + finally + { + ctx.CopyStateTo(this); + } } /// @@ -319,8 +324,8 @@ namespace Google.Protobuf /// The value to write public void WriteBytes(ByteString value) { - WriteLength(value.Length); - value.WriteRawBytesTo(this); + var span = new Span(buffer); + WritingPrimitives.WriteBytes(ref span, ref state, value); } /// @@ -329,7 +334,8 @@ namespace Google.Protobuf /// The value to write public void WriteUInt32(uint value) { - WriteRawVarint32(value); + var span = new Span(buffer); + WritingPrimitives.WriteUInt32(ref span, ref state, value); } /// @@ -338,7 +344,8 @@ namespace Google.Protobuf /// The value to write public void WriteEnum(int value) { - WriteInt32(value); + var span = new Span(buffer); + WritingPrimitives.WriteEnum(ref span, ref state, value); } /// @@ -347,7 +354,8 @@ namespace Google.Protobuf /// The value to write. public void WriteSFixed32(int value) { - WriteRawLittleEndian32((uint) value); + var span = new Span(buffer); + WritingPrimitives.WriteSFixed32(ref span, ref state, value); } /// @@ -356,7 +364,8 @@ namespace Google.Protobuf /// The value to write public void WriteSFixed64(long value) { - WriteRawLittleEndian64((ulong) value); + var span = new Span(buffer); + WritingPrimitives.WriteSFixed64(ref span, ref state, value); } /// @@ -365,7 +374,8 @@ namespace Google.Protobuf /// The value to write public void WriteSInt32(int value) { - WriteRawVarint32(EncodeZigZag32(value)); + var span = new Span(buffer); + WritingPrimitives.WriteSInt32(ref span, ref state, value); } /// @@ -374,7 +384,8 @@ namespace Google.Protobuf /// The value to write public void WriteSInt64(long value) { - WriteRawVarint64(EncodeZigZag64(value)); + var span = new Span(buffer); + WritingPrimitives.WriteSInt64(ref span, ref state, value); } /// @@ -386,7 +397,8 @@ namespace Google.Protobuf /// Length value, in bytes. public void WriteLength(int length) { - WriteRawVarint32((uint) length); + var span = new Span(buffer); + WritingPrimitives.WriteLength(ref span, ref state, length); } #endregion @@ -399,7 +411,8 @@ namespace Google.Protobuf /// The wire format type of the tag to write public void WriteTag(int fieldNumber, WireFormat.WireType type) { - WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type)); + var span = new Span(buffer); + WritingPrimitives.WriteTag(ref span, ref state, fieldNumber, type); } /// @@ -408,7 +421,8 @@ namespace Google.Protobuf /// The encoded tag public void WriteTag(uint tag) { - WriteRawVarint32(tag); + var span = new Span(buffer); + WritingPrimitives.WriteTag(ref span, ref state, tag); } /// @@ -417,7 +431,8 @@ namespace Google.Protobuf /// The encoded tag public void WriteRawTag(byte b1) { - WriteRawByte(b1); + var span = new Span(buffer); + WritingPrimitives.WriteRawTag(ref span, ref state, b1); } /// @@ -427,8 +442,8 @@ namespace Google.Protobuf /// The second byte of the encoded tag public void WriteRawTag(byte b1, byte b2) { - WriteRawByte(b1); - WriteRawByte(b2); + var span = new Span(buffer); + WritingPrimitives.WriteRawTag(ref span, ref state, b1, b2); } /// @@ -439,9 +454,8 @@ namespace Google.Protobuf /// The third byte of the encoded tag public void WriteRawTag(byte b1, byte b2, byte b3) { - WriteRawByte(b1); - WriteRawByte(b2); - WriteRawByte(b3); + var span = new Span(buffer); + WritingPrimitives.WriteRawTag(ref span, ref state, b1, b2, b3); } /// @@ -453,10 +467,8 @@ namespace Google.Protobuf /// The fourth byte of the encoded tag public void WriteRawTag(byte b1, byte b2, byte b3, byte b4) { - WriteRawByte(b1); - WriteRawByte(b2); - WriteRawByte(b3); - WriteRawByte(b4); + var span = new Span(buffer); + WritingPrimitives.WriteRawTag(ref span, ref state, b1, b2, b3, b4); } /// @@ -469,15 +481,13 @@ namespace Google.Protobuf /// The fifth byte of the encoded tag public void WriteRawTag(byte b1, byte b2, byte b3, byte b4, byte b5) { - WriteRawByte(b1); - WriteRawByte(b2); - WriteRawByte(b3); - WriteRawByte(b4); - WriteRawByte(b5); + var span = new Span(buffer); + WritingPrimitives.WriteRawTag(ref span, ref state, b1, b2, b3, b4, b5); } #endregion #region Underlying writing primitives + /// /// Writes a 32 bit value as a varint. The fast route is taken when /// there's enough buffer space left to whizz through without checking @@ -485,112 +495,26 @@ namespace Google.Protobuf /// internal void WriteRawVarint32(uint value) { - // Optimize for the common case of a single byte value - if (value < 128 && position < limit) - { - buffer[position++] = (byte)value; - return; - } - - while (value > 127 && position < limit) - { - buffer[position++] = (byte) ((value & 0x7F) | 0x80); - value >>= 7; - } - while (value > 127) - { - WriteRawByte((byte) ((value & 0x7F) | 0x80)); - value >>= 7; - } - if (position < limit) - { - buffer[position++] = (byte) value; - } - else - { - WriteRawByte((byte) value); - } + var span = new Span(buffer); + WritingPrimitives.WriteRawVarint32(ref span, ref state, value); } internal void WriteRawVarint64(ulong value) { - while (value > 127 && position < limit) - { - buffer[position++] = (byte) ((value & 0x7F) | 0x80); - value >>= 7; - } - while (value > 127) - { - WriteRawByte((byte) ((value & 0x7F) | 0x80)); - value >>= 7; - } - if (position < limit) - { - buffer[position++] = (byte) value; - } - else - { - WriteRawByte((byte) value); - } + var span = new Span(buffer); + WritingPrimitives.WriteRawVarint64(ref span, ref state, value); } internal void WriteRawLittleEndian32(uint value) { - if (position + 4 > limit) - { - WriteRawByte((byte) value); - WriteRawByte((byte) (value >> 8)); - WriteRawByte((byte) (value >> 16)); - WriteRawByte((byte) (value >> 24)); - } - else - { - buffer[position++] = ((byte) value); - buffer[position++] = ((byte) (value >> 8)); - buffer[position++] = ((byte) (value >> 16)); - buffer[position++] = ((byte) (value >> 24)); - } + var span = new Span(buffer); + WritingPrimitives.WriteRawLittleEndian32(ref span, ref state, value); } internal void WriteRawLittleEndian64(ulong value) { - if (position + 8 > limit) - { - WriteRawByte((byte) value); - WriteRawByte((byte) (value >> 8)); - WriteRawByte((byte) (value >> 16)); - WriteRawByte((byte) (value >> 24)); - WriteRawByte((byte) (value >> 32)); - WriteRawByte((byte) (value >> 40)); - WriteRawByte((byte) (value >> 48)); - WriteRawByte((byte) (value >> 56)); - } - else - { - buffer[position++] = ((byte) value); - buffer[position++] = ((byte) (value >> 8)); - buffer[position++] = ((byte) (value >> 16)); - buffer[position++] = ((byte) (value >> 24)); - buffer[position++] = ((byte) (value >> 32)); - buffer[position++] = ((byte) (value >> 40)); - buffer[position++] = ((byte) (value >> 48)); - buffer[position++] = ((byte) (value >> 56)); - } - } - - internal void WriteRawByte(byte value) - { - if (position == limit) - { - RefreshBuffer(); - } - - buffer[position++] = value; - } - - internal void WriteRawByte(uint value) - { - WriteRawByte((byte) value); + var span = new Span(buffer); + WritingPrimitives.WriteRawLittleEndian64(ref span, ref state, value); } /// @@ -606,85 +530,12 @@ namespace Google.Protobuf /// internal void WriteRawBytes(byte[] value, int offset, int length) { - if (limit - position >= length) - { - ByteArray.Copy(value, offset, buffer, position, length); - // We have room in the current buffer. - position += length; - } - else - { - // Write extends past current buffer. Fill the rest of this buffer and - // flush. - int bytesWritten = limit - position; - ByteArray.Copy(value, offset, buffer, position, bytesWritten); - offset += bytesWritten; - length -= bytesWritten; - position = limit; - RefreshBuffer(); - - // Now deal with the rest. - // Since we have an output stream, this is our buffer - // and buffer offset == 0 - if (length <= limit) - { - // Fits in new buffer. - ByteArray.Copy(value, offset, buffer, 0, length); - position = length; - } - else - { - // Write is very big. Let's do it all at once. - output.Write(value, offset, length); - } - } + var span = new Span(buffer); + WritingPrimitives.WriteRawBytes(ref span, ref state, value, offset, length); } #endregion - /// - /// Encode a 32-bit value with ZigZag encoding. - /// - /// - /// ZigZag encodes signed integers into values that can be efficiently - /// encoded with varint. (Otherwise, negative values must be - /// sign-extended to 64 bits to be varint encoded, thus always taking - /// 10 bytes on the wire.) - /// - internal static uint EncodeZigZag32(int n) - { - // Note: the right-shift must be arithmetic - return (uint) ((n << 1) ^ (n >> 31)); - } - - /// - /// Encode a 64-bit value with ZigZag encoding. - /// - /// - /// ZigZag encodes signed integers into values that can be efficiently - /// encoded with varint. (Otherwise, negative values must be - /// sign-extended to 64 bits to be varint encoded, thus always taking - /// 10 bytes on the wire.) - /// - internal static ulong EncodeZigZag64(long n) - { - return (ulong) ((n << 1) ^ (n >> 63)); - } - - private void RefreshBuffer() - { - if (output == null) - { - // We're writing to a single buffer. - throw new OutOfSpaceException(); - } - - // Since we have an output stream, this is our buffer - // and buffer offset == 0 - output.Write(buffer, 0, position); - position = 0; - } - /// /// Indicates that a CodedOutputStream wrapping a flat byte array /// ran out of space. @@ -726,45 +577,31 @@ namespace Google.Protobuf /// public void Flush() { - if (output != null) - { - RefreshBuffer(); - } + var span = new Span(buffer); + WriteBufferHelper.Flush(ref span, ref state); } /// /// Verifies that SpaceLeft returns zero. It's common to create a byte array /// that is exactly big enough to hold a message, then write to it with /// a CodedOutputStream. Calling CheckNoSpaceLeft after writing verifies that - /// the message was actually as big as expected, which can help bugs. + /// the message was actually as big as expected, which can help finding bugs. /// public void CheckNoSpaceLeft() { - if (SpaceLeft != 0) - { - throw new InvalidOperationException("Did not write as much data as expected."); - } + WriteBufferHelper.CheckNoSpaceLeft(ref state); } /// /// If writing to a flat array, returns the space left in the array. Otherwise, /// throws an InvalidOperationException. /// - public int SpaceLeft - { - get - { - if (output == null) - { - return limit - position; - } - else - { - throw new InvalidOperationException( - "SpaceLeft can only be called on CodedOutputStreams that are " + - "writing to a flat array."); - } - } - } + public int SpaceLeft => WriteBufferHelper.GetSpaceLeft(ref state); + + internal byte[] InternalBuffer => buffer; + + internal Stream InternalOutputStream => output; + + internal ref WriterInternalState InternalState => ref state; } } diff --git a/csharp/src/Google.Protobuf/Collections/MapField.cs b/csharp/src/Google.Protobuf/Collections/MapField.cs index 48cd7ab445..d60ebc5a8a 100644 --- a/csharp/src/Google.Protobuf/Collections/MapField.cs +++ b/csharp/src/Google.Protobuf/Collections/MapField.cs @@ -464,14 +464,34 @@ namespace Google.Protobuf.Collections /// The output stream to write to. /// The codec to use for each entry. public void WriteTo(CodedOutputStream output, Codec codec) + { + WriteContext.Initialize(output, out WriteContext ctx); + try + { + WriteTo(ref ctx, codec); + } + finally + { + ctx.CopyStateTo(output); + } + } + + /// + /// Writes the contents of this map to the given write context, using the specified codec + /// to encode each entry. + /// + /// The write context to write to. + /// The codec to use for each entry. + [SecuritySafeCritical] + public void WriteTo(ref WriteContext ctx, Codec codec) { var message = new Codec.MessageAdapter(codec); foreach (var entry in list) { message.Key = entry.Key; message.Value = entry.Value; - output.WriteTag(codec.MapTag); - output.WriteMessage(message); + ctx.WriteTag(codec.MapTag); + ctx.WriteMessage(message); } } @@ -711,8 +731,15 @@ namespace Google.Protobuf.Collections public void WriteTo(CodedOutputStream output) { - codec.keyCodec.WriteTagAndValue(output, Key); - codec.valueCodec.WriteTagAndValue(output, Value); + // Message adapter is an internal class and we know that all the writing will happen via InternalWriteTo. + throw new NotImplementedException(); + } + + [SecuritySafeCritical] + public void InternalWriteTo(ref WriteContext ctx) + { + codec.keyCodec.WriteTagAndValue(ref ctx, Key); + codec.valueCodec.WriteTagAndValue(ref ctx, Value); } public int CalculateSize() diff --git a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs index b1bd9b13d1..69adcdfafc 100644 --- a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs +++ b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs @@ -189,7 +189,7 @@ namespace Google.Protobuf.Collections /// Calculates the size of this collection based on the given codec. /// /// The codec to use when encoding each field. - /// The number of bytes that would be written to a by , + /// The number of bytes that would be written to an output by one of the WriteTo methods, /// using the same codec. public int CalculateSize(FieldCodec codec) { @@ -247,6 +247,26 @@ namespace Google.Protobuf.Collections /// The output stream to write to. /// The codec to use when encoding each value. public void WriteTo(CodedOutputStream output, FieldCodec codec) + { + WriteContext.Initialize(output, out WriteContext ctx); + try + { + WriteTo(ref ctx, codec); + } + finally + { + ctx.CopyStateTo(output); + } + } + + /// + /// Writes the contents of this collection to the given write context, + /// encoding each value using the specified codec. + /// + /// The write context to write to. + /// The codec to use when encoding each value. + [SecuritySafeCritical] + public void WriteTo(ref WriteContext ctx, FieldCodec codec) { if (count == 0) { @@ -257,12 +277,12 @@ namespace Google.Protobuf.Collections if (codec.PackedRepeatedField) { // Packed primitive type - uint size = (uint)CalculatePackedDataSize(codec); - output.WriteTag(tag); - output.WriteRawVarint32(size); + int size = CalculatePackedDataSize(codec); + ctx.WriteTag(tag); + ctx.WriteLength(size); for (int i = 0; i < count; i++) { - writer(output, array[i]); + writer(ref ctx, array[i]); } } else @@ -271,11 +291,11 @@ namespace Google.Protobuf.Collections // Can't use codec.WriteTagAndValue, as that omits default values. for (int i = 0; i < count; i++) { - output.WriteTag(tag); - writer(output, array[i]); + ctx.WriteTag(tag); + writer(ref ctx, array[i]); if (codec.EndTag != 0) { - output.WriteTag(codec.EndTag); + ctx.WriteTag(codec.EndTag); } } } diff --git a/csharp/src/Google.Protobuf/ExtensionSet.cs b/csharp/src/Google.Protobuf/ExtensionSet.cs index dd0b9a5519..895b9ae6ea 100644 --- a/csharp/src/Google.Protobuf/ExtensionSet.cs +++ b/csharp/src/Google.Protobuf/ExtensionSet.cs @@ -34,6 +34,7 @@ using Google.Protobuf.Collections; using System; using System.Collections.Generic; using System.Linq; +using System.Security; namespace Google.Protobuf { @@ -343,10 +344,28 @@ namespace Google.Protobuf /// Writes the extension values in this set to the output stream /// public void WriteTo(CodedOutputStream stream) + { + + WriteContext.Initialize(stream, out WriteContext ctx); + try + { + WriteTo(ref ctx); + } + finally + { + ctx.CopyStateTo(stream); + } + } + + /// + /// Writes the extension values in this set to the write context + /// + [SecuritySafeCritical] + public void WriteTo(ref WriteContext ctx) { foreach (var value in ValuesByNumber.Values) { - value.WriteTo(stream); + value.WriteTo(ref ctx); } } diff --git a/csharp/src/Google.Protobuf/ExtensionValue.cs b/csharp/src/Google.Protobuf/ExtensionValue.cs index df934ed7a1..ada5d79c80 100644 --- a/csharp/src/Google.Protobuf/ExtensionValue.cs +++ b/csharp/src/Google.Protobuf/ExtensionValue.cs @@ -41,7 +41,7 @@ namespace Google.Protobuf void MergeFrom(ref ParseContext ctx); void MergeFrom(IExtensionValue value); - void WriteTo(CodedOutputStream output); + void WriteTo(ref WriteContext ctx); int CalculateSize(); bool IsInitialized(); } @@ -106,13 +106,13 @@ namespace Google.Protobuf } } - public void WriteTo(CodedOutputStream output) + public void WriteTo(ref WriteContext ctx) { - output.WriteTag(codec.Tag); - codec.ValueWriter(output, field); + ctx.WriteTag(codec.Tag); + codec.ValueWriter(ref ctx, field); if (codec.EndTag != 0) { - output.WriteTag(codec.EndTag); + ctx.WriteTag(codec.EndTag); } } @@ -181,11 +181,6 @@ namespace Google.Protobuf } } - public void MergeFrom(CodedInputStream input) - { - field.AddEntriesFrom(input, codec); - } - public void MergeFrom(ref ParseContext ctx) { field.AddEntriesFrom(ref ctx, codec); @@ -199,9 +194,9 @@ namespace Google.Protobuf } } - public void WriteTo(CodedOutputStream output) + public void WriteTo(ref WriteContext ctx) { - field.WriteTo(output, codec); + field.WriteTo(ref ctx, codec); } public RepeatedField GetValue() => field; diff --git a/csharp/src/Google.Protobuf/FieldCodec.cs b/csharp/src/Google.Protobuf/FieldCodec.cs index ee87736d1f..158739d50a 100644 --- a/csharp/src/Google.Protobuf/FieldCodec.cs +++ b/csharp/src/Google.Protobuf/FieldCodec.cs @@ -219,7 +219,7 @@ namespace Google.Protobuf /// A codec for the given tag. public static FieldCodec ForString(uint tag, string defaultValue) { - return new FieldCodec((ref ParseContext ctx) => ctx.ReadString(), (output, value) => output.WriteString(value), CodedOutputStream.ComputeStringSize, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadString(), (ref WriteContext ctx, string value) => ctx.WriteString(value), CodedOutputStream.ComputeStringSize, tag, defaultValue); } /// @@ -230,7 +230,7 @@ namespace Google.Protobuf /// A codec for the given tag. public static FieldCodec ForBytes(uint tag, ByteString defaultValue) { - return new FieldCodec((ref ParseContext ctx) => ctx.ReadBytes(), (output, value) => output.WriteBytes(value), CodedOutputStream.ComputeBytesSize, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadBytes(), (ref WriteContext ctx, ByteString value) => ctx.WriteBytes(value), CodedOutputStream.ComputeBytesSize, tag, defaultValue); } /// @@ -241,7 +241,7 @@ namespace Google.Protobuf /// A codec for the given tag. public static FieldCodec ForBool(uint tag, bool defaultValue) { - return new FieldCodec((ref ParseContext ctx) => ctx.ReadBool(), (output, value) => output.WriteBool(value), CodedOutputStream.BoolSize, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadBool(), (ref WriteContext ctx, bool value) => ctx.WriteBool(value), CodedOutputStream.BoolSize, tag, defaultValue); } /// @@ -252,7 +252,7 @@ namespace Google.Protobuf /// A codec for the given tag. public static FieldCodec ForInt32(uint tag, int defaultValue) { - return new FieldCodec((ref ParseContext ctx) => ctx.ReadInt32(), (output, value) => output.WriteInt32(value), CodedOutputStream.ComputeInt32Size, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadInt32(), (ref WriteContext output, int value) => output.WriteInt32(value), CodedOutputStream.ComputeInt32Size, tag, defaultValue); } /// @@ -263,7 +263,7 @@ namespace Google.Protobuf /// A codec for the given tag. public static FieldCodec ForSInt32(uint tag, int defaultValue) { - return new FieldCodec((ref ParseContext ctx) => ctx.ReadSInt32(), (output, value) => output.WriteSInt32(value), CodedOutputStream.ComputeSInt32Size, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadSInt32(), (ref WriteContext output, int value) => output.WriteSInt32(value), CodedOutputStream.ComputeSInt32Size, tag, defaultValue); } /// @@ -274,7 +274,7 @@ namespace Google.Protobuf /// A codec for the given tag. public static FieldCodec ForFixed32(uint tag, uint defaultValue) { - return new FieldCodec((ref ParseContext ctx) => ctx.ReadFixed32(), (output, value) => output.WriteFixed32(value), 4, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadFixed32(), (ref WriteContext output, uint value) => output.WriteFixed32(value), 4, tag, defaultValue); } /// @@ -285,7 +285,7 @@ namespace Google.Protobuf /// A codec for the given tag. public static FieldCodec ForSFixed32(uint tag, int defaultValue) { - return new FieldCodec((ref ParseContext ctx) => ctx.ReadSFixed32(), (output, value) => output.WriteSFixed32(value), 4, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadSFixed32(), (ref WriteContext output, int value) => output.WriteSFixed32(value), 4, tag, defaultValue); } /// @@ -296,7 +296,7 @@ namespace Google.Protobuf /// A codec for the given tag. public static FieldCodec ForUInt32(uint tag, uint defaultValue) { - return new FieldCodec((ref ParseContext ctx) => ctx.ReadUInt32(), (output, value) => output.WriteUInt32(value), CodedOutputStream.ComputeUInt32Size, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadUInt32(), (ref WriteContext output, uint value) => output.WriteUInt32(value), CodedOutputStream.ComputeUInt32Size, tag, defaultValue); } /// @@ -307,7 +307,7 @@ namespace Google.Protobuf /// A codec for the given tag. public static FieldCodec ForInt64(uint tag, long defaultValue) { - return new FieldCodec((ref ParseContext ctx) => ctx.ReadInt64(), (output, value) => output.WriteInt64(value), CodedOutputStream.ComputeInt64Size, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadInt64(), (ref WriteContext output, long value) => output.WriteInt64(value), CodedOutputStream.ComputeInt64Size, tag, defaultValue); } /// @@ -318,7 +318,7 @@ namespace Google.Protobuf /// A codec for the given tag. public static FieldCodec ForSInt64(uint tag, long defaultValue) { - return new FieldCodec((ref ParseContext ctx) => ctx.ReadSInt64(), (output, value) => output.WriteSInt64(value), CodedOutputStream.ComputeSInt64Size, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadSInt64(), (ref WriteContext output, long value) => output.WriteSInt64(value), CodedOutputStream.ComputeSInt64Size, tag, defaultValue); } /// @@ -329,7 +329,7 @@ namespace Google.Protobuf /// A codec for the given tag. public static FieldCodec ForFixed64(uint tag, ulong defaultValue) { - return new FieldCodec((ref ParseContext ctx) => ctx.ReadFixed64(), (output, value) => output.WriteFixed64(value), 8, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadFixed64(), (ref WriteContext output, ulong value) => output.WriteFixed64(value), 8, tag, defaultValue); } /// @@ -340,7 +340,7 @@ namespace Google.Protobuf /// A codec for the given tag. public static FieldCodec ForSFixed64(uint tag, long defaultValue) { - return new FieldCodec((ref ParseContext ctx) => ctx.ReadSFixed64(), (output, value) => output.WriteSFixed64(value), 8, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadSFixed64(), (ref WriteContext output, long value) => output.WriteSFixed64(value), 8, tag, defaultValue); } /// @@ -351,7 +351,7 @@ namespace Google.Protobuf /// A codec for the given tag. public static FieldCodec ForUInt64(uint tag, ulong defaultValue) { - return new FieldCodec((ref ParseContext ctx) => ctx.ReadUInt64(), (output, value) => output.WriteUInt64(value), CodedOutputStream.ComputeUInt64Size, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadUInt64(), (ref WriteContext output, ulong value) => output.WriteUInt64(value), CodedOutputStream.ComputeUInt64Size, tag, defaultValue); } /// @@ -362,7 +362,7 @@ namespace Google.Protobuf /// A codec for the given tag. public static FieldCodec ForFloat(uint tag, float defaultValue) { - return new FieldCodec((ref ParseContext ctx) => ctx.ReadFloat(), (output, value) => output.WriteFloat(value), CodedOutputStream.FloatSize, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadFloat(), (ref WriteContext output, float value) => output.WriteFloat(value), CodedOutputStream.FloatSize, tag, defaultValue); } /// @@ -373,7 +373,7 @@ namespace Google.Protobuf /// A codec for the given tag. public static FieldCodec ForDouble(uint tag, double defaultValue) { - return new FieldCodec((ref ParseContext ctx) => ctx.ReadDouble(), (output, value) => output.WriteDouble(value), CodedOutputStream.DoubleSize, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadDouble(), (ref WriteContext output, double value) => output.WriteDouble(value), CodedOutputStream.DoubleSize, tag, defaultValue); } // Enums are tricky. We can probably use expression trees to build these delegates automatically, @@ -391,7 +391,7 @@ namespace Google.Protobuf { return new FieldCodec((ref ParseContext ctx) => fromInt32( ctx.ReadEnum()), - (output, value) => output.WriteEnum(toInt32(value)), + (ref WriteContext output, T value) => output.WriteEnum(toInt32(value)), value => CodedOutputStream.ComputeEnumSize(toInt32(value)), tag, defaultValue); } @@ -410,7 +410,7 @@ namespace Google.Protobuf ctx.ReadMessage(message); return message; }, - (output, value) => output.WriteMessage(value), + (ref WriteContext output, T value) => output.WriteMessage(value), (ref ParseContext ctx, ref T v) => { if (v == null) @@ -455,7 +455,7 @@ namespace Google.Protobuf ctx.ReadGroup(message); return message; }, - (output, value) => output.WriteGroup(value), + (ref WriteContext output, T value) => output.WriteGroup(value), (ref ParseContext ctx, ref T v) => { if (v == null) @@ -492,7 +492,7 @@ namespace Google.Protobuf var nestedCodec = WrapperCodecs.GetCodec(); return new FieldCodec( (ref ParseContext ctx) => WrapperCodecs.Read(ref ctx, nestedCodec), - (output, value) => WrapperCodecs.Write(output, value, nestedCodec), + (ref WriteContext output, T value) => WrapperCodecs.Write(ref output, value, nestedCodec), (ref ParseContext ctx, ref T v) => v = WrapperCodecs.Read(ref ctx, nestedCodec), (ref T v, T v2) => { v = v2; return v == null; }, value => WrapperCodecs.CalculateSize(value, nestedCodec), @@ -509,7 +509,7 @@ namespace Google.Protobuf var nestedCodec = WrapperCodecs.GetCodec(); return new FieldCodec( WrapperCodecs.GetReader(), - (output, value) => WrapperCodecs.Write(output, value.Value, nestedCodec), + (ref WriteContext output, T? value) => WrapperCodecs.Write(ref output, value.Value, nestedCodec), (ref ParseContext ctx, ref T? v) => v = WrapperCodecs.Read(ref ctx, nestedCodec), (ref T? v, T? v2) => { if (v2.HasValue) { v = v2; } return v.HasValue; }, value => value == null ? 0 : WrapperCodecs.CalculateSize(value.Value, nestedCodec), @@ -616,10 +616,10 @@ namespace Google.Protobuf return value; } - internal static void Write(CodedOutputStream output, T value, FieldCodec codec) + internal static void Write(ref WriteContext ctx, T value, FieldCodec codec) { - output.WriteLength(codec.CalculateSizeWithTag(value)); - codec.WriteTagAndValue(output, value); + ctx.WriteLength(codec.CalculateSizeWithTag(value)); + codec.WriteTagAndValue(ref ctx, value); } internal static int CalculateSize(T value, FieldCodec codec) @@ -631,6 +631,7 @@ namespace Google.Protobuf } internal delegate TValue ValueReader(ref ParseContext ctx); + internal delegate void ValueWriter(ref WriteContext ctx, T value); /// /// @@ -685,7 +686,7 @@ namespace Google.Protobuf /// /// Returns a delegate to write a value (unconditionally) to a coded output stream. /// - internal Action ValueWriter { get; } + internal ValueWriter ValueWriter { get; } /// /// Returns the size calculator for just a value. @@ -744,7 +745,7 @@ namespace Google.Protobuf internal FieldCodec( ValueReader reader, - Action writer, + ValueWriter writer, int fixedSize, uint tag, T defaultValue) : this(reader, writer, _ => fixedSize, tag, defaultValue) @@ -754,7 +755,7 @@ namespace Google.Protobuf internal FieldCodec( ValueReader reader, - Action writer, + ValueWriter writer, Func sizeCalculator, uint tag, T defaultValue) : this(reader, writer, (ref ParseContext ctx, ref T v) => v = reader(ref ctx), (ref T v, T v2) => { v = v2; return true; }, sizeCalculator, tag, 0, defaultValue) @@ -763,7 +764,7 @@ namespace Google.Protobuf internal FieldCodec( ValueReader reader, - Action writer, + ValueWriter writer, InputMerger inputMerger, ValuesMerger valuesMerger, Func sizeCalculator, @@ -774,7 +775,7 @@ namespace Google.Protobuf internal FieldCodec( ValueReader reader, - Action writer, + ValueWriter writer, InputMerger inputMerger, ValuesMerger valuesMerger, Func sizeCalculator, @@ -802,14 +803,41 @@ namespace Google.Protobuf /// Write a tag and the given value, *if* the value is not the default. /// public void WriteTagAndValue(CodedOutputStream output, T value) + { + WriteContext.Initialize(output, out WriteContext ctx); + try + { + WriteTagAndValue(ref ctx, value); + } + finally + { + ctx.CopyStateTo(output); + } + + + //if (!IsDefault(value)) + //{ + // output.WriteTag(Tag); + // ValueWriter(output, value); + // if (EndTag != 0) + // { + // output.WriteTag(EndTag); + // } + //} + } + + /// + /// Write a tag and the given value, *if* the value is not the default. + /// + public void WriteTagAndValue(ref WriteContext ctx, T value) { if (!IsDefault(value)) { - output.WriteTag(Tag); - ValueWriter(output, value); + ctx.WriteTag(Tag); + ValueWriter(ref ctx, value); if (EndTag != 0) { - output.WriteTag(EndTag); + ctx.WriteTag(EndTag); } } } diff --git a/csharp/src/Google.Protobuf/IBufferMessage.cs b/csharp/src/Google.Protobuf/IBufferMessage.cs index f6d174b3b7..c99a7d79fc 100644 --- a/csharp/src/Google.Protobuf/IBufferMessage.cs +++ b/csharp/src/Google.Protobuf/IBufferMessage.cs @@ -35,7 +35,7 @@ namespace Google.Protobuf #if GOOGLE_PROTOBUF_SUPPORT_SYSTEM_MEMORY /// /// Interface for a Protocol Buffers message, supporting - /// parsing from . + /// parsing from and writing to . /// public interface IBufferMessage : IMessage { @@ -44,6 +44,12 @@ namespace Google.Protobuf /// Users should never invoke this method directly. /// void InternalMergeFrom(ref ParseContext ctx); + + /// + /// Internal implementation of writing this message to a given write context. + /// Users should never invoke this method directly. + /// + void InternalWriteTo(ref WriteContext ctx); } #endif } diff --git a/csharp/src/Google.Protobuf/JsonFormatter.cs b/csharp/src/Google.Protobuf/JsonFormatter.cs index 699a81de51..4bffd58c1f 100644 --- a/csharp/src/Google.Protobuf/JsonFormatter.cs +++ b/csharp/src/Google.Protobuf/JsonFormatter.cs @@ -357,7 +357,7 @@ namespace Google.Protobuf /// The value to write. May be null. public void WriteValue(TextWriter writer, object value) { - if (value == null) + if (value == null || value is NullValue) { WriteNull(writer); } diff --git a/csharp/src/Google.Protobuf/JsonParser.cs b/csharp/src/Google.Protobuf/JsonParser.cs index 3f88ea38f1..cb5f5a8f21 100644 --- a/csharp/src/Google.Protobuf/JsonParser.cs +++ b/csharp/src/Google.Protobuf/JsonParser.cs @@ -37,6 +37,7 @@ using System.Collections; using System.Collections.Generic; using System.Globalization; using System.IO; +using System.Linq; using System.Text; using System.Text.RegularExpressions; @@ -63,6 +64,7 @@ namespace Google.Protobuf private static readonly Regex DurationRegex = new Regex(@"^(?-)?(?[0-9]{1,12})(?\.[0-9]{1,9})?s$", FrameworkPortability.CompiledRegexWhereAvailable); private static readonly int[] SubsecondScalingFactors = { 0, 100000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1 }; private static readonly char[] FieldMaskPathSeparators = new[] { ',' }; + private static readonly EnumDescriptor NullValueDescriptor = StructReflection.Descriptor.EnumTypes.Single(ed => ed.ClrType == typeof(NullValue)); private static readonly JsonParser defaultInstance = new JsonParser(Settings.Default); @@ -221,10 +223,11 @@ namespace Google.Protobuf if (token.Type == JsonToken.TokenType.Null) { // Clear the field if we see a null token, unless it's for a singular field of type - // google.protobuf.Value. + // google.protobuf.Value or google.protobuf.NullValue. // Note: different from Java API, which just ignores it. // TODO: Bring it more in line? Discuss... - if (field.IsMap || field.IsRepeated || !IsGoogleProtobufValueField(field)) + if (field.IsMap || field.IsRepeated || + !(IsGoogleProtobufValueField(field) || IsGoogleProtobufNullValueField(field))) { field.Accessor.Clear(message); return; @@ -314,6 +317,12 @@ namespace Google.Protobuf field.MessageType.FullName == Value.Descriptor.FullName; } + private static bool IsGoogleProtobufNullValueField(FieldDescriptor field) + { + return field.FieldType == FieldType.Enum && + field.EnumType.FullName == NullValueDescriptor.FullName; + } + private object ParseSingleValue(FieldDescriptor field, JsonTokenizer tokenizer) { var token = tokenizer.Next(); @@ -325,6 +334,10 @@ namespace Google.Protobuf { return Value.ForNull(); } + if (IsGoogleProtobufNullValueField(field)) + { + return NullValue.NullValue; + } return null; } diff --git a/csharp/src/Google.Protobuf/MessageExtensions.cs b/csharp/src/Google.Protobuf/MessageExtensions.cs index 51e40915c8..36a9df7286 100644 --- a/csharp/src/Google.Protobuf/MessageExtensions.cs +++ b/csharp/src/Google.Protobuf/MessageExtensions.cs @@ -33,6 +33,7 @@ using Google.Protobuf.Reflection; using System.Buffers; using System.Collections; +using System; using System.IO; using System.Linq; using System.Security; @@ -129,7 +130,7 @@ namespace Google.Protobuf ProtoPreconditions.CheckNotNull(message, "message"); ProtoPreconditions.CheckNotNull(output, "output"); CodedOutputStream codedOutput = new CodedOutputStream(output); - codedOutput.WriteRawVarint32((uint)message.CalculateSize()); + codedOutput.WriteLength(message.CalculateSize()); message.WriteTo(codedOutput); codedOutput.Flush(); } @@ -145,6 +146,39 @@ namespace Google.Protobuf return ByteString.AttachBytes(message.ToByteArray()); } + /// + /// Writes the given message data to the given buffer writer in protobuf encoding. + /// + /// The message to write to the stream. + /// The stream to write to. + [SecuritySafeCritical] + public static void WriteTo(this IMessage message, IBufferWriter output) + { + ProtoPreconditions.CheckNotNull(message, nameof(message)); + ProtoPreconditions.CheckNotNull(output, nameof(output)); + + WriteContext.Initialize(output, out WriteContext ctx); + WritingPrimitivesMessages.WriteRawMessage(ref ctx, message); + ctx.Flush(); + } + + /// + /// Writes the given message data to the given span in protobuf encoding. + /// The size of the destination span needs to fit the serialized size + /// of the message exactly, otherwise an exception is thrown. + /// + /// The message to write to the stream. + /// The span to write to. Size must match size of the message exactly. + [SecuritySafeCritical] + public static void WriteTo(this IMessage message, Span output) + { + ProtoPreconditions.CheckNotNull(message, nameof(message)); + + WriteContext.Initialize(ref output, out WriteContext ctx); + WritingPrimitivesMessages.WriteRawMessage(ref ctx, message); + ctx.CheckNoSpaceLeft(); + } + /// /// Checks if all required fields in a message have values set. For proto3 messages, this returns true /// diff --git a/csharp/src/Google.Protobuf/ParserInternalState.cs b/csharp/src/Google.Protobuf/ParserInternalState.cs index 4f0500b0a8..50d489dfc4 100644 --- a/csharp/src/Google.Protobuf/ParserInternalState.cs +++ b/csharp/src/Google.Protobuf/ParserInternalState.cs @@ -47,7 +47,7 @@ namespace Google.Protobuf // warning: this is a mutable struct, so it needs to be only passed as a ref! internal struct ParserInternalState { - // NOTE: the Span representing the current buffer is kept separate so that this doesn't have to be a ref struct and so it can live + // NOTE: the Span representing the current buffer is kept separate so that this doesn't have to be a ref struct and so it can // be included in CodedInputStream's internal state /// diff --git a/csharp/src/Google.Protobuf/ParsingPrimitives.cs b/csharp/src/Google.Protobuf/ParsingPrimitives.cs index 28a19493d4..ebb40840aa 100644 --- a/csharp/src/Google.Protobuf/ParsingPrimitives.cs +++ b/csharp/src/Google.Protobuf/ParsingPrimitives.cs @@ -629,7 +629,7 @@ namespace Google.Protobuf { fixed (byte* sourceBytes = &MemoryMarshal.GetReference(data)) { - value = CodedOutputStream.Utf8Encoding.GetString(sourceBytes, length); + value = WritingPrimitives.Utf8Encoding.GetString(sourceBytes, length); } } @@ -638,7 +638,7 @@ namespace Google.Protobuf } #endif - var decoder = CodedOutputStream.Utf8Encoding.GetDecoder(); + var decoder = WritingPrimitives.Utf8Encoding.GetDecoder(); // TODO: even if GOOGLE_PROTOBUF_SUPPORT_FAST_STRING is not supported, // we could still create a string efficiently by using Utf8Encoding.GetString(byte[] bytes, int index, int count) @@ -649,7 +649,7 @@ namespace Google.Protobuf // creating a string from that array might be more efficient than creating a string from the copied bytes. // Slow path: Build a byte array first then copy it. - return CodedOutputStream.Utf8Encoding.GetString(ReadRawBytes(ref buffer, ref state, length), 0, length); + return WritingPrimitives.Utf8Encoding.GetString(ReadRawBytes(ref buffer, ref state, length), 0, length); } [SecuritySafeCritical] diff --git a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs index 91e457ebb8..0a1f4a7440 100644 --- a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs @@ -275,12 +275,26 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else file_.WriteTo(output, _repeated_file_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + file_.WriteTo(ref output, _repeated_file_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -638,6 +652,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasName) { output.WriteRawTag(10); output.WriteString(Name); @@ -668,7 +685,44 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasName) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (HasPackage) { + output.WriteRawTag(18); + output.WriteString(Package); + } + dependency_.WriteTo(ref output, _repeated_dependency_codec); + messageType_.WriteTo(ref output, _repeated_messageType_codec); + enumType_.WriteTo(ref output, _repeated_enumType_codec); + service_.WriteTo(ref output, _repeated_service_codec); + extension_.WriteTo(ref output, _repeated_extension_codec); + if (options_ != null) { + output.WriteRawTag(66); + output.WriteMessage(Options); + } + if (sourceCodeInfo_ != null) { + output.WriteRawTag(74); + output.WriteMessage(SourceCodeInfo); + } + publicDependency_.WriteTo(ref output, _repeated_publicDependency_codec); + weakDependency_.WriteTo(ref output, _repeated_weakDependency_codec); + if (HasSyntax) { + output.WriteRawTag(98); + output.WriteString(Syntax); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1101,6 +1155,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasName) { output.WriteRawTag(10); output.WriteString(Name); @@ -1120,8 +1177,34 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasName) { + output.WriteRawTag(10); + output.WriteString(Name); + } + field_.WriteTo(ref output, _repeated_field_codec); + nestedType_.WriteTo(ref output, _repeated_nestedType_codec); + enumType_.WriteTo(ref output, _repeated_enumType_codec); + extensionRange_.WriteTo(ref output, _repeated_extensionRange_codec); + extension_.WriteTo(ref output, _repeated_extension_codec); + if (options_ != null) { + output.WriteRawTag(58); + output.WriteMessage(Options); + } + oneofDecl_.WriteTo(ref output, _repeated_oneofDecl_codec); + reservedRange_.WriteTo(ref output, _repeated_reservedRange_codec); + reservedName_.WriteTo(ref output, _repeated_reservedName_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -1435,6 +1518,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasStart) { output.WriteRawTag(8); output.WriteInt32(Start); @@ -1450,8 +1536,30 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasStart) { + output.WriteRawTag(8); + output.WriteInt32(Start); + } + if (HasEnd) { + output.WriteRawTag(16); + output.WriteInt32(End); + } + if (options_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Options); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -1688,6 +1796,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasStart) { output.WriteRawTag(8); output.WriteInt32(Start); @@ -1699,8 +1810,26 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasStart) { + output.WriteRawTag(8); + output.WriteInt32(Start); + } + if (HasEnd) { + output.WriteRawTag(16); + output.WriteInt32(End); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -1877,6 +2006,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec); if (_extensions != null) { _extensions.WriteTo(output); @@ -1884,7 +2016,21 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -2383,6 +2529,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasName) { output.WriteRawTag(10); output.WriteString(Name); @@ -2430,8 +2579,62 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasName) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (HasExtendee) { + output.WriteRawTag(18); + output.WriteString(Extendee); + } + if (HasNumber) { + output.WriteRawTag(24); + output.WriteInt32(Number); + } + if (HasLabel) { + output.WriteRawTag(32); + output.WriteEnum((int) Label); + } + if (HasType) { + output.WriteRawTag(40); + output.WriteEnum((int) Type); + } + if (HasTypeName) { + output.WriteRawTag(50); + output.WriteString(TypeName); + } + if (HasDefaultValue) { + output.WriteRawTag(58); + output.WriteString(DefaultValue); + } + if (options_ != null) { + output.WriteRawTag(66); + output.WriteMessage(Options); + } + if (HasOneofIndex) { + output.WriteRawTag(72); + output.WriteInt32(OneofIndex); + } + if (HasJsonName) { + output.WriteRawTag(82); + output.WriteString(JsonName); + } + if (HasProto3Optional) { + output.WriteRawTag(136, 1); + output.WriteBool(Proto3Optional); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -2823,6 +3026,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasName) { output.WriteRawTag(10); output.WriteString(Name); @@ -2834,8 +3040,26 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasName) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (options_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Options); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -3082,6 +3306,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasName) { output.WriteRawTag(10); output.WriteString(Name); @@ -3096,8 +3323,29 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasName) { + output.WriteRawTag(10); + output.WriteString(Name); + } + value_.WriteTo(ref output, _repeated_value_codec); + if (options_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Options); + } + reservedRange_.WriteTo(ref output, _repeated_reservedRange_codec); + reservedName_.WriteTo(ref output, _repeated_reservedName_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -3355,6 +3603,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasStart) { output.WriteRawTag(8); output.WriteInt32(Start); @@ -3366,7 +3617,25 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasStart) { + output.WriteRawTag(8); + output.WriteInt32(Start); + } + if (HasEnd) { + output.WriteRawTag(16); + output.WriteInt32(End); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -3591,6 +3860,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasName) { output.WriteRawTag(10); output.WriteString(Name); @@ -3606,7 +3878,29 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasName) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (HasNumber) { + output.WriteRawTag(16); + output.WriteInt32(Number); + } + if (options_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Options); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -3833,6 +4127,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasName) { output.WriteRawTag(10); output.WriteString(Name); @@ -3845,7 +4142,26 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasName) { + output.WriteRawTag(10); + output.WriteString(Name); + } + method_.WriteTo(ref output, _repeated_method_codec); + if (options_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Options); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -4173,6 +4489,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasName) { output.WriteRawTag(10); output.WriteString(Name); @@ -4200,8 +4519,42 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasName) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (HasInputType) { + output.WriteRawTag(18); + output.WriteString(InputType); + } + if (HasOutputType) { + output.WriteRawTag(26); + output.WriteString(OutputType); + } + if (options_ != null) { + output.WriteRawTag(34); + output.WriteMessage(Options); + } + if (HasClientStreaming) { + output.WriteRawTag(40); + output.WriteBool(ClientStreaming); + } + if (HasServerStreaming) { + output.WriteRawTag(48); + output.WriteBool(ServerStreaming); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -5067,6 +5420,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasJavaPackage) { output.WriteRawTag(10); output.WriteString(JavaPackage); @@ -5154,7 +5510,101 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasJavaPackage) { + output.WriteRawTag(10); + output.WriteString(JavaPackage); + } + if (HasJavaOuterClassname) { + output.WriteRawTag(66); + output.WriteString(JavaOuterClassname); + } + if (HasOptimizeFor) { + output.WriteRawTag(72); + output.WriteEnum((int) OptimizeFor); + } + if (HasJavaMultipleFiles) { + output.WriteRawTag(80); + output.WriteBool(JavaMultipleFiles); + } + if (HasGoPackage) { + output.WriteRawTag(90); + output.WriteString(GoPackage); + } + if (HasCcGenericServices) { + output.WriteRawTag(128, 1); + output.WriteBool(CcGenericServices); + } + if (HasJavaGenericServices) { + output.WriteRawTag(136, 1); + output.WriteBool(JavaGenericServices); + } + if (HasPyGenericServices) { + output.WriteRawTag(144, 1); + output.WriteBool(PyGenericServices); + } + if (HasJavaGenerateEqualsAndHash) { + output.WriteRawTag(160, 1); + output.WriteBool(JavaGenerateEqualsAndHash); + } + if (HasDeprecated) { + output.WriteRawTag(184, 1); + output.WriteBool(Deprecated); + } + if (HasJavaStringCheckUtf8) { + output.WriteRawTag(216, 1); + output.WriteBool(JavaStringCheckUtf8); + } + if (HasCcEnableArenas) { + output.WriteRawTag(248, 1); + output.WriteBool(CcEnableArenas); + } + if (HasObjcClassPrefix) { + output.WriteRawTag(162, 2); + output.WriteString(ObjcClassPrefix); + } + if (HasCsharpNamespace) { + output.WriteRawTag(170, 2); + output.WriteString(CsharpNamespace); + } + if (HasSwiftPrefix) { + output.WriteRawTag(186, 2); + output.WriteString(SwiftPrefix); + } + if (HasPhpClassPrefix) { + output.WriteRawTag(194, 2); + output.WriteString(PhpClassPrefix); + } + if (HasPhpNamespace) { + output.WriteRawTag(202, 2); + output.WriteString(PhpNamespace); + } + if (HasPhpGenericServices) { + output.WriteRawTag(208, 2); + output.WriteBool(PhpGenericServices); + } + if (HasPhpMetadataNamespace) { + output.WriteRawTag(226, 2); + output.WriteString(PhpMetadataNamespace); + } + if (HasRubyPackage) { + output.WriteRawTag(234, 2); + output.WriteString(RubyPackage); + } + uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -5793,21 +6243,53 @@ namespace Google.Protobuf.Reflection { if (HasMapEntry) hash ^= MapEntry.GetHashCode(); hash ^= uninterpretedOption_.GetHashCode(); if (_extensions != null) { - hash ^= _extensions.GetHashCode(); + hash ^= _extensions.GetHashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasMessageSetWireFormat) { + output.WriteRawTag(8); + output.WriteBool(MessageSetWireFormat); + } + if (HasNoStandardDescriptorAccessor) { + output.WriteRawTag(16); + output.WriteBool(NoStandardDescriptorAccessor); + } + if (HasDeprecated) { + output.WriteRawTag(24); + output.WriteBool(Deprecated); + } + if (HasMapEntry) { + output.WriteRawTag(56); + output.WriteBool(MapEntry); + } + uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(output); } if (_unknownFields != null) { - hash ^= _unknownFields.GetHashCode(); + _unknownFields.WriteTo(output); } - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { if (HasMessageSetWireFormat) { output.WriteRawTag(8); output.WriteBool(MessageSetWireFormat); @@ -5824,14 +6306,15 @@ namespace Google.Protobuf.Reflection { output.WriteRawTag(56); output.WriteBool(MapEntry); } - uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec); + uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec); if (_extensions != null) { - _extensions.WriteTo(output); + _extensions.WriteTo(ref output); } if (_unknownFields != null) { - _unknownFields.WriteTo(output); + _unknownFields.WriteTo(ref output); } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -6300,6 +6783,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasCtype) { output.WriteRawTag(8); output.WriteEnum((int) Ctype); @@ -6331,7 +6817,45 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasCtype) { + output.WriteRawTag(8); + output.WriteEnum((int) Ctype); + } + if (HasPacked) { + output.WriteRawTag(16); + output.WriteBool(Packed); + } + if (HasDeprecated) { + output.WriteRawTag(24); + output.WriteBool(Deprecated); + } + if (HasLazy) { + output.WriteRawTag(40); + output.WriteBool(Lazy); + } + if (HasJstype) { + output.WriteRawTag(48); + output.WriteEnum((int) Jstype); + } + if (HasWeak) { + output.WriteRawTag(80); + output.WriteBool(Weak); + } + uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -6631,6 +7155,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec); if (_extensions != null) { _extensions.WriteTo(output); @@ -6638,7 +7165,21 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -6889,6 +7430,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasAllowAlias) { output.WriteRawTag(16); output.WriteBool(AllowAlias); @@ -6904,7 +7448,29 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasAllowAlias) { + output.WriteRawTag(16); + output.WriteBool(AllowAlias); + } + if (HasDeprecated) { + output.WriteRawTag(24); + output.WriteBool(Deprecated); + } + uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -7152,6 +7718,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasDeprecated) { output.WriteRawTag(8); output.WriteBool(Deprecated); @@ -7163,7 +7732,25 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasDeprecated) { + output.WriteRawTag(8); + output.WriteBool(Deprecated); + } + uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -7397,6 +7984,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasDeprecated) { output.WriteRawTag(136, 2); output.WriteBool(Deprecated); @@ -7408,7 +7998,25 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasDeprecated) { + output.WriteRawTag(136, 2); + output.WriteBool(Deprecated); + } + uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -7669,6 +8277,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasDeprecated) { output.WriteRawTag(136, 2); output.WriteBool(Deprecated); @@ -7684,7 +8295,29 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasDeprecated) { + output.WriteRawTag(136, 2); + output.WriteBool(Deprecated); + } + if (HasIdempotencyLevel) { + output.WriteRawTag(144, 2); + output.WriteEnum((int) IdempotencyLevel); + } + uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec); + if (_extensions != null) { + _extensions.WriteTo(ref output); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -8082,6 +8715,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else name_.WriteTo(output, _repeated_name_codec); if (HasIdentifierValue) { output.WriteRawTag(26); @@ -8110,7 +8746,42 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + name_.WriteTo(ref output, _repeated_name_codec); + if (HasIdentifierValue) { + output.WriteRawTag(26); + output.WriteString(IdentifierValue); + } + if (HasPositiveIntValue) { + output.WriteRawTag(32); + output.WriteUInt64(PositiveIntValue); + } + if (HasNegativeIntValue) { + output.WriteRawTag(40); + output.WriteInt64(NegativeIntValue); + } + if (HasDoubleValue) { + output.WriteRawTag(49); + output.WriteDouble(DoubleValue); + } + if (HasStringValue) { + output.WriteRawTag(58); + output.WriteBytes(StringValue); + } + if (HasAggregateValue) { + output.WriteRawTag(66); + output.WriteString(AggregateValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -8388,6 +9059,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (HasNamePart_) { output.WriteRawTag(10); output.WriteString(NamePart_); @@ -8399,7 +9073,25 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasNamePart_) { + output.WriteRawTag(10); + output.WriteString(NamePart_); + } + if (HasIsExtension) { + output.WriteRawTag(16); + output.WriteBool(IsExtension); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -8614,11 +9306,25 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else location_.WriteTo(output, _repeated_location_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + location_.WriteTo(ref output, _repeated_location_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -8922,6 +9628,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else path_.WriteTo(output, _repeated_path_codec); span_.WriteTo(output, _repeated_span_codec); if (HasLeadingComments) { @@ -8936,7 +9645,28 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + path_.WriteTo(ref output, _repeated_path_codec); + span_.WriteTo(ref output, _repeated_span_codec); + if (HasLeadingComments) { + output.WriteRawTag(26); + output.WriteString(LeadingComments); + } + if (HasTrailingComments) { + output.WriteRawTag(34); + output.WriteString(TrailingComments); + } + leadingDetachedComments_.WriteTo(ref output, _repeated_leadingDetachedComments_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -9145,11 +9875,25 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else annotation_.WriteTo(output, _repeated_annotation_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + annotation_.WriteTo(ref output, _repeated_annotation_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -9392,6 +10136,9 @@ namespace Google.Protobuf.Reflection { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else path_.WriteTo(output, _repeated_path_codec); if (HasSourceFile) { output.WriteRawTag(18); @@ -9408,7 +10155,30 @@ namespace Google.Protobuf.Reflection { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + path_.WriteTo(ref output, _repeated_path_codec); + if (HasSourceFile) { + output.WriteRawTag(18); + output.WriteString(SourceFile); + } + if (HasBegin) { + output.WriteRawTag(24); + output.WriteInt32(Begin); + } + if (HasEnd) { + output.WriteRawTag(32); + output.WriteInt32(End); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { diff --git a/csharp/src/Google.Protobuf/UnknownField.cs b/csharp/src/Google.Protobuf/UnknownField.cs index e3ce0e86ef..63d89604a2 100644 --- a/csharp/src/Google.Protobuf/UnknownField.cs +++ b/csharp/src/Google.Protobuf/UnknownField.cs @@ -101,8 +101,8 @@ namespace Google.Protobuf /// /// /// The unknown field number. - /// The CodedOutputStream to write to. - internal void WriteTo(int fieldNumber, CodedOutputStream output) + /// The write context to write to. + internal void WriteTo(int fieldNumber, ref WriteContext output) { if (varintList != null) { @@ -141,7 +141,7 @@ namespace Google.Protobuf foreach (UnknownFieldSet value in groupList) { output.WriteTag(fieldNumber, WireFormat.WireType.StartGroup); - value.WriteTo(output); + value.WriteTo(ref output); output.WriteTag(fieldNumber, WireFormat.WireType.EndGroup); } } diff --git a/csharp/src/Google.Protobuf/UnknownFieldSet.cs b/csharp/src/Google.Protobuf/UnknownFieldSet.cs index 9ebe704065..9888dd1c3d 100644 --- a/csharp/src/Google.Protobuf/UnknownFieldSet.cs +++ b/csharp/src/Google.Protobuf/UnknownFieldSet.cs @@ -71,10 +71,27 @@ namespace Google.Protobuf /// Serializes the set and writes it to . /// public void WriteTo(CodedOutputStream output) + { + WriteContext.Initialize(output, out WriteContext ctx); + try + { + WriteTo(ref ctx); + } + finally + { + ctx.CopyStateTo(output); + } + } + + /// + /// Serializes the set and writes it to . + /// + [SecuritySafeCritical] + public void WriteTo(ref WriteContext ctx) { foreach (KeyValuePair entry in fields) { - entry.Value.WriteTo(entry.Key, output); + entry.Value.WriteTo(entry.Key, ref ctx); } } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs index 18520470d8..60ae03da94 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs @@ -78,10 +78,13 @@ namespace Google.Protobuf.WellKnownTypes { /// Example 4: Pack and unpack a message in Go /// /// foo := &pb.Foo{...} - /// any, err := ptypes.MarshalAny(foo) + /// any, err := anypb.New(foo) + /// if err != nil { + /// ... + /// } /// ... /// foo := &pb.Foo{} - /// if err := ptypes.UnmarshalAny(any, foo); err != nil { + /// if err := any.UnmarshalTo(foo); err != nil { /// ... /// } /// @@ -248,6 +251,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (TypeUrl.Length != 0) { output.WriteRawTag(10); output.WriteString(TypeUrl); @@ -259,7 +265,25 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (TypeUrl.Length != 0) { + output.WriteRawTag(10); + output.WriteString(TypeUrl); + } + if (Value.Length != 0) { + output.WriteRawTag(18); + output.WriteBytes(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs index 4e9cf11c3c..50d79bf8e9 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs @@ -269,6 +269,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); @@ -291,8 +294,37 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + methods_.WriteTo(ref output, _repeated_methods_codec); + options_.WriteTo(ref output, _repeated_options_codec); + if (Version.Length != 0) { + output.WriteRawTag(34); + output.WriteString(Version); + } + if (sourceContext_ != null) { + output.WriteRawTag(42); + output.WriteMessage(SourceContext); + } + mixins_.WriteTo(ref output, _repeated_mixins_codec); + if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) { + output.WriteRawTag(56); + output.WriteEnum((int) Syntax); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -627,6 +659,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); @@ -655,7 +690,42 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (RequestTypeUrl.Length != 0) { + output.WriteRawTag(18); + output.WriteString(RequestTypeUrl); + } + if (RequestStreaming != false) { + output.WriteRawTag(24); + output.WriteBool(RequestStreaming); + } + if (ResponseTypeUrl.Length != 0) { + output.WriteRawTag(34); + output.WriteString(ResponseTypeUrl); + } + if (ResponseStreaming != false) { + output.WriteRawTag(40); + output.WriteBool(ResponseStreaming); + } + options_.WriteTo(ref output, _repeated_options_codec); + if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) { + output.WriteRawTag(56); + output.WriteEnum((int) Syntax); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -984,6 +1054,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); @@ -995,8 +1068,26 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (Root.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Root); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs index e686655697..2a653a3754 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs @@ -210,6 +210,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Seconds != 0L) { output.WriteRawTag(8); output.WriteInt64(Seconds); @@ -221,7 +224,25 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Seconds != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Seconds); + } + if (Nanos != 0) { + output.WriteRawTag(16); + output.WriteInt32(Nanos); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs index 5e2d5a10df..e2e35182fd 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs @@ -119,10 +119,23 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs index c92be3c73d..d5da31441e 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs @@ -324,11 +324,25 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else paths_.WriteTo(output, _repeated_paths_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + paths_.WriteTo(ref output, _repeated_paths_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs b/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs index 7d46be1d93..5fe9b89536 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs @@ -131,6 +131,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (FileName.Length != 0) { output.WriteRawTag(10); output.WriteString(FileName); @@ -138,7 +141,21 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (FileName.Length != 0) { + output.WriteRawTag(10); + output.WriteString(FileName); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs index c7ca9270ab..0bbb1fcdf9 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs @@ -162,11 +162,25 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else fields_.WriteTo(output, _map_fields_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + fields_.WriteTo(ref output, _map_fields_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -446,6 +460,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (kindCase_ == KindOneofCase.NullValue) { output.WriteRawTag(8); output.WriteEnum((int) NullValue); @@ -473,7 +490,41 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (kindCase_ == KindOneofCase.NullValue) { + output.WriteRawTag(8); + output.WriteEnum((int) NullValue); + } + if (kindCase_ == KindOneofCase.NumberValue) { + output.WriteRawTag(17); + output.WriteDouble(NumberValue); + } + if (kindCase_ == KindOneofCase.StringValue) { + output.WriteRawTag(26); + output.WriteString(StringValue); + } + if (kindCase_ == KindOneofCase.BoolValue) { + output.WriteRawTag(32); + output.WriteBool(BoolValue); + } + if (kindCase_ == KindOneofCase.StructValue) { + output.WriteRawTag(42); + output.WriteMessage(StructValue); + } + if (kindCase_ == KindOneofCase.ListValue) { + output.WriteRawTag(50); + output.WriteMessage(ListValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -729,12 +780,26 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else values_.WriteTo(output, _repeated_values_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + values_.WriteTo(ref output, _repeated_values_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs index 849162f048..c75ef0f9a1 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs @@ -231,6 +231,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Seconds != 0L) { output.WriteRawTag(8); output.WriteInt64(Seconds); @@ -242,7 +245,25 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Seconds != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Seconds); + } + if (Nanos != 0) { + output.WriteRawTag(16); + output.WriteInt32(Nanos); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs index 8e92707476..f5dfdb7e3e 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs @@ -262,6 +262,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); @@ -280,7 +283,32 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + fields_.WriteTo(ref output, _repeated_fields_codec); + oneofs_.WriteTo(ref output, _repeated_oneofs_codec); + options_.WriteTo(ref output, _repeated_options_codec); + if (sourceContext_ != null) { + output.WriteRawTag(42); + output.WriteMessage(SourceContext); + } + if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) { + output.WriteRawTag(48); + output.WriteEnum((int) Syntax); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -655,6 +683,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Kind != global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TypeUnknown) { output.WriteRawTag(8); output.WriteEnum((int) Kind); @@ -695,7 +726,54 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Kind != global::Google.Protobuf.WellKnownTypes.Field.Types.Kind.TypeUnknown) { + output.WriteRawTag(8); + output.WriteEnum((int) Kind); + } + if (Cardinality != global::Google.Protobuf.WellKnownTypes.Field.Types.Cardinality.Unknown) { + output.WriteRawTag(16); + output.WriteEnum((int) Cardinality); + } + if (Number != 0) { + output.WriteRawTag(24); + output.WriteInt32(Number); + } + if (Name.Length != 0) { + output.WriteRawTag(34); + output.WriteString(Name); + } + if (TypeUrl.Length != 0) { + output.WriteRawTag(50); + output.WriteString(TypeUrl); + } + if (OneofIndex != 0) { + output.WriteRawTag(56); + output.WriteInt32(OneofIndex); + } + if (Packed != false) { + output.WriteRawTag(64); + output.WriteBool(Packed); + } + options_.WriteTo(ref output, _repeated_options_codec); + if (JsonName.Length != 0) { + output.WriteRawTag(82); + output.WriteString(JsonName); + } + if (DefaultValue.Length != 0) { + output.WriteRawTag(90); + output.WriteString(DefaultValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1148,6 +1226,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); @@ -1165,7 +1246,31 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + enumvalue_.WriteTo(ref output, _repeated_enumvalue_codec); + options_.WriteTo(ref output, _repeated_options_codec); + if (sourceContext_ != null) { + output.WriteRawTag(34); + output.WriteMessage(SourceContext); + } + if (Syntax != global::Google.Protobuf.WellKnownTypes.Syntax.Proto2) { + output.WriteRawTag(40); + output.WriteEnum((int) Syntax); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1409,6 +1514,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); @@ -1421,8 +1529,27 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (Number != 0) { + output.WriteRawTag(16); + output.WriteInt32(Number); + } + options_.WriteTo(ref output, _repeated_options_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -1623,6 +1750,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Name.Length != 0) { output.WriteRawTag(10); output.WriteString(Name); @@ -1634,8 +1764,26 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (value_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs index 1ccbc2a9c8..01d31216e8 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs @@ -144,6 +144,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Value != 0D) { output.WriteRawTag(9); output.WriteDouble(Value); @@ -151,7 +154,21 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value != 0D) { + output.WriteRawTag(9); + output.WriteDouble(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -307,6 +324,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Value != 0F) { output.WriteRawTag(13); output.WriteFloat(Value); @@ -314,7 +334,21 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value != 0F) { + output.WriteRawTag(13); + output.WriteFloat(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -470,6 +504,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Value != 0L) { output.WriteRawTag(8); output.WriteInt64(Value); @@ -477,8 +514,22 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -633,6 +684,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Value != 0UL) { output.WriteRawTag(8); output.WriteUInt64(Value); @@ -640,8 +694,22 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value != 0UL) { + output.WriteRawTag(8); + output.WriteUInt64(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -796,6 +864,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Value != 0) { output.WriteRawTag(8); output.WriteInt32(Value); @@ -803,7 +874,21 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value != 0) { + output.WriteRawTag(8); + output.WriteInt32(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -959,6 +1044,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Value != 0) { output.WriteRawTag(8); output.WriteUInt32(Value); @@ -966,7 +1054,21 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value != 0) { + output.WriteRawTag(8); + output.WriteUInt32(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } } + #endif [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { @@ -1122,6 +1224,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Value != false) { output.WriteRawTag(8); output.WriteBool(Value); @@ -1129,8 +1234,22 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value != false) { + output.WriteRawTag(8); + output.WriteBool(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -1285,6 +1404,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Value.Length != 0) { output.WriteRawTag(10); output.WriteString(Value); @@ -1292,8 +1414,22 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; @@ -1448,6 +1584,9 @@ namespace Google.Protobuf.WellKnownTypes { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else if (Value.Length != 0) { output.WriteRawTag(10); output.WriteBytes(Value); @@ -1455,8 +1594,22 @@ namespace Google.Protobuf.WellKnownTypes { if (_unknownFields != null) { _unknownFields.WriteTo(output); } + #endif } + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value.Length != 0) { + output.WriteRawTag(10); + output.WriteBytes(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() { int size = 0; diff --git a/csharp/src/Google.Protobuf/WriteBufferHelper.cs b/csharp/src/Google.Protobuf/WriteBufferHelper.cs new file mode 100644 index 0000000000..f2a59bc56f --- /dev/null +++ b/csharp/src/Google.Protobuf/WriteBufferHelper.cs @@ -0,0 +1,166 @@ +#region Copyright notice and license +// 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. +#endregion + +using System; +using System.Buffers; +using System.IO; +using System.Runtime.CompilerServices; +using System.Security; + +namespace Google.Protobuf +{ + /// + /// Abstraction for writing to a steam / IBufferWriter + /// + [SecuritySafeCritical] + internal struct WriteBufferHelper + { + private IBufferWriter bufferWriter; + private CodedOutputStream codedOutputStream; + + public CodedOutputStream CodedOutputStream => codedOutputStream; + + /// + /// Initialize an instance with a coded output stream. + /// This approach is faster than using a constructor because the instance to initialize is passed by reference + /// and we can write directly into it without copying. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Initialize(CodedOutputStream codedOutputStream, out WriteBufferHelper instance) + { + instance.bufferWriter = null; + instance.codedOutputStream = codedOutputStream; + } + + /// + /// Initialize an instance with a buffer writer. + /// This approach is faster than using a constructor because the instance to initialize is passed by reference + /// and we can write directly into it without copying. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Initialize(IBufferWriter bufferWriter, out WriteBufferHelper instance, out Span buffer) + { + instance.bufferWriter = bufferWriter; + instance.codedOutputStream = null; + buffer = default; // TODO: initialize the initial buffer so that the first write is not via slowpath. + } + + /// + /// Initialize an instance with a buffer represented by a single span (i.e. buffer cannot be refreshed) + /// This approach is faster than using a constructor because the instance to initialize is passed by reference + /// and we can write directly into it without copying. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void InitializeNonRefreshable(out WriteBufferHelper instance) + { + instance.bufferWriter = null; + instance.codedOutputStream = null; + } + + /// + /// Verifies that SpaceLeft returns zero. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CheckNoSpaceLeft(ref WriterInternalState state) + { + if (GetSpaceLeft(ref state) != 0) + { + throw new InvalidOperationException("Did not write as much data as expected."); + } + } + + /// + /// If writing to a flat array, returns the space left in the array. Otherwise, + /// throws an InvalidOperationException. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int GetSpaceLeft(ref WriterInternalState state) + { + if (state.writeBufferHelper.codedOutputStream?.InternalOutputStream == null && state.writeBufferHelper.bufferWriter == null) + { + return state.limit - state.position; + } + else + { + throw new InvalidOperationException( + "SpaceLeft can only be called on CodedOutputStreams that are " + + "writing to a flat array or when writing to a single span."); + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static void RefreshBuffer(ref Span buffer, ref WriterInternalState state) + { + if (state.writeBufferHelper.codedOutputStream?.InternalOutputStream != null) + { + // because we're using coded output stream, we know that "buffer" and codedOutputStream.InternalBuffer are identical. + state.writeBufferHelper.codedOutputStream.InternalOutputStream.Write(state.writeBufferHelper.codedOutputStream.InternalBuffer, 0, state.position); + // reset position, limit stays the same because we are reusing the codedOutputStream's internal buffer. + state.position = 0; + } + else if (state.writeBufferHelper.bufferWriter != null) + { + // commit the bytes and get a new buffer to write to. + state.writeBufferHelper.bufferWriter.Advance(state.position); + state.position = 0; + buffer = state.writeBufferHelper.bufferWriter.GetSpan(); + state.limit = buffer.Length; + } + else + { + // We're writing to a single buffer. + throw new CodedOutputStream.OutOfSpaceException(); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Flush(ref Span buffer, ref WriterInternalState state) + { + if (state.writeBufferHelper.codedOutputStream?.InternalOutputStream != null) + { + // because we're using coded output stream, we know that "buffer" and codedOutputStream.InternalBuffer are identical. + state.writeBufferHelper.codedOutputStream.InternalOutputStream.Write(state.writeBufferHelper.codedOutputStream.InternalBuffer, 0, state.position); + state.position = 0; + } + else if (state.writeBufferHelper.bufferWriter != null) + { + // calling Advance invalidates the current buffer and we must not continue writing to it, + // so we set the current buffer to point to an empty Span. If any subsequent writes happen, + // the first subsequent write will trigger refresing of the buffer. + state.writeBufferHelper.bufferWriter.Advance(state.position); + state.position = 0; + state.limit = 0; + buffer = default; // invalidate the current buffer + } + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/WriteContext.cs b/csharp/src/Google.Protobuf/WriteContext.cs new file mode 100644 index 0000000000..e822e1d6da --- /dev/null +++ b/csharp/src/Google.Protobuf/WriteContext.cs @@ -0,0 +1,371 @@ +#region Copyright notice and license +// 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. +#endregion + +using System; +using System.Buffers; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; +using Google.Protobuf.Collections; + +namespace Google.Protobuf +{ + /// + /// An opaque struct that represents the current serialization state and is passed along + /// as the serialization proceeds. + /// All the public methods are intended to be invoked only by the generated code, + /// users should never invoke them directly. + /// + [SecuritySafeCritical] + public ref struct WriteContext + { + internal Span buffer; + internal WriterInternalState state; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void Initialize(ref Span buffer, ref WriterInternalState state, out WriteContext ctx) + { + ctx.buffer = buffer; + ctx.state = state; + } + + /// + /// Creates a WriteContext instance from CodedOutputStream. + /// WARNING: internally this copies the CodedOutputStream's state, so after done with the WriteContext, + /// the CodedOutputStream's state needs to be updated. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void Initialize(CodedOutputStream output, out WriteContext ctx) + { + ctx.buffer = new Span(output.InternalBuffer); + // ideally we would use a reference to the original state, but that doesn't seem possible + // so we just copy the struct that holds the state. We will need to later store the state back + // into CodedOutputStream if we want to keep it usable. + ctx.state = output.InternalState; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void Initialize(IBufferWriter output, out WriteContext ctx) + { + ctx.buffer = default; + ctx.state = default; + WriteBufferHelper.Initialize(output, out ctx.state.writeBufferHelper, out ctx.buffer); + ctx.state.limit = ctx.buffer.Length; + ctx.state.position = 0; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void Initialize(ref Span buffer, out WriteContext ctx) + { + ctx.buffer = buffer; + ctx.state = default; + ctx.state.limit = ctx.buffer.Length; + ctx.state.position = 0; + WriteBufferHelper.InitializeNonRefreshable(out ctx.state.writeBufferHelper); + } + + /// + /// Writes a double field value, without a tag. + /// + /// The value to write + public void WriteDouble(double value) + { + WritingPrimitives.WriteDouble(ref buffer, ref state, value); + } + + /// + /// Writes a float field value, without a tag. + /// + /// The value to write + public void WriteFloat(float value) + { + WritingPrimitives.WriteFloat(ref buffer, ref state, value); + } + + /// + /// Writes a uint64 field value, without a tag. + /// + /// The value to write + public void WriteUInt64(ulong value) + { + WritingPrimitives.WriteUInt64(ref buffer, ref state, value); + } + + /// + /// Writes an int64 field value, without a tag. + /// + /// The value to write + public void WriteInt64(long value) + { + WritingPrimitives.WriteInt64(ref buffer, ref state, value); + } + + /// + /// Writes an int32 field value, without a tag. + /// + /// The value to write + public void WriteInt32(int value) + { + WritingPrimitives.WriteInt32(ref buffer, ref state, value); + } + + /// + /// Writes a fixed64 field value, without a tag. + /// + /// The value to write + public void WriteFixed64(ulong value) + { + WritingPrimitives.WriteFixed64(ref buffer, ref state, value); + } + + /// + /// Writes a fixed32 field value, without a tag. + /// + /// The value to write + public void WriteFixed32(uint value) + { + WritingPrimitives.WriteFixed32(ref buffer, ref state, value); + } + + /// + /// Writes a bool field value, without a tag. + /// + /// The value to write + public void WriteBool(bool value) + { + WritingPrimitives.WriteBool(ref buffer, ref state, value); + } + + /// + /// Writes a string field value, without a tag. + /// The data is length-prefixed. + /// + /// The value to write + public void WriteString(string value) + { + WritingPrimitives.WriteString(ref buffer, ref state, value); + } + + /// + /// Writes a message, without a tag. + /// The data is length-prefixed. + /// + /// The value to write + public void WriteMessage(IMessage value) + { + WritingPrimitivesMessages.WriteMessage(ref this, value); + } + + /// + /// Writes a group, without a tag, to the stream. + /// + /// The value to write + public void WriteGroup(IMessage value) + { + WritingPrimitivesMessages.WriteGroup(ref this, value); + } + + /// + /// Write a byte string, without a tag, to the stream. + /// The data is length-prefixed. + /// + /// The value to write + public void WriteBytes(ByteString value) + { + WritingPrimitives.WriteBytes(ref buffer, ref state, value); + } + + /// + /// Writes a uint32 value, without a tag. + /// + /// The value to write + public void WriteUInt32(uint value) + { + WritingPrimitives.WriteUInt32(ref buffer, ref state, value); + } + + /// + /// Writes an enum value, without a tag. + /// + /// The value to write + public void WriteEnum(int value) + { + WritingPrimitives.WriteEnum(ref buffer, ref state, value); + } + + /// + /// Writes an sfixed32 value, without a tag. + /// + /// The value to write. + public void WriteSFixed32(int value) + { + WritingPrimitives.WriteSFixed32(ref buffer, ref state, value); + } + + /// + /// Writes an sfixed64 value, without a tag. + /// + /// The value to write + public void WriteSFixed64(long value) + { + WritingPrimitives.WriteSFixed64(ref buffer, ref state, value); + } + + /// + /// Writes an sint32 value, without a tag. + /// + /// The value to write + public void WriteSInt32(int value) + { + WritingPrimitives.WriteSInt32(ref buffer, ref state, value); + } + + /// + /// Writes an sint64 value, without a tag. + /// + /// The value to write + public void WriteSInt64(long value) + { + WritingPrimitives.WriteSInt64(ref buffer, ref state, value); + } + + /// + /// Writes a length (in bytes) for length-delimited data. + /// + /// + /// This method simply writes a rawint, but exists for clarity in calling code. + /// + /// Length value, in bytes. + public void WriteLength(int length) + { + WritingPrimitives.WriteLength(ref buffer, ref state, length); + } + + /// + /// Encodes and writes a tag. + /// + /// The number of the field to write the tag for + /// The wire format type of the tag to write + public void WriteTag(int fieldNumber, WireFormat.WireType type) + { + WritingPrimitives.WriteTag(ref buffer, ref state, fieldNumber, type); + } + + /// + /// Writes an already-encoded tag. + /// + /// The encoded tag + public void WriteTag(uint tag) + { + WritingPrimitives.WriteTag(ref buffer, ref state, tag); + } + + /// + /// Writes the given single-byte tag. + /// + /// The encoded tag + public void WriteRawTag(byte b1) + { + WritingPrimitives.WriteRawTag(ref buffer, ref state, b1); + } + + /// + /// Writes the given two-byte tag. + /// + /// The first byte of the encoded tag + /// The second byte of the encoded tag + public void WriteRawTag(byte b1, byte b2) + { + WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2); + } + + /// + /// Writes the given three-byte tag. + /// + /// The first byte of the encoded tag + /// The second byte of the encoded tag + /// The third byte of the encoded tag + public void WriteRawTag(byte b1, byte b2, byte b3) + { + WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2, b3); + } + + /// + /// Writes the given four-byte tag. + /// + /// The first byte of the encoded tag + /// The second byte of the encoded tag + /// The third byte of the encoded tag + /// The fourth byte of the encoded tag + public void WriteRawTag(byte b1, byte b2, byte b3, byte b4) + { + WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2, b3, b4); + } + + /// + /// Writes the given five-byte tag. + /// + /// The first byte of the encoded tag + /// The second byte of the encoded tag + /// The third byte of the encoded tag + /// The fourth byte of the encoded tag + /// The fifth byte of the encoded tag + public void WriteRawTag(byte b1, byte b2, byte b3, byte b4, byte b5) + { + WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2, b3, b4, b5); + } + + internal void Flush() + { + WriteBufferHelper.Flush(ref buffer, ref state); + } + + internal void CheckNoSpaceLeft() + { + WriteBufferHelper.CheckNoSpaceLeft(ref state); + } + + internal void CopyStateTo(CodedOutputStream output) + { + output.InternalState = state; + } + + internal void LoadStateFrom(CodedOutputStream output) + { + state = output.InternalState; + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/WriterInternalState.cs b/csharp/src/Google.Protobuf/WriterInternalState.cs new file mode 100644 index 0000000000..a779305bb7 --- /dev/null +++ b/csharp/src/Google.Protobuf/WriterInternalState.cs @@ -0,0 +1,62 @@ +#region Copyright notice and license +// 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. +#endregion + +using System; +using System.Buffers; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; +using Google.Protobuf.Collections; + +namespace Google.Protobuf +{ + + // warning: this is a mutable struct, so it needs to be only passed as a ref! + internal struct WriterInternalState + { + // NOTE: the Span representing the current buffer is kept separate so that this doesn't have to be a ref struct and so it can + // be included in CodedOutputStream's internal state + + internal int limit; // the size of the current buffer + internal int position; // position in the current buffer + + internal WriteBufferHelper writeBufferHelper; + + // If non-null, the top level parse method was started with given coded output stream as an argument + // which also means we can potentially fallback to calling WriteTo(CodedOutputStream cos) if needed. + internal CodedOutputStream CodedOutputStream => writeBufferHelper.CodedOutputStream; + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/WritingPrimitives.cs b/csharp/src/Google.Protobuf/WritingPrimitives.cs new file mode 100644 index 0000000000..846df73502 --- /dev/null +++ b/csharp/src/Google.Protobuf/WritingPrimitives.cs @@ -0,0 +1,628 @@ +#region Copyright notice and license +// 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. +#endregion + +using System; +using System.Buffers.Binary; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; + +namespace Google.Protobuf +{ + /// + /// Primitives for encoding protobuf wire format. + /// + [SecuritySafeCritical] + internal static class WritingPrimitives + { + // "Local" copy of Encoding.UTF8, for efficiency. (Yes, it makes a difference.) + internal static readonly Encoding Utf8Encoding = Encoding.UTF8; + + #region Writing of values (not including tags) + + /// + /// Writes a double field value, without a tag, to the stream. + /// + public static void WriteDouble(ref Span buffer, ref WriterInternalState state, double value) + { + WriteRawLittleEndian64(ref buffer, ref state, (ulong)BitConverter.DoubleToInt64Bits(value)); + } + + /// + /// Writes a float field value, without a tag, to the stream. + /// + public static unsafe void WriteFloat(ref Span buffer, ref WriterInternalState state, float value) + { + const int length = sizeof(float); + if (buffer.Length - state.position >= length) + { + // if there's enough space in the buffer, write the float directly into the buffer + var floatSpan = buffer.Slice(state.position, length); + Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(floatSpan), value); + + if (!BitConverter.IsLittleEndian) + { + floatSpan.Reverse(); + } + state.position += length; + } + else + { + WriteFloatSlowPath(ref buffer, ref state, value); + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static unsafe void WriteFloatSlowPath(ref Span buffer, ref WriterInternalState state, float value) + { + const int length = sizeof(float); + + // TODO(jtattermusch): deduplicate the code. Populating the span is the same as for the fastpath. + Span floatSpan = stackalloc byte[length]; + Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(floatSpan), value); + if (!BitConverter.IsLittleEndian) + { + floatSpan.Reverse(); + } + + WriteRawByte(ref buffer, ref state, floatSpan[0]); + WriteRawByte(ref buffer, ref state, floatSpan[1]); + WriteRawByte(ref buffer, ref state, floatSpan[2]); + WriteRawByte(ref buffer, ref state, floatSpan[3]); + } + + /// + /// Writes a uint64 field value, without a tag, to the stream. + /// + public static void WriteUInt64(ref Span buffer, ref WriterInternalState state, ulong value) + { + WriteRawVarint64(ref buffer, ref state, value); + } + + /// + /// Writes an int64 field value, without a tag, to the stream. + /// + public static void WriteInt64(ref Span buffer, ref WriterInternalState state, long value) + { + WriteRawVarint64(ref buffer, ref state, (ulong)value); + } + + /// + /// Writes an int32 field value, without a tag, to the stream. + /// + public static void WriteInt32(ref Span buffer, ref WriterInternalState state, int value) + { + if (value >= 0) + { + WriteRawVarint32(ref buffer, ref state, (uint)value); + } + else + { + // Must sign-extend. + WriteRawVarint64(ref buffer, ref state, (ulong)value); + } + } + + /// + /// Writes a fixed64 field value, without a tag, to the stream. + /// + public static void WriteFixed64(ref Span buffer, ref WriterInternalState state, ulong value) + { + WriteRawLittleEndian64(ref buffer, ref state, value); + } + + /// + /// Writes a fixed32 field value, without a tag, to the stream. + /// + public static void WriteFixed32(ref Span buffer, ref WriterInternalState state, uint value) + { + WriteRawLittleEndian32(ref buffer, ref state, value); + } + + /// + /// Writes a bool field value, without a tag, to the stream. + /// + public static void WriteBool(ref Span buffer, ref WriterInternalState state, bool value) + { + WriteRawByte(ref buffer, ref state, value ? (byte)1 : (byte)0); + } + + /// + /// Writes a string field value, without a tag, to the stream. + /// The data is length-prefixed. + /// + public static void WriteString(ref Span buffer, ref WriterInternalState state, string value) + { + // Optimise the case where we have enough space to write + // the string directly to the buffer, which should be common. + int length = Utf8Encoding.GetByteCount(value); + WriteLength(ref buffer, ref state, length); + if (buffer.Length - state.position >= length) + { + if (length == value.Length) // Must be all ASCII... + { + for (int i = 0; i < length; i++) + { + buffer[state.position + i] = (byte)value[i]; + } + state.position += length; + } + else + { +#if NETSTANDARD1_1 + // slowpath when Encoding.GetBytes(Char*, Int32, Byte*, Int32) is not available + byte[] bytes = Utf8Encoding.GetBytes(value); + WriteRawBytes(ref buffer, ref state, bytes); +#else + ReadOnlySpan source = value.AsSpan(); + int bytesUsed; + unsafe + { + fixed (char* sourceChars = &MemoryMarshal.GetReference(source)) + fixed (byte* destinationBytes = &MemoryMarshal.GetReference(buffer.Slice(state.position))) + { + bytesUsed = Utf8Encoding.GetBytes(sourceChars, source.Length, destinationBytes, buffer.Length); + } + } + state.position += bytesUsed; +#endif + } + } + else + { + // Opportunity for future optimization: + // Large strings that don't fit into the current buffer segment + // can probably be optimized by using Utf8Encoding.GetEncoder() + // but more benchmarks would need to be added as evidence. + byte[] bytes = Utf8Encoding.GetBytes(value); + WriteRawBytes(ref buffer, ref state, bytes); + } + } + + /// + /// Write a byte string, without a tag, to the stream. + /// The data is length-prefixed. + /// + public static void WriteBytes(ref Span buffer, ref WriterInternalState state, ByteString value) + { + WriteLength(ref buffer, ref state, value.Length); + WriteRawBytes(ref buffer, ref state, value.Span); + } + + /// + /// Writes a uint32 value, without a tag, to the stream. + /// + public static void WriteUInt32(ref Span buffer, ref WriterInternalState state, uint value) + { + WriteRawVarint32(ref buffer, ref state, value); + } + + /// + /// Writes an enum value, without a tag, to the stream. + /// + public static void WriteEnum(ref Span buffer, ref WriterInternalState state, int value) + { + WriteInt32(ref buffer, ref state, value); + } + + /// + /// Writes an sfixed32 value, without a tag, to the stream. + /// + public static void WriteSFixed32(ref Span buffer, ref WriterInternalState state, int value) + { + WriteRawLittleEndian32(ref buffer, ref state, (uint)value); + } + + /// + /// Writes an sfixed64 value, without a tag, to the stream. + /// + public static void WriteSFixed64(ref Span buffer, ref WriterInternalState state, long value) + { + WriteRawLittleEndian64(ref buffer, ref state, (ulong)value); + } + + /// + /// Writes an sint32 value, without a tag, to the stream. + /// + public static void WriteSInt32(ref Span buffer, ref WriterInternalState state, int value) + { + WriteRawVarint32(ref buffer, ref state, EncodeZigZag32(value)); + } + + /// + /// Writes an sint64 value, without a tag, to the stream. + /// + public static void WriteSInt64(ref Span buffer, ref WriterInternalState state, long value) + { + WriteRawVarint64(ref buffer, ref state, EncodeZigZag64(value)); + } + + /// + /// Writes a length (in bytes) for length-delimited data. + /// + /// + /// This method simply writes a rawint, but exists for clarity in calling code. + /// + public static void WriteLength(ref Span buffer, ref WriterInternalState state, int length) + { + WriteRawVarint32(ref buffer, ref state, (uint)length); + } + + #endregion + + #region Writing primitives + /// + /// Writes a 32 bit value as a varint. The fast route is taken when + /// there's enough buffer space left to whizz through without checking + /// for each byte; otherwise, we resort to calling WriteRawByte each time. + /// + public static void WriteRawVarint32(ref Span buffer, ref WriterInternalState state, uint value) + { + // Optimize for the common case of a single byte value + if (value < 128 && state.position < buffer.Length) + { + buffer[state.position++] = (byte)value; + return; + } + + // Fast path when capacity is available + while (state.position < buffer.Length) + { + if (value > 127) + { + buffer[state.position++] = (byte)((value & 0x7F) | 0x80); + value >>= 7; + } + else + { + buffer[state.position++] = (byte)value; + return; + } + } + + while (value > 127) + { + WriteRawByte(ref buffer, ref state, (byte)((value & 0x7F) | 0x80)); + value >>= 7; + } + + WriteRawByte(ref buffer, ref state, (byte)value); + } + + public static void WriteRawVarint64(ref Span buffer, ref WriterInternalState state, ulong value) + { + // Optimize for the common case of a single byte value + if (value < 128 && state.position < buffer.Length) + { + buffer[state.position++] = (byte)value; + return; + } + + // Fast path when capacity is available + while (state.position < buffer.Length) + { + if (value > 127) + { + buffer[state.position++] = (byte)((value & 0x7F) | 0x80); + value >>= 7; + } + else + { + buffer[state.position++] = (byte)value; + return; + } + } + + while (value > 127) + { + WriteRawByte(ref buffer, ref state, (byte)((value & 0x7F) | 0x80)); + value >>= 7; + } + + WriteRawByte(ref buffer, ref state, (byte)value); + } + + public static void WriteRawLittleEndian32(ref Span buffer, ref WriterInternalState state, uint value) + { + const int length = sizeof(uint); + if (state.position + length > buffer.Length) + { + WriteRawLittleEndian32SlowPath(ref buffer, ref state, value); + } + else + { + BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(state.position), value); + state.position += length; + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void WriteRawLittleEndian32SlowPath(ref Span buffer, ref WriterInternalState state, uint value) + { + WriteRawByte(ref buffer, ref state, (byte)value); + WriteRawByte(ref buffer, ref state, (byte)(value >> 8)); + WriteRawByte(ref buffer, ref state, (byte)(value >> 16)); + WriteRawByte(ref buffer, ref state, (byte)(value >> 24)); + } + + public static void WriteRawLittleEndian64(ref Span buffer, ref WriterInternalState state, ulong value) + { + const int length = sizeof(ulong); + if (state.position + length > buffer.Length) + { + WriteRawLittleEndian64SlowPath(ref buffer, ref state, value); + } + else + { + BinaryPrimitives.WriteUInt64LittleEndian(buffer.Slice(state.position), value); + state.position += length; + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static void WriteRawLittleEndian64SlowPath(ref Span buffer, ref WriterInternalState state, ulong value) + { + WriteRawByte(ref buffer, ref state, (byte)value); + WriteRawByte(ref buffer, ref state, (byte)(value >> 8)); + WriteRawByte(ref buffer, ref state, (byte)(value >> 16)); + WriteRawByte(ref buffer, ref state, (byte)(value >> 24)); + WriteRawByte(ref buffer, ref state, (byte)(value >> 32)); + WriteRawByte(ref buffer, ref state, (byte)(value >> 40)); + WriteRawByte(ref buffer, ref state, (byte)(value >> 48)); + WriteRawByte(ref buffer, ref state, (byte)(value >> 56)); + } + + private static void WriteRawByte(ref Span buffer, ref WriterInternalState state, byte value) + { + if (state.position == buffer.Length) + { + WriteBufferHelper.RefreshBuffer(ref buffer, ref state); + } + + buffer[state.position++] = value; + } + + /// + /// Writes out an array of bytes. + /// + public static void WriteRawBytes(ref Span buffer, ref WriterInternalState state, byte[] value) + { + WriteRawBytes(ref buffer, ref state, new ReadOnlySpan(value)); + } + + /// + /// Writes out part of an array of bytes. + /// + public static void WriteRawBytes(ref Span buffer, ref WriterInternalState state, byte[] value, int offset, int length) + { + WriteRawBytes(ref buffer, ref state, new ReadOnlySpan(value, offset, length)); + } + + /// + /// Writes out part of an array of bytes. + /// + public static void WriteRawBytes(ref Span buffer, ref WriterInternalState state, ReadOnlySpan value) + { + if (buffer.Length - state.position >= value.Length) + { + // We have room in the current buffer. + value.CopyTo(buffer.Slice(state.position, value.Length)); + state.position += value.Length; + } + else + { + // When writing to a CodedOutputStream backed by a Stream, we could avoid + // copying the data twice (first copying to the current buffer and + // and later writing from the current buffer to the underlying Stream) + // in some circumstances by writing the data directly to the underlying Stream. + // Current this is not being done to avoid specialcasing the code for + // CodedOutputStream vs IBufferWriter. + int bytesWritten = 0; + while (buffer.Length - state.position < value.Length - bytesWritten) + { + int length = buffer.Length - state.position; + value.Slice(bytesWritten, length).CopyTo(buffer.Slice(state.position, length)); + bytesWritten += length; + state.position += length; + WriteBufferHelper.RefreshBuffer(ref buffer, ref state); + } + + // copy the remaining data + int remainderLength = value.Length - bytesWritten; + value.Slice(bytesWritten, remainderLength).CopyTo(buffer.Slice(state.position, remainderLength)); + state.position += remainderLength; + } + } + #endregion + + #region Raw tag writing + /// + /// Encodes and writes a tag. + /// + public static void WriteTag(ref Span buffer, ref WriterInternalState state, int fieldNumber, WireFormat.WireType type) + { + WriteRawVarint32(ref buffer, ref state, WireFormat.MakeTag(fieldNumber, type)); + } + + /// + /// Writes an already-encoded tag. + /// + public static void WriteTag(ref Span buffer, ref WriterInternalState state, uint tag) + { + WriteRawVarint32(ref buffer, ref state, tag); + } + + /// + /// Writes the given single-byte tag directly to the stream. + /// + public static void WriteRawTag(ref Span buffer, ref WriterInternalState state, byte b1) + { + WriteRawByte(ref buffer, ref state, b1); + } + + /// + /// Writes the given two-byte tag directly to the stream. + /// + public static void WriteRawTag(ref Span buffer, ref WriterInternalState state, byte b1, byte b2) + { + if (state.position + 2 > buffer.Length) + { + WriteRawTagSlowPath(ref buffer, ref state, b1, b2); + } + else + { + buffer[state.position++] = b1; + buffer[state.position++] = b2; + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void WriteRawTagSlowPath(ref Span buffer, ref WriterInternalState state, byte b1, byte b2) + { + WriteRawByte(ref buffer, ref state, b1); + WriteRawByte(ref buffer, ref state, b2); + } + + /// + /// Writes the given three-byte tag directly to the stream. + /// + public static void WriteRawTag(ref Span buffer, ref WriterInternalState state, byte b1, byte b2, byte b3) + { + if (state.position + 3 > buffer.Length) + { + WriteRawTagSlowPath(ref buffer, ref state, b1, b2, b3); + } + else + { + buffer[state.position++] = b1; + buffer[state.position++] = b2; + buffer[state.position++] = b3; + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void WriteRawTagSlowPath(ref Span buffer, ref WriterInternalState state, byte b1, byte b2, byte b3) + { + WriteRawByte(ref buffer, ref state, b1); + WriteRawByte(ref buffer, ref state, b2); + WriteRawByte(ref buffer, ref state, b3); + } + + /// + /// Writes the given four-byte tag directly to the stream. + /// + public static void WriteRawTag(ref Span buffer, ref WriterInternalState state, byte b1, byte b2, byte b3, byte b4) + { + if (state.position + 4 > buffer.Length) + { + WriteRawTagSlowPath(ref buffer, ref state, b1, b2, b3, b4); + } + else + { + buffer[state.position++] = b1; + buffer[state.position++] = b2; + buffer[state.position++] = b3; + buffer[state.position++] = b4; + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + + private static void WriteRawTagSlowPath(ref Span buffer, ref WriterInternalState state, byte b1, byte b2, byte b3, byte b4) + { + WriteRawByte(ref buffer, ref state, b1); + WriteRawByte(ref buffer, ref state, b2); + WriteRawByte(ref buffer, ref state, b3); + WriteRawByte(ref buffer, ref state, b4); + } + + /// + /// Writes the given five-byte tag directly to the stream. + /// + public static void WriteRawTag(ref Span buffer, ref WriterInternalState state, byte b1, byte b2, byte b3, byte b4, byte b5) + { + if (state.position + 5 > buffer.Length) + { + WriteRawTagSlowPath(ref buffer, ref state, b1, b2, b3, b4, b5); + } + else + { + buffer[state.position++] = b1; + buffer[state.position++] = b2; + buffer[state.position++] = b3; + buffer[state.position++] = b4; + buffer[state.position++] = b5; + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void WriteRawTagSlowPath(ref Span buffer, ref WriterInternalState state, byte b1, byte b2, byte b3, byte b4, byte b5) + { + WriteRawByte(ref buffer, ref state, b1); + WriteRawByte(ref buffer, ref state, b2); + WriteRawByte(ref buffer, ref state, b3); + WriteRawByte(ref buffer, ref state, b4); + WriteRawByte(ref buffer, ref state, b5); + } + #endregion + + /// + /// Encode a 32-bit value with ZigZag encoding. + /// + /// + /// ZigZag encodes signed integers into values that can be efficiently + /// encoded with varint. (Otherwise, negative values must be + /// sign-extended to 64 bits to be varint encoded, thus always taking + /// 10 bytes on the wire.) + /// + public static uint EncodeZigZag32(int n) + { + // Note: the right-shift must be arithmetic + return (uint)((n << 1) ^ (n >> 31)); + } + + /// + /// Encode a 64-bit value with ZigZag encoding. + /// + /// + /// ZigZag encodes signed integers into values that can be efficiently + /// encoded with varint. (Otherwise, negative values must be + /// sign-extended to 64 bits to be varint encoded, thus always taking + /// 10 bytes on the wire.) + /// + public static ulong EncodeZigZag64(long n) + { + return (ulong)((n << 1) ^ (n >> 63)); + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/WritingPrimitivesMessages.cs b/csharp/src/Google.Protobuf/WritingPrimitivesMessages.cs new file mode 100644 index 0000000000..cd2d437915 --- /dev/null +++ b/csharp/src/Google.Protobuf/WritingPrimitivesMessages.cs @@ -0,0 +1,112 @@ +#region Copyright notice and license +// 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. +#endregion + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices.ComTypes; +using System.Security; + +namespace Google.Protobuf +{ + /// + /// Writing messages / groups. + /// + [SecuritySafeCritical] + internal static class WritingPrimitivesMessages + { + /// + /// Writes a message, without a tag. + /// The data is length-prefixed. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteMessage(ref WriteContext ctx, IMessage value) + { + WritingPrimitives.WriteLength(ref ctx.buffer, ref ctx.state, value.CalculateSize()); + WriteRawMessage(ref ctx, value); + } + + /// + /// Writes a group, without a tag. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteGroup(ref WriteContext ctx, IMessage value) + { + WriteRawMessage(ref ctx, value); + } + + /// + /// Writes a message, without a tag. + /// Message will be written without a length prefix. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteRawMessage(ref WriteContext ctx, IMessage message) + { + if (message is IBufferMessage bufferMessage) + { + bufferMessage.InternalWriteTo(ref ctx); + } + else + { + // If we reached here, it means we've ran into a nested message with older generated code + // which doesn't provide the InternalWriteTo method that takes a WriteContext. + // With a slight performance overhead, we can still serialize this message just fine, + // but we need to find the original CodedOutputStream instance that initiated this + // serialization process and make sure its internal state is up to date. + // Note that this performance overhead is not very high (basically copying contents of a struct) + // and it will only be incurred in case the application mixes older and newer generated code. + // Regenerating the code from .proto files will remove this overhead because it will + // generate the InternalWriteTo method we need. + + if (ctx.state.CodedOutputStream == null) + { + // This can only happen when the serialization started without providing a CodedOutputStream instance + // (e.g. WriteContext was created directly from a IBufferWriter). + // That also means that one of the new parsing APIs was used at the top level + // and in such case it is reasonable to require that all the nested message provide + // up-to-date generated code with WriteContext support (and fail otherwise). + throw new InvalidProtocolBufferException($"Message {message.GetType().Name} doesn't provide the generated method that enables WriteContext-based serialization. You might need to regenerate the generated protobuf code."); + } + + ctx.CopyStateTo(ctx.state.CodedOutputStream); + try + { + // fallback parse using the CodedOutputStream that started current serialization tree + message.WriteTo(ctx.state.CodedOutputStream); + } + finally + { + ctx.LoadStateFrom(ctx.state.CodedOutputStream); + } + } + } + } +} \ No newline at end of file diff --git a/docs/third_party.md b/docs/third_party.md index 257f9d5952..c1726a0f17 100644 --- a/docs/third_party.md +++ b/docs/third_party.md @@ -36,6 +36,7 @@ These are projects we know about implementing Protocol Buffers for other program * Delphi: http://fundementals.sourceforge.net/dl.html * Elixir: https://github.com/jeremyong/exprotoc * Elixir: https://github.com/tony612/protobuf-elixir +* Elixir: https://github.com/ahamez/protox * Elm: https://github.com/tiziano88/elm-protobuf * Erlang: https://github.com/tomas-abrahamsson/gpb * Erlang: http://piqi.org/ diff --git a/editors/protobuf-mode.el b/editors/protobuf-mode.el index f73d4b2b45..8102771665 100644 --- a/editors/protobuf-mode.el +++ b/editors/protobuf-mode.el @@ -216,7 +216,11 @@ Key bindings: (c-common-init 'protobuf-mode) (easy-menu-add protobuf-menu) (c-run-mode-hooks 'c-mode-common-hook 'protobuf-mode-hook) - (c-update-modeline)) + (c-update-modeline) + (setq imenu-generic-expression + '(("Message" "^[[:space:]]*message[[:space:]]+\\([[:alnum:]]+\\)" 1) + ("Enum" "^[[:space:]]*enum[[:space:]]+\\([[:alnum:]]+\\)" 1) + ("Service" "^[[:space:]]*service[[:space:]]+\\([[:alnum:]]+\\)" 1)))) (provide 'protobuf-mode) diff --git a/kokoro/linux/dockerfile/test/csharp/Dockerfile b/kokoro/linux/dockerfile/test/csharp/Dockerfile index 3d54436bac..95bd653152 100644 --- a/kokoro/linux/dockerfile/test/csharp/Dockerfile +++ b/kokoro/linux/dockerfile/test/csharp/Dockerfile @@ -29,7 +29,7 @@ RUN apt-get update && apt-get install -y libunwind8 libicu57 && apt-get clean RUN wget -q https://dot.net/v1/dotnet-install.sh && \ chmod u+x dotnet-install.sh && \ ./dotnet-install.sh --version 2.1.802 && \ - ./dotnet-install.sh --version 3.0.100 && \ + ./dotnet-install.sh --version 3.1.301 && \ ln -s /root/.dotnet/dotnet /usr/local/bin RUN wget -q www.nuget.org/NuGet.exe -O /usr/local/bin/nuget.exe diff --git a/objectivec/GPBAny.pbobjc.h b/objectivec/GPBAny.pbobjc.h index 288d552356..21b7dcf4af 100644 --- a/objectivec/GPBAny.pbobjc.h +++ b/objectivec/GPBAny.pbobjc.h @@ -94,10 +94,13 @@ typedef GPB_ENUM(GPBAny_FieldNumber) { * Example 4: Pack and unpack a message in Go * * foo := &pb.Foo{...} - * any, err := ptypes.MarshalAny(foo) + * any, err := anypb.New(foo) + * if err != nil { + * ... + * } * ... * foo := &pb.Foo{} - * if err := ptypes.UnmarshalAny(any, foo); err != nil { + * if err := any.UnmarshalTo(foo); err != nil { * ... * } * diff --git a/php/ext/google/protobuf2/arena.c b/php/ext/google/protobuf2/arena.c new file mode 100644 index 0000000000..035dfcad76 --- /dev/null +++ b/php/ext/google/protobuf2/arena.c @@ -0,0 +1,95 @@ +// 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. + +#include + +#include "php-upb.h" + +// ----------------------------------------------------------------------------- +// Arena +// ----------------------------------------------------------------------------- + +typedef struct Arena { + zend_object std; + upb_arena* arena; +} Arena; + +zend_class_entry *Arena_class_entry; +static zend_object_handlers Arena_object_handlers; + +// PHP Object Handlers ///////////////////////////////////////////////////////// + +static zend_object* Arena_Create(zend_class_entry *class_type) { + Arena *intern = emalloc(sizeof(Arena)); + zend_object_std_init(&intern->std, class_type); + intern->std.handlers = &Arena_object_handlers; + intern->arena = upb_arena_new(); + // Skip object_properties_init(), we don't allow derived classes. + return &intern->std; +} + +static void Arena_Free(zend_object* obj) { + Arena* intern = (Arena*)obj; + upb_arena_free(intern->arena); + zend_object_std_dtor(&intern->std); +} + +// C Functions from arena.h //////////////////////////////////////////////////// + +void Arena_Init(zval* val) { + ZVAL_OBJ(val, Arena_Create(Arena_class_entry)); +} + +upb_arena *Arena_Get(zval *val) { + Arena *a = (Arena*)Z_OBJ_P(val); + return a->arena; +} + +// ----------------------------------------------------------------------------- +// Module init. +// ----------------------------------------------------------------------------- + +// No public methods. +static const zend_function_entry Arena_methods[] = { + ZEND_FE_END +}; + +void Arena_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\Arena", Arena_methods); + Arena_class_entry = zend_register_internal_class(&tmp_ce); + Arena_class_entry->create_object = Arena_Create; + Arena_class_entry->ce_flags |= ZEND_ACC_FINAL; + + memcpy(&Arena_object_handlers, &std_object_handlers, + sizeof(zend_object_handlers)); + Arena_object_handlers.free_obj = Arena_Free; +} diff --git a/php/ext/google/protobuf2/arena.h b/php/ext/google/protobuf2/arena.h new file mode 100644 index 0000000000..67e165d37d --- /dev/null +++ b/php/ext/google/protobuf2/arena.h @@ -0,0 +1,47 @@ +// 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 PHP_PROTOBUF_ARENA_H_ +#define PHP_PROTOBUF_ARENA_H_ + +#include + +#include "php-upb.h" + +// Registers the PHP Arena class. +void Arena_ModuleInit(); + +// Creates and returns a new arena object that wraps a new upb_arena*. +void Arena_Init(zval *val); + +// Gets the underlying upb_arena from this arena object. +upb_arena *Arena_Get(zval *arena); + +#endif // PHP_PROTOBUF_ARENA_H_ diff --git a/php/ext/google/protobuf2/array.c b/php/ext/google/protobuf2/array.c new file mode 100644 index 0000000000..571d3e41cd --- /dev/null +++ b/php/ext/google/protobuf2/array.c @@ -0,0 +1,602 @@ +// 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. + +#include "array.h" + +#include +#include + +#include + +// This is not self-contained: it must be after other Zend includes. +#include + +#include "arena.h" +#include "convert.h" +#include "def.h" +#include "php-upb.h" +#include "protobuf.h" + +static void RepeatedFieldIter_make(zval *val, zval *repeated_field); + +// ----------------------------------------------------------------------------- +// RepeatedField +// ----------------------------------------------------------------------------- + +typedef struct { + zend_object std; + zval arena; + upb_array *array; + upb_fieldtype_t type; + const Descriptor* desc; // When values are messages. +} RepeatedField; + +zend_class_entry *RepeatedField_class_entry; +static zend_object_handlers RepeatedField_object_handlers; + +// PHP Object Handlers ///////////////////////////////////////////////////////// + +/** + * RepeatedField_create() + * + * PHP class entry function to allocate and initialize a new RepeatedField + * object. + */ +static zend_object* RepeatedField_create(zend_class_entry *class_type) { + RepeatedField *intern = emalloc(sizeof(RepeatedField)); + zend_object_std_init(&intern->std, class_type); + intern->std.handlers = &RepeatedField_object_handlers; + Arena_Init(&intern->arena); + intern->array = NULL; + intern->desc = NULL; + // Skip object_properties_init(), we don't allow derived classes. + return &intern->std; +} + +/** + * RepeatedField_dtor() + * + * Object handler to destroy a RepeatedField. This releases all resources + * associated with the message. Note that it is possible to access a destroyed + * object from PHP in rare cases. + */ +static void RepeatedField_destructor(zend_object* obj) { + RepeatedField* intern = (RepeatedField*)obj; + ObjCache_Delete(intern->array); + zval_ptr_dtor(&intern->arena); + zend_object_std_dtor(&intern->std); +} + +static HashTable *RepeatedField_GetProperties(zval *object TSRMLS_DC) { + return NULL; // We do not have a properties table. +} + +static zval *RepeatedField_GetPropertyPtrPtr(zval *object, zval *member, + int type, void **cache_slot) { + return NULL; // We don't offer direct references to our properties. +} + +// C Functions from array.h //////////////////////////////////////////////////// + +// These are documented in the header file. + +void RepeatedField_GetPhpWrapper(zval *val, upb_array *arr, + const upb_fielddef *f, zval *arena) { + if (!arr) { + ZVAL_NULL(val); + return; + } + + if (!ObjCache_Get(arr, val)) { + RepeatedField *intern = emalloc(sizeof(RepeatedField)); + zend_object_std_init(&intern->std, RepeatedField_class_entry); + intern->std.handlers = &RepeatedField_object_handlers; + ZVAL_COPY(&intern->arena, arena); + intern->array = arr; + intern->type = upb_fielddef_type(f); + intern->desc = Descriptor_GetFromFieldDef(f); + // Skip object_properties_init(), we don't allow derived classes. + ObjCache_Add(intern->array, &intern->std); + ZVAL_OBJ(val, &intern->std); + } +} + +upb_array *RepeatedField_GetUpbArray(zval *val, const upb_fielddef *f, + upb_arena *arena) { + if (Z_ISREF_P(val)) { + ZVAL_DEREF(val); + } + + if (Z_TYPE_P(val) == IS_ARRAY) { + // Auto-construct, eg. [1, 2, 3] -> upb_array([1, 2, 3]). + upb_array *arr = upb_array_new(arena, upb_fielddef_type(f)); + HashTable *table = HASH_OF(val); + HashPosition pos; + upb_fieldtype_t type = upb_fielddef_type(f); + const Descriptor *desc = Descriptor_GetFromFieldDef(f); + + zend_hash_internal_pointer_reset_ex(table, &pos); + + while (true) { + zval *zv = zend_hash_get_current_data_ex(table, &pos); + upb_msgval val; + + if (!zv) return arr; + + if (!Convert_PhpToUpbAutoWrap(zv, &val, type, desc, arena)) { + return NULL; + } + + upb_array_append(arr, val, arena); + zend_hash_move_forward_ex(table, &pos); + } + } else if (Z_TYPE_P(val) == IS_OBJECT && + Z_OBJCE_P(val) == RepeatedField_class_entry) { + // Unwrap existing RepeatedField object to get the upb_array* inside. + RepeatedField *intern = (RepeatedField*)Z_OBJ_P(val); + const Descriptor *desc = Descriptor_GetFromFieldDef(f); + + if (intern->type != upb_fielddef_type(f) || intern->desc != desc) { + php_error_docref(NULL, E_USER_ERROR, + "Wrong type for this repeated field."); + } + + upb_arena_fuse(arena, Arena_Get(&intern->arena)); + return intern->array; + } else { + php_error_docref(NULL, E_USER_ERROR, "Must be a repeated field"); + return NULL; + } +} + +// RepeatedField PHP methods /////////////////////////////////////////////////// + +/** + * RepeatedField::__construct() + * + * Constructs an instance of RepeatedField. + * @param long Type of the stored element. + * @param string Message/Enum class. + */ +PHP_METHOD(RepeatedField, __construct) { + RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis()); + upb_arena *arena = Arena_Get(&intern->arena); + zend_long type; + zend_class_entry* klass = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|C", &type, &klass) != SUCCESS) { + return; + } + + intern->type = pbphp_dtype_to_type(type); + intern->desc = Descriptor_GetFromClassEntry(klass); + + if (intern->type == UPB_TYPE_MESSAGE && klass == NULL) { + php_error_docref(NULL, E_USER_ERROR, + "Message/enum type must have concrete class."); + return; + } + + intern->array = upb_array_new(arena, intern->type); + ObjCache_Add(intern->array, &intern->std); +} + +/** + * RepeatedField::append() + * + * Append element to the end of the repeated field. + * @param object The element to be added. + */ +PHP_METHOD(RepeatedField, append) { + RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis()); + upb_arena *arena = Arena_Get(&intern->arena); + zval *php_val; + upb_msgval msgval; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &php_val) != SUCCESS || + !Convert_PhpToUpb(php_val, &msgval, intern->type, intern->desc, arena)) { + return; + } + + upb_array_append(intern->array, msgval, arena); +} + +/** + * RepeatedField::offsetExists() + * + * Implements the ArrayAccess interface. Invoked when PHP code calls: + * + * isset($arr[$idx]); + * empty($arr[$idx]); + * + * @param long The index to be checked. + * @return bool True if the element at the given index exists. + */ +PHP_METHOD(RepeatedField, offsetExists) { + RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis()); + zend_long index; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) { + return; + } + + RETURN_BOOL(index >= 0 && index < upb_array_size(intern->array)); +} + +/** + * RepeatedField::offsetGet() + * + * Implements the ArrayAccess interface. Invoked when PHP code calls: + * + * $x = $arr[$idx]; + * + * @param long The index of the element to be fetched. + * @return object The stored element at given index. + * @exception Invalid type for index. + * @exception Non-existing index. + */ +PHP_METHOD(RepeatedField, offsetGet) { + RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis()); + zend_long index; + upb_msgval msgval; + zval ret; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) { + return; + } + + if (index < 0 || index >= upb_array_size(intern->array)) { + zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index); + return; + } + + msgval = upb_array_get(intern->array, index); + Convert_UpbToPhp(msgval, &ret, intern->type, intern->desc, &intern->arena); + RETURN_ZVAL(&ret, 0, 1); +} + +/** + * RepeatedField::offsetSet() + * + * Implements the ArrayAccess interface. Invoked when PHP code calls: + * + * $arr[$idx] = $x; + * $arr []= $x; // Append + * + * @param long The index of the element to be assigned. + * @param object The element to be assigned. + * @exception Invalid type for index. + * @exception Non-existing index. + * @exception Incorrect type of the element. + */ +PHP_METHOD(RepeatedField, offsetSet) { + RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis()); + upb_arena *arena = Arena_Get(&intern->arena); + size_t size = upb_array_size(intern->array); + zval *offset, *val; + int64_t index; + upb_msgval msgval; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &offset, &val) != SUCCESS) { + return; + } + + if (Z_TYPE_P(offset) == IS_NULL) { + index = size; + } else if (!Convert_PhpToInt64(offset, &index)) { + return; + } + + if (!Convert_PhpToUpb(val, &msgval, intern->type, intern->desc, arena)) { + return; + } + + if (index > size) { + zend_error(E_USER_ERROR, "Element at index %ld doesn't exist.\n", index); + } else if (index == size) { + upb_array_append(intern->array, msgval, Arena_Get(&intern->arena)); + } else { + upb_array_set(intern->array, index, msgval); + } +} + +/** + * RepeatedField::offsetUnset() + * + * Implements the ArrayAccess interface. Invoked when PHP code calls: + * + * unset($arr[$idx]); + * + * @param long The index of the element to be removed. + * @exception Invalid type for index. + * @exception The element to be removed is not at the end of the RepeatedField. + */ +PHP_METHOD(RepeatedField, offsetUnset) { + RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis()); + zend_long index; + zend_long size = upb_array_size(intern->array); + + // Only the element at the end of the array can be removed. + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) != SUCCESS) { + return; + } + + if (size == 0 || index != size - 1) { + php_error_docref(NULL, E_USER_ERROR, "Cannot remove element at %ld.\n", + index); + return; + } + + upb_array_resize(intern->array, size - 1, Arena_Get(&intern->arena)); +} + +/** + * RepeatedField::count() + * + * Implements the Countable interface. Invoked when PHP code calls: + * + * $len = count($arr); + * Return the number of stored elements. + * This will also be called for: count($arr) + * @return long The number of stored elements. + */ +PHP_METHOD(RepeatedField, count) { + RepeatedField *intern = (RepeatedField*)Z_OBJ_P(getThis()); + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + RETURN_LONG(upb_array_size(intern->array)); +} + +/** + * RepeatedField::getIterator() + * + * Implements the IteratorAggregate interface. Invoked when PHP code calls: + * + * foreach ($arr) {} + * + * @return object Beginning iterator. + */ +PHP_METHOD(RepeatedField, getIterator) { + zval ret; + RepeatedFieldIter_make(&ret, getThis()); + RETURN_ZVAL(&ret, 0, 1); +} + +ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1) + ZEND_ARG_INFO(0, index) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetSet, 0, 0, 2) + ZEND_ARG_INFO(0, index) + ZEND_ARG_INFO(0, newval) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_void, 0) +ZEND_END_ARG_INFO() + +static zend_function_entry repeated_field_methods[] = { + PHP_ME(RepeatedField, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedField, append, NULL, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedField, offsetUnset, arginfo_offsetGet, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedField, count, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedField, getIterator, arginfo_void, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +// ----------------------------------------------------------------------------- +// PHP RepeatedFieldIter +// ----------------------------------------------------------------------------- + +typedef struct { + zend_object std; + zval repeated_field; + zend_long position; +} RepeatedFieldIter; + +zend_class_entry *RepeatedFieldIter_class_entry; +static zend_object_handlers repeated_field_iter_object_handlers; + +/** + * RepeatedFieldIter_create() + * + * PHP class entry function to allocate and initialize a new RepeatedFieldIter + * object. + */ +zend_object* RepeatedFieldIter_create(zend_class_entry *class_type) { + RepeatedFieldIter *intern = emalloc(sizeof(RepeatedFieldIter)); + zend_object_std_init(&intern->std, class_type); + intern->std.handlers = &repeated_field_iter_object_handlers; + ZVAL_NULL(&intern->repeated_field); + intern->position = 0; + // Skip object_properties_init(), we don't allow derived classes. + return &intern->std; +} + +/** + * RepeatedFieldIter_dtor() + * + * Object handler to destroy a RepeatedFieldIter. This releases all resources + * associated with the message. Note that it is possible to access a destroyed + * object from PHP in rare cases. + */ +static void RepeatedFieldIter_dtor(zend_object* obj) { + RepeatedFieldIter* intern = (RepeatedFieldIter*)obj; + zval_ptr_dtor(&intern->repeated_field); + zend_object_std_dtor(&intern->std); +} + +/** + * RepeatedFieldIter_make() + * + * C function to create a RepeatedFieldIter. + */ +static void RepeatedFieldIter_make(zval *val, zval *repeated_field) { + RepeatedFieldIter *iter; + ZVAL_OBJ(val, RepeatedFieldIter_class_entry->create_object( + RepeatedFieldIter_class_entry)); + iter = (RepeatedFieldIter*)Z_OBJ_P(val); + ZVAL_COPY(&iter->repeated_field, repeated_field); +} + +/* + * When a user writes: + * + * foreach($arr as $key => $val) {} + * + * PHP's iterator protocol is: + * + * $iter = $arr->getIterator(); + * for ($iter->rewind(); $iter->valid(); $iter->next()) { + * $key = $iter->key(); + * $val = $iter->current(); + * } + */ + +/** + * RepeatedFieldIter::rewind() + * + * Implements the Iterator interface. Sets the iterator to the first element. + */ +PHP_METHOD(RepeatedFieldIter, rewind) { + RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis()); + intern->position = 0; +} + +/** + * RepeatedFieldIter::current() + * + * Implements the Iterator interface. Returns the current value. + */ +PHP_METHOD(RepeatedFieldIter, current) { + RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis()); + RepeatedField *field = (RepeatedField*)Z_OBJ_P(&intern->repeated_field); + upb_array *array = field->array; + zend_long index = intern->position; + upb_msgval msgval; + zval ret; + + if (index < 0 || index >= upb_array_size(array)) { + zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index); + } + + msgval = upb_array_get(array, index); + + Convert_UpbToPhp(msgval, &ret, field->type, field->desc, &field->arena); + RETURN_ZVAL(&ret, 0, 1); +} + +/** + * RepeatedFieldIter::key() + * + * Implements the Iterator interface. Returns the current key. + */ +PHP_METHOD(RepeatedFieldIter, key) { + RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis()); + RETURN_LONG(intern->position); +} + +/** + * RepeatedFieldIter::next() + * + * Implements the Iterator interface. Advances to the next element. + */ +PHP_METHOD(RepeatedFieldIter, next) { + RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis()); + ++intern->position; +} + +/** + * RepeatedFieldIter::valid() + * + * Implements the Iterator interface. Returns true if this is a valid element. + */ +PHP_METHOD(RepeatedFieldIter, valid) { + RepeatedFieldIter *intern = (RepeatedFieldIter*)Z_OBJ_P(getThis()); + RepeatedField *field = (RepeatedField*)Z_OBJ_P(&intern->repeated_field); + RETURN_BOOL(intern->position < upb_array_size(field->array)); +} + +static zend_function_entry repeated_field_iter_methods[] = { + PHP_ME(RepeatedFieldIter, rewind, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedFieldIter, current, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedFieldIter, key, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedFieldIter, next, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedFieldIter, valid, arginfo_void, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +// ----------------------------------------------------------------------------- +// Module init. +// ----------------------------------------------------------------------------- + +/** + * Array_ModuleInit() + * + * Called when the C extension is loaded to register all types. + */ +void Array_ModuleInit() { + zend_class_entry tmp_ce; + zend_object_handlers *h; + + // RepeatedField. + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\RepeatedField", + repeated_field_methods); + + RepeatedField_class_entry = zend_register_internal_class(&tmp_ce); + zend_class_implements(RepeatedField_class_entry, 3, spl_ce_ArrayAccess, + zend_ce_aggregate, spl_ce_Countable); + RepeatedField_class_entry->ce_flags |= ZEND_ACC_FINAL; + RepeatedField_class_entry->create_object = RepeatedField_create; + + h = &RepeatedField_object_handlers; + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + h->dtor_obj = RepeatedField_destructor; + h->get_properties = RepeatedField_GetProperties; + h->get_property_ptr_ptr = RepeatedField_GetPropertyPtrPtr; + + // RepeatedFieldIter + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\RepeatedFieldIter", + repeated_field_iter_methods); + + RepeatedFieldIter_class_entry = zend_register_internal_class(&tmp_ce); + zend_class_implements(RepeatedFieldIter_class_entry, 1, zend_ce_iterator); + RepeatedFieldIter_class_entry->ce_flags |= ZEND_ACC_FINAL; + RepeatedFieldIter_class_entry->create_object = RepeatedFieldIter_create; + + h = &repeated_field_iter_object_handlers; + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + h->dtor_obj = RepeatedFieldIter_dtor; +} diff --git a/php/ext/google/protobuf2/array.h b/php/ext/google/protobuf2/array.h new file mode 100644 index 0000000000..5cf517c566 --- /dev/null +++ b/php/ext/google/protobuf2/array.h @@ -0,0 +1,61 @@ +// 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 PHP_PROTOBUF_ARRAY_H_ +#define PHP_PROTOBUF_ARRAY_H_ + +#include + +#include "php-upb.h" + +// Registers PHP classes for RepeatedField. +void Array_ModuleInit(); + +// Gets a upb_array* for the PHP object |val|: +// * If |val| is a RepeatedField object, we first check its type and verify +// that that the elements have the correct type for |f|. If so, we return the +// wrapped upb_array*. We also make sure that this array's arena is fused to +// |arena|, so the returned upb_array is guaranteed to live as long as +// |arena|. +// * If |val| is a PHP Array, we attempt to create a new upb_array using +// |arena| and add all of the PHP elements to it. +// +// If an error occurs, we raise a PHP error and return NULL. +upb_array *RepeatedField_GetUpbArray(zval *val, const upb_fielddef *f, upb_arena *arena); + +// Creates a PHP RepeatedField object for the given upb_array* and |f| and +// returns it in |val|. The PHP object will keep a reference to this |arena| to +// ensure the underlying array data stays alive. +// +// If |arr| is NULL, this will return a PHP null object. +void RepeatedField_GetPhpWrapper(zval *val, upb_array *arr, + const upb_fielddef *f, zval *arena); + +#endif // PHP_PROTOBUF_ARRAY_H_ diff --git a/php/ext/google/protobuf2/bundled_php.h b/php/ext/google/protobuf2/bundled_php.h new file mode 100644 index 0000000000..76147677a1 --- /dev/null +++ b/php/ext/google/protobuf2/bundled_php.h @@ -0,0 +1,46 @@ +// 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 PHP_PROTOBUF_BUNDLED_PHP_H_ +#define PHP_PROTOBUF_BUNDLED_PHP_H_ + +// We embed PHP source code into the binary for things we don't want to +// implement in C. This struct serves as a table of contents for all of +// the embedded files. +typedef struct { + const char *filename; + const char *contents; +} BundledPhp_File; + +// An array of all the embedded file structs. This array is terminated with a +// {NULL, NULL} entry. +extern BundledPhp_File *bundled_files; + +#endif // PHP_PROTOBUF_BUNDLED_PHP_H_ diff --git a/php/ext/google/protobuf2/config.m4 b/php/ext/google/protobuf2/config.m4 new file mode 100644 index 0000000000..3fdcb00480 --- /dev/null +++ b/php/ext/google/protobuf2/config.m4 @@ -0,0 +1,10 @@ +PHP_ARG_ENABLE(protobuf, whether to enable Protobuf extension, [ --enable-protobuf Enable Protobuf extension]) + +if test "$PHP_PROTOBUF" != "no"; then + + PHP_NEW_EXTENSION( + protobuf, + arena.c array.c bundled_php.c convert.c def.c map.c message.c names.c php-upb.c protobuf.c, + $ext_shared) + +fi diff --git a/php/ext/google/protobuf2/convert.c b/php/ext/google/protobuf2/convert.c new file mode 100644 index 0000000000..dd076c5f1a --- /dev/null +++ b/php/ext/google/protobuf2/convert.c @@ -0,0 +1,478 @@ +// 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. + +#include "convert.h" + +#include + +// This is not self-contained: it must be after other Zend includes. +#include + +#include "array.h" +#include "map.h" +#include "message.h" +#include "php-upb.h" +#include "protobuf.h" + +// ----------------------------------------------------------------------------- +// GPBUtil +// ----------------------------------------------------------------------------- + +static zend_class_entry* GPBUtil_class_entry; + +// The implementation of type checking for primitive fields is empty. This is +// because type checking is done when direct assigning message fields (e.g., +// foo->a = 1). Functions defined here are place holders in generated code for +// pure PHP implementation (c extension and pure PHP share the same generated +// code). + +PHP_METHOD(Util, checkInt32) {} +PHP_METHOD(Util, checkUint32) {} +PHP_METHOD(Util, checkInt64) {} +PHP_METHOD(Util, checkUint64) {} +PHP_METHOD(Util, checkEnum) {} +PHP_METHOD(Util, checkFloat) {} +PHP_METHOD(Util, checkDouble) {} +PHP_METHOD(Util, checkBool) {} +PHP_METHOD(Util, checkString) {} +PHP_METHOD(Util, checkBytes) {} +PHP_METHOD(Util, checkMessage) {} + +// The result of checkMapField() is assigned, so we need to return the first +// param: +// $arr = GPBUtil::checkMapField($var, +// \Google\Protobuf\Internal\GPBType::INT64, +// \Google\Protobuf\Internal\GPBType::INT32); +PHP_METHOD(Util, checkMapField) { + zval *val, *key_type, *val_type, *klass; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzz|z", &val, &key_type, + &val_type, &klass) == FAILURE) { + return; + } + RETURN_ZVAL(val, 1, 0); +} + +// The result of checkRepeatedField() is assigned, so we need to return the +// first param: +// $arr = GPBUtil::checkRepeatedField( +// $var, \Google\Protobuf\Internal\GPBType::STRING); +PHP_METHOD(Util, checkRepeatedField) { + zval *val, *type, *klass; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz|z", &val, &type, &klass) == + FAILURE) { + return; + } + RETURN_ZVAL(val, 1, 0); +} + +static zend_function_entry util_methods[] = { + PHP_ME(Util, checkInt32, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkUint32, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkInt64, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkUint64, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkEnum, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkFloat, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkDouble, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkBool, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkString, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkBytes, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkMessage, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkMapField, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkRepeatedField, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + ZEND_FE_END +}; + +// ----------------------------------------------------------------------------- +// Conversion functions used from C +// ----------------------------------------------------------------------------- + +upb_fieldtype_t pbphp_dtype_to_type(upb_descriptortype_t type) { + switch (type) { +#define CASE(descriptor_type, type) \ + case UPB_DESCRIPTOR_TYPE_##descriptor_type: \ + return UPB_TYPE_##type; + + CASE(FLOAT, FLOAT); + CASE(DOUBLE, DOUBLE); + CASE(BOOL, BOOL); + CASE(STRING, STRING); + CASE(BYTES, BYTES); + CASE(MESSAGE, MESSAGE); + CASE(GROUP, MESSAGE); + CASE(ENUM, ENUM); + CASE(INT32, INT32); + CASE(INT64, INT64); + CASE(UINT32, UINT32); + CASE(UINT64, UINT64); + CASE(SINT32, INT32); + CASE(SINT64, INT64); + CASE(FIXED32, UINT32); + CASE(FIXED64, UINT64); + CASE(SFIXED32, INT32); + CASE(SFIXED64, INT64); + +#undef CASE + + } + + zend_error(E_ERROR, "Unknown field type."); + return 0; +} + +static bool buftouint64(const char *ptr, const char *end, uint64_t *val) { + uint64_t u64 = 0; + while (ptr < end) { + unsigned ch = (unsigned)(*ptr - '0'); + if (ch >= 10) break; + if (u64 > UINT64_MAX / 10 || u64 * 10 > UINT64_MAX - ch) { + return false; + } + u64 *= 10; + u64 += ch; + ptr++; + } + + if (ptr != end) { + // In PHP tradition, we allow truncation: "1.1" -> 1. + // But we don't allow 'e', eg. '1.1e2' or any other non-numeric chars. + if (*ptr++ != '.') return false; + + for (;ptr < end; ptr++) { + if (*ptr < '0' || *ptr > '9') { + return false; + } + } + } + + *val = u64; + return true; +} + +static bool buftoint64(const char *ptr, const char *end, int64_t *val) { + bool neg = false; + uint64_t u64; + + if (ptr != end && *ptr == '-') { + ptr++; + neg = true; + } + + if (!buftouint64(ptr, end, &u64) || + u64 > (uint64_t)INT64_MAX + neg) { + return false; + } + + *val = neg ? -u64 : u64; + return true; +} + +static void throw_conversion_exception(const char *to, const zval *zv) { + zval tmp; + ZVAL_COPY(&tmp, zv); + convert_to_string(&tmp); + + zend_throw_exception_ex(NULL, 0, "Cannot convert '%s' to %s", + Z_STRVAL_P(&tmp), to); + + zval_ptr_dtor(&tmp); +} + +bool Convert_PhpToInt64(const zval *php_val, int64_t *i64) { + switch (Z_TYPE_P(php_val)) { + case IS_LONG: + *i64 = Z_LVAL_P(php_val); + return true; + case IS_DOUBLE: { + double dbl = Z_DVAL_P(php_val); + if (dbl > 9223372036854774784.0 || dbl < -9223372036854775808.0) { + zend_throw_exception_ex(NULL, 0, "Out of range"); + return false; + } + *i64 = dbl; /* must be guarded, overflow here is UB */ + return true; + } + case IS_STRING: { + const char *buf = Z_STRVAL_P(php_val); + // PHP would accept scientific notation here, but we're going to be a + // little more discerning and only accept pure integers. + bool ok = buftoint64(buf, buf + Z_STRLEN_P(php_val), i64); + if (!ok) { + throw_conversion_exception("integer", php_val); + } + return ok; + } + default: + throw_conversion_exception("integer", php_val); + return false; + } +} + +static bool to_double(zval *php_val, double *dbl) { + switch (Z_TYPE_P(php_val)) { + case IS_LONG: + *dbl = Z_LVAL_P(php_val); + return true; + case IS_DOUBLE: + *dbl = Z_DVAL_P(php_val); + return true; + case IS_STRING: { + zend_long lval; + switch (is_numeric_string(Z_STRVAL_P(php_val), Z_STRLEN_P(php_val), &lval, + dbl, false)) { + case IS_LONG: + *dbl = lval; + return true; + case IS_DOUBLE: + return true; + default: + goto fail; + } + } + default: + fail: + throw_conversion_exception("double", php_val); + return false; + } +} + +static bool to_bool(zval* from, bool* to) { + switch (Z_TYPE_P(from)) { + case IS_TRUE: + *to = true; + return true; + case IS_FALSE: + *to = false; + return true; + case IS_LONG: + *to = (Z_LVAL_P(from) != 0); + return true; + case IS_DOUBLE: + *to = (Z_LVAL_P(from) != 0); + return true; + case IS_STRING: + if (Z_STRLEN_P(from) == 0 || + (Z_STRLEN_P(from) == 1 && Z_STRVAL_P(from)[0] == '0')) { + *to = false; + } else { + *to = true; + } + return true; + default: + throw_conversion_exception("bool", from); + return false; + } +} + +static bool to_string(zval* from) { + if (Z_ISREF_P(from)) { + ZVAL_DEREF(from); + } + + switch (Z_TYPE_P(from)) { + case IS_STRING: + return true; + case IS_TRUE: + case IS_FALSE: + case IS_LONG: + case IS_DOUBLE: { + zval tmp; + zend_make_printable_zval(from, &tmp); + ZVAL_COPY_VALUE(from, &tmp); + return true; + } + default: + throw_conversion_exception("string", from); + return false; + } +} + +bool Convert_PhpToUpb(zval *php_val, upb_msgval *upb_val, upb_fieldtype_t type, + const Descriptor *desc, upb_arena *arena) { + int64_t i64; + + if (Z_ISREF_P(php_val)) { + ZVAL_DEREF(php_val); + } + + switch (type) { + case UPB_TYPE_INT64: + return Convert_PhpToInt64(php_val, &upb_val->int64_val); + case UPB_TYPE_INT32: + case UPB_TYPE_ENUM: + if (!Convert_PhpToInt64(php_val, &i64)) { + return false; + } + upb_val->int32_val = i64; + return true; + case UPB_TYPE_UINT64: + if (!Convert_PhpToInt64(php_val, &i64)) { + return false; + } + upb_val->uint64_val = i64; + return true; + case UPB_TYPE_UINT32: + if (!Convert_PhpToInt64(php_val, &i64)) { + return false; + } + upb_val->uint32_val = i64; + return true; + case UPB_TYPE_DOUBLE: + return to_double(php_val, &upb_val->double_val); + case UPB_TYPE_FLOAT: + if (!to_double(php_val, &upb_val->double_val)) return false; + upb_val->float_val = upb_val->double_val; + return true; + case UPB_TYPE_BOOL: + return to_bool(php_val, &upb_val->bool_val); + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: { + char *ptr; + size_t size; + + if (!to_string(php_val)) return false; + + size = Z_STRLEN_P(php_val); + + // If arena is NULL we reference the input zval. + // The resulting upb_strview will only be value while the zval is alive. + if (arena) { + ptr = upb_arena_malloc(arena, size); + memcpy(ptr, Z_STRVAL_P(php_val), size); + } else { + ptr = Z_STRVAL_P(php_val); + } + + upb_val->str_val = upb_strview_make(ptr, size); + return true; + } + case UPB_TYPE_MESSAGE: + PBPHP_ASSERT(desc); + return Message_GetUpbMessage(php_val, desc, arena, + (upb_msg **)&upb_val->msg_val); + } + + return false; +} + +void Convert_UpbToPhp(upb_msgval upb_val, zval *php_val, upb_fieldtype_t type, + const Descriptor *desc, zval *arena) { + switch (type) { + case UPB_TYPE_INT64: +#if SIZEOF_ZEND_LONG == 8 + ZVAL_LONG(php_val, upb_val.int64_val); +#else + { + char buf[20]; + int size = sprintf(buf, "%lld", upb_val.int64_val); + ZVAL_NEW_STR(php_val, zend_string_init(buf, size, 0)); + } +#endif + break; + case UPB_TYPE_UINT64: +#if SIZEOF_ZEND_LONG == 8 + ZVAL_LONG(php_val, upb_val.uint64_val); +#else + { + char buf[20]; + int size = sprintf(buf, "%lld", (int64_t)upb_val.uint64_val); + ZVAL_NEW_STR(php_val, zend_string_init(buf, size, 0)); + } +#endif + break; + case UPB_TYPE_INT32: + case UPB_TYPE_ENUM: + ZVAL_LONG(php_val, upb_val.int32_val); + break; + case UPB_TYPE_UINT32: { + // Sign-extend for consistency between 32/64-bit builds. + zend_long val = (int32_t)upb_val.uint32_val; + ZVAL_LONG(php_val, val); + break; + } + case UPB_TYPE_DOUBLE: + ZVAL_DOUBLE(php_val, upb_val.double_val); + break; + case UPB_TYPE_FLOAT: + ZVAL_DOUBLE(php_val, upb_val.float_val); + break; + case UPB_TYPE_BOOL: + ZVAL_BOOL(php_val, upb_val.bool_val); + break; + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: { + upb_strview str = upb_val.str_val; + ZVAL_NEW_STR(php_val, zend_string_init(str.data, str.size, 0)); + break; + } + case UPB_TYPE_MESSAGE: + PBPHP_ASSERT(desc); + Message_GetPhpWrapper(php_val, desc, (upb_msg*)upb_val.msg_val, arena); + break; + } +} + +bool Convert_PhpToUpbAutoWrap(zval *val, upb_msgval *upb_val, + upb_fieldtype_t type, const Descriptor *desc, + upb_arena *arena) { + const upb_msgdef *subm = desc ? desc->msgdef : NULL; + if (subm && upb_msgdef_iswrapper(subm) && Z_TYPE_P(val) != IS_OBJECT) { + // Assigning a scalar to a wrapper-typed value. We will automatically wrap + // the value, so the user doesn't need to create a FooWrapper(['value': X]) + // message manually. + upb_msg *wrapper = upb_msg_new(subm, arena); + const upb_fielddef *val_f = upb_msgdef_itof(subm, 1); + upb_fieldtype_t type_f = upb_fielddef_type(val_f); + upb_msgval msgval; + if (!Convert_PhpToUpb(val, &msgval, type_f, NULL, arena)) return false; + upb_msg_set(wrapper, val_f, msgval, arena); + upb_val->msg_val = wrapper; + return true; + } else { + // Convert_PhpToUpb doesn't auto-construct messages. This means that we only + // allow: + // ['foo_submsg': new Foo(['a' => 1])] + // not: + // ['foo_submsg': ['a' => 1]] + return Convert_PhpToUpb(val, upb_val, type, desc, arena); + } +} + +void Convert_ModuleInit(void) { + const char *prefix_name = "TYPE_URL_PREFIX"; + zend_class_entry class_type; + + INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBUtil", + util_methods); + GPBUtil_class_entry = zend_register_internal_class(&class_type); + + zend_declare_class_constant_string(GPBUtil_class_entry, prefix_name, + strlen(prefix_name), + "type.googleapis.com/"); +} diff --git a/php/ext/google/protobuf2/convert.h b/php/ext/google/protobuf2/convert.h new file mode 100644 index 0000000000..06c05c7275 --- /dev/null +++ b/php/ext/google/protobuf2/convert.h @@ -0,0 +1,73 @@ +// 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 PHP_PROTOBUF_CONVERT_H_ +#define PHP_PROTOBUF_CONVERT_H_ + +#include + +#include "php-upb.h" +#include "def.h" + +upb_fieldtype_t pbphp_dtype_to_type(upb_descriptortype_t type); + +// Converts |php_val| to an int64_t. Returns false if the value cannot be +// converted. +bool Convert_PhpToInt64(const zval *php_val, int64_t *i64); + +// Converts |php_val| to a upb_msgval according to |type|. If type is +// UPB_TYPE_MESSAGE, then |desc| must be the Descriptor for this message type. +// If type is string, message, or bytes, then |arena| will be used to copy +// string data or fuse this arena to the given message's arena. +bool Convert_PhpToUpb(zval *php_val, upb_msgval *upb_val, upb_fieldtype_t type, + const Descriptor *desc, upb_arena *arena); + +// Similar to Convert_PhpToUpb, but supports automatically wrapping the wrapper +// types if a primitive is specified: +// +// 5 -> Int64Wrapper(value=5) +// +// We currently allow this implicit conversion in initializers, but not for +// assignment. +bool Convert_PhpToUpbAutoWrap(zval *val, upb_msgval *upb_val, + upb_fieldtype_t type, const Descriptor *desc, + upb_arena *arena); + +// Converts |upb_val| to a PHP zval according to |type|. This may involve +// creating a PHP wrapper object. If type == UPB_TYPE_MESSAGE, then |desc| must +// be the Descriptor for this message type. Any newly created wrapper object +// will reference |arena|. +void Convert_UpbToPhp(upb_msgval upb_val, zval *php_val, upb_fieldtype_t type, + const Descriptor *desc, zval *arena); + +// Registers the GPBUtil class. +void Convert_ModuleInit(void); + +#endif // PHP_PROTOBUF_CONVERT_H_ diff --git a/php/ext/google/protobuf2/def.c b/php/ext/google/protobuf2/def.c new file mode 100644 index 0000000000..c76134d86b --- /dev/null +++ b/php/ext/google/protobuf2/def.c @@ -0,0 +1,1085 @@ +// 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. + +#include "def.h" + +#include + +// This is not self-contained: it must be after other Zend includes. +#include + +#include "names.h" +#include "php-upb.h" +#include "protobuf.h" + +static void CheckUpbStatus(const upb_status* status, const char* msg) { + if (!upb_ok(status)) { + zend_error(E_ERROR, "%s: %s\n", msg, upb_status_errmsg(status)); + } +} + +static void FieldDescriptor_FromFieldDef(zval *val, const upb_fielddef *f); + +// We use this for objects that should not be created directly from PHP. +static zend_object *CreateHandler_ReturnNull(zend_class_entry *class_type) { + return NULL; // Nobody should call this. +} + + +// ----------------------------------------------------------------------------- +// EnumValueDescriptor +// ----------------------------------------------------------------------------- + +typedef struct { + zend_object std; + const char *name; + int32_t number; +} EnumValueDescriptor; + +zend_class_entry *EnumValueDescriptor_class_entry; +static zend_object_handlers EnumValueDescriptor_object_handlers; + +/* + * EnumValueDescriptor_Make() + * + * Function to create an EnumValueDescriptor object from C. + */ +static void EnumValueDescriptor_Make(zval *val, const char *name, + int32_t number) { + EnumValueDescriptor *intern = emalloc(sizeof(EnumValueDescriptor)); + zend_object_std_init(&intern->std, EnumValueDescriptor_class_entry); + intern->std.handlers = &EnumValueDescriptor_object_handlers; + intern->name = name; + intern->number = number; + // Skip object_properties_init(), we don't allow derived classes. + ZVAL_OBJ(val, &intern->std); +} + +/* + * EnumValueDescriptor::getName() + * + * Returns the name for this enum value. + */ +PHP_METHOD(EnumValueDescriptor, getName) { + EnumValueDescriptor *intern = (EnumValueDescriptor*)Z_OBJ_P(getThis()); + RETURN_STRING(intern->name); +} + +/* + * EnumValueDescriptor::getNumber() + * + * Returns the number for this enum value. + */ +PHP_METHOD(EnumValueDescriptor, getNumber) { + EnumValueDescriptor *intern = (EnumValueDescriptor*)Z_OBJ_P(getThis()); + RETURN_LONG(intern->number); +} + +static zend_function_entry EnumValueDescriptor_methods[] = { + PHP_ME(EnumValueDescriptor, getName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(EnumValueDescriptor, getNumber, NULL, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +// ----------------------------------------------------------------------------- +// EnumDescriptor +// ----------------------------------------------------------------------------- + +typedef struct { + zend_object std; + const upb_enumdef *enumdef; +} EnumDescriptor; + +zend_class_entry *EnumDescriptor_class_entry; +static zend_object_handlers EnumDescriptor_object_handlers; + +void EnumDescriptor_FromClassEntry(zval *val, zend_class_entry *ce) { + // To differentiate enums from classes, we pointer-tag the class entry. + void* key = (void*)((uintptr_t)ce | 1); + PBPHP_ASSERT(key != ce); + + if (ce == NULL) { + ZVAL_NULL(val); + return; + } + + if (!ObjCache_Get(key, val)) { + const upb_enumdef *e = NameMap_GetEnum(ce); + if (!e) { + ZVAL_NULL(val); + return; + } + EnumDescriptor* ret = emalloc(sizeof(EnumDescriptor)); + zend_object_std_init(&ret->std, EnumDescriptor_class_entry); + ret->std.handlers = &EnumDescriptor_object_handlers; + ret->enumdef = e; + ObjCache_Add(key, &ret->std); + + // Prevent this from ever being collected (within a request). + GC_ADDREF(&ret->std); + + ZVAL_OBJ(val, &ret->std); + } +} + +void EnumDescriptor_FromEnumDef(zval *val, const upb_enumdef *m) { + if (!m) { + ZVAL_NULL(val); + } else { + char *classname = + GetPhpClassname(upb_enumdef_file(m), upb_enumdef_fullname(m)); + zend_string *str = zend_string_init(classname, strlen(classname), 0); + zend_class_entry *ce = zend_lookup_class(str); // May autoload the class. + + zend_string_release (str); + + if (!ce) { + zend_error(E_ERROR, "Couldn't load generated class %s", classname); + } + + free(classname); + EnumDescriptor_FromClassEntry(val, ce); + } +} + +/* + * EnumDescriptor::getValue() + * + * Returns an EnumValueDescriptor for this index. Note: we are not looking + * up by numeric enum value, but by the index in the list of enum values. + */ +PHP_METHOD(EnumDescriptor, getValue) { + EnumDescriptor *intern = (EnumDescriptor*)Z_OBJ_P(getThis()); + zend_long index; + zval ret; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == + FAILURE) { + zend_error(E_USER_ERROR, "Expect integer for index.\n"); + return; + } + + int field_num = upb_enumdef_numvals(intern->enumdef); + if (index < 0 || index >= field_num) { + zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index); + return; + } + + upb_enum_iter iter; + int i; + for(upb_enum_begin(&iter, intern->enumdef), i = 0; + !upb_enum_done(&iter) && i < index; + upb_enum_next(&iter), i++); + + EnumValueDescriptor_Make(&ret, upb_enum_iter_name(&iter), + upb_enum_iter_number(&iter)); + RETURN_ZVAL(&ret, 0, 1); +} + +/* + * EnumDescriptor::getValueCount() + * + * Returns the number of values in this enum. + */ +PHP_METHOD(EnumDescriptor, getValueCount) { + EnumDescriptor *intern = (EnumDescriptor*)Z_OBJ_P(getThis()); + RETURN_LONG(upb_enumdef_numvals(intern->enumdef)); +} + +/* + * EnumDescriptor::getPublicDescriptor() + * + * Returns this EnumDescriptor. Unlike the pure-PHP descriptor, we do not + * have two separate EnumDescriptor classes. We use a single class for both + * the public and private descriptor. + */ +PHP_METHOD(EnumDescriptor, getPublicDescriptor) { + RETURN_ZVAL(getThis(), 1, 0); +} + +static zend_function_entry EnumDescriptor_methods[] = { + PHP_ME(EnumDescriptor, getPublicDescriptor, NULL, ZEND_ACC_PUBLIC) + PHP_ME(EnumDescriptor, getValueCount, NULL, ZEND_ACC_PUBLIC) + PHP_ME(EnumDescriptor, getValue, NULL, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +// ----------------------------------------------------------------------------- +// Oneof +// ----------------------------------------------------------------------------- + +typedef struct { + zend_object std; + const upb_oneofdef *oneofdef; +} OneofDescriptor; + +zend_class_entry *OneofDescriptor_class_entry; +static zend_object_handlers OneofDescriptor_object_handlers; + +static void OneofDescriptor_FromOneofDef(zval *val, const upb_oneofdef *o) { + if (o == NULL) { + ZVAL_NULL(val); + return; + } + + if (!ObjCache_Get(o, val)) { + OneofDescriptor* ret = emalloc(sizeof(OneofDescriptor)); + zend_object_std_init(&ret->std, OneofDescriptor_class_entry); + ret->std.handlers = &OneofDescriptor_object_handlers; + ret->oneofdef = o; + ObjCache_Add(o, &ret->std); + + // Prevent this from ever being collected (within a request). + GC_ADDREF(&ret->std); + + ZVAL_OBJ(val, &ret->std); + } +} + +/* + * OneofDescriptor::getName() + * + * Returns the name of this oneof. + */ +PHP_METHOD(OneofDescriptor, getName) { + OneofDescriptor *intern = (OneofDescriptor*)Z_OBJ_P(getThis()); + RETURN_STRING(upb_oneofdef_name(intern->oneofdef)); +} + +/* + * OneofDescriptor::getField() + * + * Returns a field from this oneof. The given index must be in the range + * [0, getFieldCount() - 1]. + */ +PHP_METHOD(OneofDescriptor, getField) { + OneofDescriptor *intern = (OneofDescriptor*)Z_OBJ_P(getThis()); + zend_long index; + zval ret; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == + FAILURE) { + zend_error(E_USER_ERROR, "Expect integer for index.\n"); + return; + } + + int field_num = upb_oneofdef_numfields(intern->oneofdef); + if (index < 0 || index >= field_num) { + zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index); + return; + } + + upb_oneof_iter iter; + int i; + for(upb_oneof_begin(&iter, intern->oneofdef), i = 0; + !upb_oneof_done(&iter) && i < index; + upb_oneof_next(&iter), i++); + const upb_fielddef *field = upb_oneof_iter_field(&iter); + + FieldDescriptor_FromFieldDef(&ret, field); + RETURN_ZVAL(&ret, 1, 0); +} + +/* + * OneofDescriptor::getFieldCount() + * + * Returns the number of fields in this oneof. + */ +PHP_METHOD(OneofDescriptor, getFieldCount) { + OneofDescriptor *intern = (OneofDescriptor*)Z_OBJ_P(getThis()); + RETURN_LONG(upb_oneofdef_numfields(intern->oneofdef)); +} + +static zend_function_entry OneofDescriptor_methods[] = { + PHP_ME(OneofDescriptor, getName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(OneofDescriptor, getField, NULL, ZEND_ACC_PUBLIC) + PHP_ME(OneofDescriptor, getFieldCount, NULL, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +// ----------------------------------------------------------------------------- +// FieldDescriptor +// ----------------------------------------------------------------------------- + +typedef struct { + zend_object std; + const upb_fielddef *fielddef; +} FieldDescriptor; + +zend_class_entry *FieldDescriptor_class_entry; +static zend_object_handlers FieldDescriptor_object_handlers; + +static void FieldDescriptor_FromFieldDef(zval *val, const upb_fielddef *f) { + if (f == NULL) { + ZVAL_NULL(val); + return; + } + + if (!ObjCache_Get(f, val)) { + FieldDescriptor* ret = emalloc(sizeof(FieldDescriptor)); + zend_object_std_init(&ret->std, FieldDescriptor_class_entry); + ret->std.handlers = &FieldDescriptor_object_handlers; + ret->fielddef = f; + ObjCache_Add(f, &ret->std); + + // Prevent this from ever being collected (within a request). + GC_ADDREF(&ret->std); + + ZVAL_OBJ(val, &ret->std); + } +} + +upb_fieldtype_t to_fieldtype(upb_descriptortype_t type) { + switch (type) { +#define CASE(descriptor_type, type) \ + case UPB_DESCRIPTOR_TYPE_##descriptor_type: \ + return UPB_TYPE_##type; + + CASE(FLOAT, FLOAT); + CASE(DOUBLE, DOUBLE); + CASE(BOOL, BOOL); + CASE(STRING, STRING); + CASE(BYTES, BYTES); + CASE(MESSAGE, MESSAGE); + CASE(GROUP, MESSAGE); + CASE(ENUM, ENUM); + CASE(INT32, INT32); + CASE(INT64, INT64); + CASE(UINT32, UINT32); + CASE(UINT64, UINT64); + CASE(SINT32, INT32); + CASE(SINT64, INT64); + CASE(FIXED32, UINT32); + CASE(FIXED64, UINT64); + CASE(SFIXED32, INT32); + CASE(SFIXED64, INT64); + +#undef CONVERT + + } + + zend_error(E_ERROR, "Unknown field type."); + return 0; +} + +/* + * FieldDescriptor::getName() + * + * Returns the name of this field. + */ +PHP_METHOD(FieldDescriptor, getName) { + FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis()); + RETURN_STRING(upb_fielddef_name(intern->fielddef)); +} + +/* + * FieldDescriptor::getNumber() + * + * Returns the number of this field. + */ +PHP_METHOD(FieldDescriptor, getNumber) { + FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis()); + RETURN_LONG(upb_fielddef_number(intern->fielddef)); +} + +/* + * FieldDescriptor::getLabel() + * + * Returns the label of this field as an integer. + */ +PHP_METHOD(FieldDescriptor, getLabel) { + FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis()); + RETURN_LONG(upb_fielddef_label(intern->fielddef)); +} + +/* + * FieldDescriptor::getType() + * + * Returns the type of this field as an integer. + */ +PHP_METHOD(FieldDescriptor, getType) { + FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis()); + RETURN_LONG(upb_fielddef_descriptortype(intern->fielddef)); +} + +/* + * FieldDescriptor::isMap() + * + * Returns true if this field is a map. + */ +PHP_METHOD(FieldDescriptor, isMap) { + FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis()); + RETURN_BOOL(upb_fielddef_ismap(intern->fielddef)); +} + +/* + * FieldDescriptor::getEnumType() + * + * Returns the EnumDescriptor for this field, which must be an enum. + */ +PHP_METHOD(FieldDescriptor, getEnumType) { + FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis()); + const upb_enumdef *e = upb_fielddef_enumsubdef(intern->fielddef); + zval ret; + + if (!e) { + zend_throw_exception_ex(NULL, 0, + "Cannot get enum type for non-enum field '%s'", + upb_fielddef_name(intern->fielddef)); + return; + } + + EnumDescriptor_FromEnumDef(&ret, e); + RETURN_ZVAL(&ret, 1, 0); +} + +/* + * FieldDescriptor::getMessageType() + * + * Returns the Descriptor for this field, which must be a message. + */ +PHP_METHOD(FieldDescriptor, getMessageType) { + FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis()); + Descriptor* desc = Descriptor_GetFromFieldDef(intern->fielddef); + zval ret; + + if (!desc) { + zend_throw_exception_ex( + NULL, 0, "Cannot get message type for non-message field '%s'", + upb_fielddef_name(intern->fielddef)); + return; + } + + ZVAL_OBJ(&ret, &desc->std); + RETURN_ZVAL(&ret, 1, 0); +} + +static zend_function_entry FieldDescriptor_methods[] = { + PHP_ME(FieldDescriptor, getName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(FieldDescriptor, getNumber, NULL, ZEND_ACC_PUBLIC) + PHP_ME(FieldDescriptor, getLabel, NULL, ZEND_ACC_PUBLIC) + PHP_ME(FieldDescriptor, getType, NULL, ZEND_ACC_PUBLIC) + PHP_ME(FieldDescriptor, isMap, NULL, ZEND_ACC_PUBLIC) + PHP_ME(FieldDescriptor, getEnumType, NULL, ZEND_ACC_PUBLIC) + PHP_ME(FieldDescriptor, getMessageType, NULL, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +// ----------------------------------------------------------------------------- +// Descriptor +// ----------------------------------------------------------------------------- + +zend_class_entry *Descriptor_class_entry; +static zend_object_handlers Descriptor_object_handlers; + +static void Descriptor_destructor(zend_object* obj) { + // We don't really need to do anything here, we don't allow this to be + // collected before the end of the request. +} + +// C Functions from def.h ////////////////////////////////////////////////////// + +// These are documented in the header file. + +void Descriptor_FromClassEntry(zval *val, zend_class_entry *ce) { + if (ce == NULL) { + ZVAL_NULL(val); + return; + } + + if (!ObjCache_Get(ce, val)) { + const upb_msgdef *msgdef = NameMap_GetMessage(ce); + if (!msgdef) { + ZVAL_NULL(val); + return; + } + Descriptor* ret = emalloc(sizeof(Descriptor)); + zend_object_std_init(&ret->std, Descriptor_class_entry); + ret->std.handlers = &Descriptor_object_handlers; + ret->class_entry = ce; + ret->msgdef = msgdef; + ObjCache_Add(ce, &ret->std); + + // Prevent this from ever being collected (within a request). + GC_ADDREF(&ret->std); + + ZVAL_OBJ(val, &ret->std); + } +} + +Descriptor* Descriptor_GetFromClassEntry(zend_class_entry *ce) { + zval desc; + Descriptor_FromClassEntry(&desc, ce); + if (Z_TYPE_P(&desc) == IS_NULL) { + return NULL; + } else { + return (Descriptor*)Z_OBJ_P(&desc); + } +} + +Descriptor* Descriptor_GetFromMessageDef(const upb_msgdef *m) { + if (m) { + if (upb_msgdef_mapentry(m)) { + // A bit of a hack, since map entries don't have classes. + Descriptor* ret = emalloc(sizeof(Descriptor)); + zend_object_std_init(&ret->std, Descriptor_class_entry); + ret->std.handlers = &Descriptor_object_handlers; + ret->class_entry = NULL; + ret->msgdef = m; + + // Prevent this from ever being collected (within a request). + GC_ADDREF(&ret->std); + + return ret; + } + + char *classname = + GetPhpClassname(upb_msgdef_file(m), upb_msgdef_fullname(m)); + zend_string *str = zend_string_init(classname, strlen(classname), 0); + zend_class_entry *ce = zend_lookup_class(str); // May autoload the class. + + zend_string_release (str); + + if (!ce) { + zend_error(E_ERROR, "Couldn't load generated class %s", classname); + } + + free(classname); + return Descriptor_GetFromClassEntry(ce); + } else { + return NULL; + } +} + +Descriptor* Descriptor_GetFromFieldDef(const upb_fielddef *f) { + return Descriptor_GetFromMessageDef(upb_fielddef_msgsubdef(f)); +} + +/* + * Descriptor::getPublicDescriptor() + * + * Returns this EnumDescriptor. Unlike the pure-PHP descriptor, we do not + * have two separate EnumDescriptor classes. We use a single class for both + * the public and private descriptor. + */ +PHP_METHOD(Descriptor, getPublicDescriptor) { + RETURN_ZVAL(getThis(), 1, 0); +} + +/* + * Descriptor::getFullName() + * + * Returns the full name for this message type. + */ +PHP_METHOD(Descriptor, getFullName) { + Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis()); + RETURN_STRING(upb_msgdef_fullname(intern->msgdef)); +} + +/* + * Descriptor::getField() + * + * Returns a FieldDescriptor for the given index, which must be in the range + * [0, getFieldCount()-1]. + */ +PHP_METHOD(Descriptor, getField) { + Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis()); + int count = upb_msgdef_numfields(intern->msgdef); + zval ret; + zend_long index; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == + FAILURE) { + zend_error(E_USER_ERROR, "Expect integer for index.\n"); + return; + } + + if (index < 0 || index >= count) { + zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index); + return; + } + + upb_msg_field_iter iter; + int i; + for(upb_msg_field_begin(&iter, intern->msgdef), i = 0; + !upb_msg_field_done(&iter) && i < index; + upb_msg_field_next(&iter), i++); + const upb_fielddef *field = upb_msg_iter_field(&iter); + + FieldDescriptor_FromFieldDef(&ret, field); + RETURN_ZVAL(&ret, 1, 0); +} + +/* + * Descriptor::getFieldCount() + * + * Returns the number of fields in this message. + */ +PHP_METHOD(Descriptor, getFieldCount) { + Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis()); + RETURN_LONG(upb_msgdef_numfields(intern->msgdef)); +} + +/* + * Descriptor::getOneofDecl() + * + * Returns a OneofDescriptor for the given index, which must be in the range + * [0, getOneofDeclCount()]. + */ +PHP_METHOD(Descriptor, getOneofDecl) { + Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis()); + zend_long index; + zval ret; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == + FAILURE) { + zend_error(E_USER_ERROR, "Expect integer for index.\n"); + return; + } + + int field_num = upb_msgdef_numoneofs(intern->msgdef); + if (index < 0 || index >= field_num) { + zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index); + return; + } + + upb_msg_oneof_iter iter; + int i; + for(upb_msg_oneof_begin(&iter, intern->msgdef), i = 0; + !upb_msg_oneof_done(&iter) && i < index; + upb_msg_oneof_next(&iter), i++); + const upb_oneofdef *oneof = upb_msg_iter_oneof(&iter); + + OneofDescriptor_FromOneofDef(&ret, oneof); + RETURN_ZVAL(&ret, 1, 0); +} + +/* + * Descriptor::getOneofDeclCount() + * + * Returns the number of oneofs in this message. + */ +PHP_METHOD(Descriptor, getOneofDeclCount) { + Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis()); + RETURN_LONG(upb_msgdef_numoneofs(intern->msgdef)); +} + +/* + * Descriptor::getClass() + * + * Returns the name of the PHP class for this message. + */ +PHP_METHOD(Descriptor, getClass) { + Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis()); + const char* classname = ZSTR_VAL(intern->class_entry->name); + RETURN_STRING(classname); +} + + +static zend_function_entry Descriptor_methods[] = { + PHP_ME(Descriptor, getClass, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Descriptor, getFullName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Descriptor, getField, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Descriptor, getFieldCount, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Descriptor, getOneofDecl, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Descriptor, getOneofDeclCount, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Descriptor, getPublicDescriptor, NULL, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +// ----------------------------------------------------------------------------- +// DescriptorPool +// ----------------------------------------------------------------------------- + +typedef struct DescriptorPool { + zend_object std; + upb_symtab *symtab; +} DescriptorPool; + +zend_class_entry *DescriptorPool_class_entry; +static zend_object_handlers DescriptorPool_object_handlers; + +static DescriptorPool *GetPool(const zval* this_ptr) { + return (DescriptorPool*)Z_OBJ_P(this_ptr); +} + +/** + * Object handler to create an DescriptorPool. + */ +static zend_object* DescriptorPool_create(zend_class_entry *class_type) { + DescriptorPool *intern = emalloc(sizeof(DescriptorPool)); + zend_object_std_init(&intern->std, class_type); + intern->std.handlers = &DescriptorPool_object_handlers; + intern->symtab = upb_symtab_new(); + // Skip object_properties_init(), we don't allow derived classes. + return &intern->std; +} + +/** + * Object handler to free an DescriptorPool. + */ +static void DescriptorPool_destructor(zend_object* obj) { + DescriptorPool* intern = (DescriptorPool*)obj; + if (intern->symtab) { + upb_symtab_free(intern->symtab); + } + intern->symtab = NULL; + zend_object_std_dtor(&intern->std); +} + +void DescriptorPool_CreateWithSymbolTable(zval *zv, upb_symtab *symtab) { + ZVAL_OBJ(zv, DescriptorPool_create(DescriptorPool_class_entry)); + + if (symtab) { + DescriptorPool *intern = GetPool(zv); + upb_symtab_free(intern->symtab); + intern->symtab = symtab; + } +} + +upb_symtab *DescriptorPool_Steal(zval *zv) { + DescriptorPool *intern = GetPool(zv); + upb_symtab *ret = intern->symtab; + intern->symtab = NULL; + return ret; +} + +upb_symtab *DescriptorPool_GetSymbolTable() { + DescriptorPool *intern = GetPool(get_generated_pool()); + return intern->symtab; +} + +/* + * DescriptorPool::getGeneratedPool() + * + * Returns the generated DescriptorPool. + */ +PHP_METHOD(DescriptorPool, getGeneratedPool) { + zval ret; + ZVAL_COPY(&ret, get_generated_pool()); + RETURN_ZVAL(&ret, 0, 1); +} + +/* + * DescriptorPool::getDescriptorByClassName() + * + * Returns a Descriptor object for the given PHP class name. + */ +PHP_METHOD(DescriptorPool, getDescriptorByClassName) { + char *classname = NULL; + zend_long classname_len; + zend_class_entry *ce; + zend_string *str; + zval ret; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &classname, + &classname_len) == FAILURE) { + return; + } + + str = zend_string_init(classname, strlen(classname), 0); + ce = zend_lookup_class(str); // May autoload the class. + zend_string_release (str); + + if (!ce) { + RETURN_NULL(); + } + + Descriptor_FromClassEntry(&ret, ce); + RETURN_ZVAL(&ret, 1, 0); +} + +/* + * DescriptorPool::getEnumDescriptorByClassName() + * + * Returns a EnumDescriptor object for the given PHP class name. + */ +PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName) { + char *classname = NULL; + zend_long classname_len; + zend_class_entry *ce; + zend_string *str; + zval ret; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &classname, + &classname_len) == FAILURE) { + return; + } + + str = zend_string_init(classname, strlen(classname), 0); + ce = zend_lookup_class(str); // May autoload the class. + zend_string_release (str); + + if (!ce) { + RETURN_NULL(); + } + + EnumDescriptor_FromClassEntry(&ret, ce); + RETURN_ZVAL(&ret, 1, 0); +} + +/* + * DescriptorPool::getEnumDescriptorByProtoName() + * + * Returns a Descriptor object for the given protobuf message name. + */ +PHP_METHOD(DescriptorPool, getDescriptorByProtoName) { + DescriptorPool *intern = GetPool(getThis()); + char *protoname = NULL; + zend_long protoname_len; + const upb_msgdef *m; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &protoname, + &protoname_len) == FAILURE) { + return; + } + + if (*protoname == '.') protoname++; + + m = upb_symtab_lookupmsg(intern->symtab, protoname); + + if (m) { + zval ret; + ZVAL_OBJ(&ret, &Descriptor_GetFromMessageDef(m)->std); + RETURN_ZVAL(&ret, 1, 0); + } else { + RETURN_NULL(); + } +} + +/* + * depends_on_descriptor() + * + * Returns true if this FileDescriptorProto depends on descriptor.proto. + */ +bool depends_on_descriptor(const google_protobuf_FileDescriptorProto* file) { + const upb_strview *deps; + upb_strview name = upb_strview_makez("google/protobuf/descriptor.proto"); + size_t i, n; + + deps = google_protobuf_FileDescriptorProto_dependency(file, &n); + for (i = 0; i < n; i++) { + if (upb_strview_eql(deps[i], name)) { + return true; + } + } + + return false; +} + +/* + * add_name_mappings() + * + * Adds the messages and enums in this file to the NameMap. + */ +static void add_name_mappings(const upb_filedef *file) { + size_t i; + for (i = 0; i < upb_filedef_msgcount(file); i++) { + NameMap_AddMessage(upb_filedef_msg(file, i)); + } + + for (i = 0; i < upb_filedef_enumcount(file); i++) { + NameMap_AddEnum(upb_filedef_enum(file, i)); + } +} + +/* + * add_name_mappings() + * + * Adds the given descriptor data to this DescriptorPool. + */ +static void add_descriptor(DescriptorPool *pool, const char *data, + int data_len, upb_arena *arena) { + size_t i, n; + google_protobuf_FileDescriptorSet *set; + const google_protobuf_FileDescriptorProto* const* files; + + set = google_protobuf_FileDescriptorSet_parse(data, data_len, arena); + + if (!set) { + zend_error(E_ERROR, "Failed to parse binary descriptor\n"); + return; + } + + files = google_protobuf_FileDescriptorSet_file(set, &n); + + for (i = 0; i < n; i++) { + const google_protobuf_FileDescriptorProto* file = files[i]; + upb_strview name = google_protobuf_FileDescriptorProto_name(file); + upb_status status; + const upb_filedef *file_def; + upb_status_clear(&status); + + if (upb_symtab_lookupfile2(pool->symtab, name.data, name.size)) { + // Already added. + continue; + } + + // The PHP code generator currently special-cases descriptor.proto. It + // doesn't add it as a dependency even if the proto file actually does + // depend on it. + if (depends_on_descriptor(file)) { + google_protobuf_FileDescriptorProto_getmsgdef(pool->symtab); + } + + file_def = upb_symtab_addfile(pool->symtab, file, &status); + CheckUpbStatus(&status, "Unable to load descriptor"); + add_name_mappings(file_def); + } +} + +/* + * DescriptorPool::internalAddGeneratedFile() + * + * Adds the given descriptor data to this DescriptorPool. + */ +PHP_METHOD(DescriptorPool, internalAddGeneratedFile) { + DescriptorPool *intern = GetPool(getThis()); + char *data = NULL; + zend_long data_len; + zend_bool use_nested_submsg = false; + upb_arena *arena; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|b", &data, &data_len, + &use_nested_submsg) != SUCCESS) { + return; + } + + arena = upb_arena_new(); + add_descriptor(intern, data, data_len, arena); + upb_arena_free(arena); +} + +static zend_function_entry DescriptorPool_methods[] = { + PHP_ME(DescriptorPool, getGeneratedPool, NULL, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(DescriptorPool, getDescriptorByClassName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(DescriptorPool, getDescriptorByProtoName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(DescriptorPool, getEnumDescriptorByClassName, NULL, ZEND_ACC_PUBLIC) + PHP_ME(DescriptorPool, internalAddGeneratedFile, NULL, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +// ----------------------------------------------------------------------------- +// GPBType +// ----------------------------------------------------------------------------- + +zend_class_entry* gpb_type_type; + +static zend_function_entry gpb_type_methods[] = { + ZEND_FE_END +}; + +// ----------------------------------------------------------------------------- +// Module Init +// ----------------------------------------------------------------------------- + +void Def_ModuleInit() { + zend_class_entry tmp_ce; + zend_object_handlers *h; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\OneofDescriptor", + OneofDescriptor_methods); + OneofDescriptor_class_entry = zend_register_internal_class(&tmp_ce); + OneofDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL; + OneofDescriptor_class_entry->create_object = CreateHandler_ReturnNull; + h = &OneofDescriptor_object_handlers; + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\EnumValueDescriptor", + EnumValueDescriptor_methods); + EnumValueDescriptor_class_entry = zend_register_internal_class(&tmp_ce); + EnumValueDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL; + EnumValueDescriptor_class_entry->create_object = CreateHandler_ReturnNull; + h = &EnumValueDescriptor_object_handlers; + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\EnumDescriptor", + EnumDescriptor_methods); + EnumDescriptor_class_entry = zend_register_internal_class(&tmp_ce); + EnumDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL; + EnumDescriptor_class_entry->create_object = CreateHandler_ReturnNull; + h = &EnumDescriptor_object_handlers; + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Descriptor", + Descriptor_methods); + + Descriptor_class_entry = zend_register_internal_class(&tmp_ce); + Descriptor_class_entry->ce_flags |= ZEND_ACC_FINAL; + Descriptor_class_entry->create_object = CreateHandler_ReturnNull; + h = &Descriptor_object_handlers; + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + h->dtor_obj = Descriptor_destructor; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\FieldDescriptor", + FieldDescriptor_methods); + FieldDescriptor_class_entry = zend_register_internal_class(&tmp_ce); + FieldDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL; + FieldDescriptor_class_entry->create_object = CreateHandler_ReturnNull; + h = &FieldDescriptor_object_handlers; + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\DescriptorPool", + DescriptorPool_methods); + DescriptorPool_class_entry = zend_register_internal_class(&tmp_ce); + DescriptorPool_class_entry->ce_flags |= ZEND_ACC_FINAL; + DescriptorPool_class_entry->create_object = DescriptorPool_create; + h = &DescriptorPool_object_handlers; + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + h->dtor_obj = DescriptorPool_destructor; + + // GPBType. +#define STR(str) (str), strlen(str) + zend_class_entry class_type; + INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBType", + gpb_type_methods); + gpb_type_type = zend_register_internal_class(&class_type); + zend_declare_class_constant_long(gpb_type_type, STR("DOUBLE"), 1); + zend_declare_class_constant_long(gpb_type_type, STR("FLOAT"), 2); + zend_declare_class_constant_long(gpb_type_type, STR("INT64"), 3); + zend_declare_class_constant_long(gpb_type_type, STR("UINT64"), 4); + zend_declare_class_constant_long(gpb_type_type, STR("INT32"), 5); + zend_declare_class_constant_long(gpb_type_type, STR("FIXED64"), 6); + zend_declare_class_constant_long(gpb_type_type, STR("FIXED32"), 7); + zend_declare_class_constant_long(gpb_type_type, STR("BOOL"), 8); + zend_declare_class_constant_long(gpb_type_type, STR("STRING"), 9); + zend_declare_class_constant_long(gpb_type_type, STR("GROUP"), 10); + zend_declare_class_constant_long(gpb_type_type, STR("MESSAGE"), 11); + zend_declare_class_constant_long(gpb_type_type, STR("BYTES"), 12); + zend_declare_class_constant_long(gpb_type_type, STR("UINT32"), 13); + zend_declare_class_constant_long(gpb_type_type, STR("ENUM"), 14); + zend_declare_class_constant_long(gpb_type_type, STR("SFIXED32"), 15); + zend_declare_class_constant_long(gpb_type_type, STR("SFIXED64"), 16); + zend_declare_class_constant_long(gpb_type_type, STR("SINT32"), 17); + zend_declare_class_constant_long(gpb_type_type, STR("SINT64"), 18); +#undef STR +} diff --git a/php/ext/google/protobuf2/def.h b/php/ext/google/protobuf2/def.h new file mode 100644 index 0000000000..515a83eca7 --- /dev/null +++ b/php/ext/google/protobuf2/def.h @@ -0,0 +1,69 @@ +// 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 PHP_PROTOBUF_DEF_H_ +#define PHP_PROTOBUF_DEF_H_ + +#include + +#include "php-upb.h" + +// Initializes the Def module, which defines all of the descriptor classes. +void Def_ModuleInit(); + +// Creates a new DescriptorPool to wrap the given symtab. The DescriptorPool +// takes ownership of the given symtab. If symtab is NULL, the DescriptorPool +// will create an empty symtab instead. +void DescriptorPool_CreateWithSymbolTable(zval *zv, upb_symtab *symtab); + +// Given a zval representing a DescriptorPool, steals and returns its symtab, +// which is now owned by the caller. +upb_symtab *DescriptorPool_Steal(zval *zv); + +upb_symtab *DescriptorPool_GetSymbolTable(); + +typedef struct Descriptor { + zend_object std; + const upb_msgdef *msgdef; + zend_class_entry *class_entry; +} Descriptor; + +// Gets or creates a PHP Descriptor object for a |ce| and stores it in |val|. +// If this is not a protobuf generated class, |val| will be set to null. +void Descriptor_FromClassEntry(zval *val, zend_class_entry *ce); + +// Gets or creates a Descriptor* for the given class entry, upb_msgdef, or +// upb_fielddef. The returned Descriptor* will live for the entire request, +// so no ref is necessary to keep it alive. +Descriptor* Descriptor_GetFromClassEntry(zend_class_entry *ce); +Descriptor* Descriptor_GetFromMessageDef(const upb_msgdef *m); +Descriptor* Descriptor_GetFromFieldDef(const upb_fielddef *f); + +#endif // PHP_PROTOBUF_DEF_H_ diff --git a/php/ext/google/protobuf2/make-preload.php b/php/ext/google/protobuf2/make-preload.php new file mode 100644 index 0000000000..c6043e2891 --- /dev/null +++ b/php/ext/google/protobuf2/make-preload.php @@ -0,0 +1,62 @@ + Google\\Protobuf\\BoolValue + $ret = stripSuffix($filename, ".php"); + return str_replace("/", "\\\\", $ret); +} + +function toCSymbolName($filename) { + # Google/Protobuf/BoolValue.php -> Google__Protobuf__BoolValue + $ret = stripSuffix($filename, ".php"); + return str_replace("/", "__", $ret); +} + +$f = fopen($output, "w"); + +fwrite($f, "#include \"bundled_php.h\"\n"); +fwrite($f, "#include \"stdlib.h\"\n"); + +foreach ($filenames as $filename) { + print("Reading $filename...\n"); + $contents = file_get_contents($filename); + $contents = substr($contents, 5); // Strip diff --git a/php/ext/google/protobuf2/map.c b/php/ext/google/protobuf2/map.c new file mode 100644 index 0000000000..0217c6491e --- /dev/null +++ b/php/ext/google/protobuf2/map.c @@ -0,0 +1,590 @@ +// 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. + +#include "map.h" + +#include +#include + +#include + +#include "arena.h" +#include "convert.h" +#include "php-upb.h" +#include "protobuf.h" + +static void MapFieldIter_make(zval *val, zval *map_field); + +// ----------------------------------------------------------------------------- +// MapField +// ----------------------------------------------------------------------------- + +typedef struct { + zend_object std; + zval arena; + upb_map *map; + upb_fieldtype_t key_type; + upb_fieldtype_t val_type; + const Descriptor* desc; // When values are messages. +} MapField; + +zend_class_entry *MapField_class_entry; +static zend_object_handlers MapField_object_handlers; + +// PHP Object Handlers ///////////////////////////////////////////////////////// + +/** + * MapField_create() + * + * PHP class entry function to allocate and initialize a new MapField + * object. + */ +static zend_object* MapField_create(zend_class_entry *class_type) { + MapField *intern = emalloc(sizeof(MapField)); + zend_object_std_init(&intern->std, class_type); + intern->std.handlers = &MapField_object_handlers; + Arena_Init(&intern->arena); + intern->map = NULL; + // Skip object_properties_init(), we don't allow derived classes. + return &intern->std; +} + +/** + * MapField_dtor() + * + * Object handler to destroy a MapField. This releases all resources + * associated with the message. Note that it is possible to access a destroyed + * object from PHP in rare cases. + */ +static void MapField_destructor(zend_object* obj) { + MapField* intern = (MapField*)obj; + ObjCache_Delete(intern->map); + zval_ptr_dtor(&intern->arena); + zend_object_std_dtor(&intern->std); +} + +static zval *Map_GetPropertyPtrPtr(zval *object, zval *member, int type, + void **cache_slot) { + return NULL; // We don't offer direct references to our properties. +} + +static HashTable *map_get_properties(zval *object TSRMLS_DC) { + return NULL; // We do not have a properties table. +} + +// C Functions from map.h ////////////////////////////////////////////////////// + +// These are documented in the header file. + +void MapField_GetPhpWrapper(zval *val, upb_map *map, const upb_fielddef *f, + zval *arena) { + if (!map) { + ZVAL_NULL(val); + return; + } + + if (!ObjCache_Get(map, val)) { + const upb_msgdef *ent = upb_fielddef_msgsubdef(f); + const upb_fielddef *key_f = upb_msgdef_itof(ent, 1); + const upb_fielddef *val_f = upb_msgdef_itof(ent, 2); + MapField *intern = emalloc(sizeof(MapField)); + zend_object_std_init(&intern->std, MapField_class_entry); + intern->std.handlers = &MapField_object_handlers; + ZVAL_COPY(&intern->arena, arena); + intern->map = map; + intern->key_type = upb_fielddef_type(key_f); + intern->val_type = upb_fielddef_type(val_f); + intern->desc = Descriptor_GetFromFieldDef(val_f); + // Skip object_properties_init(), we don't allow derived classes. + ObjCache_Add(intern->map, &intern->std); + ZVAL_OBJ(val, &intern->std); + } +} + +upb_map *MapField_GetUpbMap(zval *val, const upb_fielddef *f, upb_arena *arena) { + const upb_msgdef *ent = upb_fielddef_msgsubdef(f); + const upb_fielddef *key_f = upb_msgdef_itof(ent, 1); + const upb_fielddef *val_f = upb_msgdef_itof(ent, 2); + upb_fieldtype_t key_type = upb_fielddef_type(key_f); + upb_fieldtype_t val_type = upb_fielddef_type(val_f); + const Descriptor *desc = Descriptor_GetFromFieldDef(val_f); + + if (Z_ISREF_P(val)) { + ZVAL_DEREF(val); + } + + if (Z_TYPE_P(val) == IS_ARRAY) { + upb_map *map = upb_map_new(arena, key_type, val_type); + HashTable *table = HASH_OF(val); + HashPosition pos; + + zend_hash_internal_pointer_reset_ex(table, &pos); + + while (true) { + zval php_key; + zval *php_val; + upb_msgval upb_key; + upb_msgval upb_val; + + zend_hash_get_current_key_zval_ex(table, &php_key, &pos); + php_val = zend_hash_get_current_data_ex(table, &pos); + + if (!php_val) return map; + + if (!Convert_PhpToUpb(&php_key, &upb_key, key_type, NULL, arena) || + !Convert_PhpToUpbAutoWrap(php_val, &upb_val, val_type, desc, arena)) { + return NULL; + } + + upb_map_set(map, upb_key, upb_val, arena); + zend_hash_move_forward_ex(table, &pos); + zval_dtor(&php_key); + } + } else if (Z_TYPE_P(val) == IS_OBJECT && + Z_OBJCE_P(val) == MapField_class_entry) { + MapField *intern = (MapField*)Z_OBJ_P(val); + + if (intern->key_type != key_type || intern->val_type != val_type || + intern->desc != desc) { + php_error_docref(NULL, E_USER_ERROR, "Wrong type for this map field."); + return NULL; + } + + upb_arena_fuse(arena, Arena_Get(&intern->arena)); + return intern->map; + } else { + php_error_docref(NULL, E_USER_ERROR, "Must be a map"); + return NULL; + } +} + +// MapField PHP methods //////////////////////////////////////////////////////// + +/** + * MapField::__construct() + * + * Constructs an instance of MapField. + * @param long Key type. + * @param long Value type. + * @param string Message/Enum class (message/enum value types only). + */ +PHP_METHOD(MapField, __construct) { + MapField *intern = (MapField*)Z_OBJ_P(getThis()); + upb_arena *arena = Arena_Get(&intern->arena); + zend_long key_type, val_type; + zend_class_entry* klass = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll|C", &key_type, &val_type, + &klass) != SUCCESS) { + return; + } + + intern->key_type = pbphp_dtype_to_type(key_type); + intern->val_type = pbphp_dtype_to_type(val_type); + intern->desc = Descriptor_GetFromClassEntry(klass); + + // Check that the key type is an allowed type. + switch (intern->key_type) { + case UPB_TYPE_INT32: + case UPB_TYPE_INT64: + case UPB_TYPE_UINT32: + case UPB_TYPE_UINT64: + case UPB_TYPE_BOOL: + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: + // These are OK. + break; + default: + zend_error(E_USER_ERROR, "Invalid key type for map."); + } + + if (intern->val_type == UPB_TYPE_MESSAGE && klass == NULL) { + php_error_docref(NULL, E_USER_ERROR, + "Message/enum type must have concrete class."); + return; + } + + intern->map = upb_map_new(arena, intern->key_type, intern->val_type); + ObjCache_Add(intern->map, &intern->std); +} + +/** + * MapField::offsetExists() + * + * Implements the ArrayAccess interface. Invoked when PHP code calls: + * + * isset($map[$idx]); + * empty($map[$idx]); + * + * @param long The index to be checked. + * @return bool True if the element at the given index exists. + */ +PHP_METHOD(MapField, offsetExists) { + MapField *intern = (MapField*)Z_OBJ_P(getThis()); + zval *key; + upb_msgval upb_key; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS || + !Convert_PhpToUpb(key, &upb_key, intern->key_type, intern->desc, NULL)) { + return; + } + + RETURN_BOOL(upb_map_get(intern->map, upb_key, NULL)); +} + +/** + * MapField::offsetGet() + * + * Implements the ArrayAccess interface. Invoked when PHP code calls: + * + * $x = $map[$idx]; + * + * @param long The index of the element to be fetched. + * @return object The stored element at given index. + * @exception Invalid type for index. + * @exception Non-existing index. + */ +PHP_METHOD(MapField, offsetGet) { + MapField *intern = (MapField*)Z_OBJ_P(getThis()); + zval *key; + zval ret; + upb_msgval upb_key, upb_val; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS || + !Convert_PhpToUpb(key, &upb_key, intern->key_type, intern->desc, NULL)) { + return; + } + + if (!upb_map_get(intern->map, upb_key, &upb_val)) { + zend_error(E_USER_ERROR, "Given key doesn't exist."); + return; + } + + Convert_UpbToPhp(upb_val, &ret, intern->val_type, intern->desc, &intern->arena); + RETURN_ZVAL(&ret, 0, 1); +} + +/** + * MapField::offsetSet() + * + * Implements the ArrayAccess interface. Invoked when PHP code calls: + * + * $map[$idx] = $x; + * + * @param long The index of the element to be assigned. + * @param object The element to be assigned. + * @exception Invalid type for index. + * @exception Non-existing index. + * @exception Incorrect type of the element. + */ +PHP_METHOD(MapField, offsetSet) { + MapField *intern = (MapField*)Z_OBJ_P(getThis()); + upb_arena *arena = Arena_Get(&intern->arena); + zval *key, *val; + upb_msgval upb_key, upb_val; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &key, &val) != SUCCESS || + !Convert_PhpToUpb(key, &upb_key, intern->key_type, NULL, NULL) || + !Convert_PhpToUpb(val, &upb_val, intern->val_type, intern->desc, arena)) { + return; + } + + upb_map_set(intern->map, upb_key, upb_val, arena); +} + +/** + * MapField::offsetUnset() + * + * Implements the ArrayAccess interface. Invoked when PHP code calls: + * + * unset($map[$idx]); + * + * @param long The index of the element to be removed. + * @exception Invalid type for index. + * @exception The element to be removed is not at the end of the MapField. + */ +PHP_METHOD(MapField, offsetUnset) { + MapField *intern = (MapField*)Z_OBJ_P(getThis()); + zval *key; + upb_msgval upb_key; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &key) != SUCCESS || + !Convert_PhpToUpb(key, &upb_key, intern->key_type, NULL, NULL)) { + return; + } + + upb_map_delete(intern->map, upb_key); +} + +/** + * MapField::count() + * + * Implements the Countable interface. Invoked when PHP code calls: + * + * $len = count($map); + * Return the number of stored elements. + * This will also be called for: count($map) + * @return long The number of stored elements. + */ +PHP_METHOD(MapField, count) { + MapField *intern = (MapField*)Z_OBJ_P(getThis()); + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + RETURN_LONG(upb_map_size(intern->map)); +} + +/** + * MapField::getIterator() + * + * Implements the IteratorAggregate interface. Invoked when PHP code calls: + * + * foreach ($arr) {} + * + * @return object Beginning iterator. + */ +PHP_METHOD(MapField, getIterator) { + zval ret; + MapFieldIter_make(&ret, getThis()); + RETURN_ZVAL(&ret, 0, 1); +} + +ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1) + ZEND_ARG_INFO(0, index) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetSet, 0, 0, 2) + ZEND_ARG_INFO(0, index) + ZEND_ARG_INFO(0, newval) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_void, 0) +ZEND_END_ARG_INFO() + +static zend_function_entry MapField_methods[] = { + PHP_ME(MapField, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(MapField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC) + PHP_ME(MapField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC) + PHP_ME(MapField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC) + PHP_ME(MapField, offsetUnset, arginfo_offsetGet, ZEND_ACC_PUBLIC) + PHP_ME(MapField, count, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(MapField, getIterator, arginfo_void, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +// ----------------------------------------------------------------------------- +// MapFieldIter +// ----------------------------------------------------------------------------- + +typedef struct { + zend_object std; + zval map_field; + size_t position; +} MapFieldIter; + +zend_class_entry *MapFieldIter_class_entry; +static zend_object_handlers MapFieldIter_object_handlers; + +/** + * MapFieldIter_create() + * + * PHP class entry function to allocate and initialize a new MapFieldIter + * object. + */ +zend_object* MapFieldIter_create(zend_class_entry *class_type) { + MapFieldIter *intern = emalloc(sizeof(MapFieldIter)); + zend_object_std_init(&intern->std, class_type); + intern->std.handlers = &MapFieldIter_object_handlers; + ZVAL_NULL(&intern->map_field); + intern->position = 0; + // Skip object_properties_init(), we don't allow derived classes. + return &intern->std; +} + +/** + * MapFieldIter_dtor() + * + * Object handler to destroy a MapFieldIter. This releases all resources + * associated with the message. Note that it is possible to access a destroyed + * object from PHP in rare cases. + */ +static void map_field_iter_dtor(zend_object* obj) { + MapFieldIter* intern = (MapFieldIter*)obj; + zval_ptr_dtor(&intern->map_field); + zend_object_std_dtor(&intern->std); +} + +/** + * MapFieldIter_make() + * + * Function to create a MapFieldIter directly from C. + */ +static void MapFieldIter_make(zval *val, zval *map_field) { + MapFieldIter *iter; + ZVAL_OBJ(val, + MapFieldIter_class_entry->create_object(MapFieldIter_class_entry)); + iter = (MapFieldIter*)Z_OBJ_P(val); + ZVAL_COPY(&iter->map_field, map_field); +} + +// ----------------------------------------------------------------------------- +// PHP MapFieldIter Methods +// ----------------------------------------------------------------------------- + +/* + * When a user writes: + * + * foreach($arr as $key => $val) {} + * + * PHP translates this into: + * + * $iter = $arr->getIterator(); + * for ($iter->rewind(); $iter->valid(); $iter->next()) { + * $key = $iter->key(); + * $val = $iter->current(); + * } + */ + +/** + * MapFieldIter::rewind() + * + * Implements the Iterator interface. Sets the iterator to the first element. + */ +PHP_METHOD(MapFieldIter, rewind) { + MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis()); + MapField *map_field = (MapField*)Z_OBJ_P(&intern->map_field); + intern->position = UPB_MAP_BEGIN; + upb_mapiter_next(map_field->map, &intern->position); +} + +/** + * MapFieldIter::current() + * + * Implements the Iterator interface. Returns the current value. + */ +PHP_METHOD(MapFieldIter, current) { + MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis()); + MapField *field = (MapField*)Z_OBJ_P(&intern->map_field); + upb_msgval upb_val = upb_mapiter_value(field->map, intern->position); + zval ret; + Convert_UpbToPhp(upb_val, &ret, field->val_type, field->desc, &field->arena); + RETURN_ZVAL(&ret, 0, 1); +} + +/** + * MapFieldIter::key() + * + * Implements the Iterator interface. Returns the current key. + */ +PHP_METHOD(MapFieldIter, key) { + MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis()); + MapField *field = (MapField*)Z_OBJ_P(&intern->map_field); + upb_msgval upb_key = upb_mapiter_key(field->map, intern->position); + zval ret; + Convert_UpbToPhp(upb_key, &ret, field->key_type, NULL, NULL); + RETURN_ZVAL(&ret, 0, 1); +} + +/** + * MapFieldIter::next() + * + * Implements the Iterator interface. Advances to the next element. + */ +PHP_METHOD(MapFieldIter, next) { + MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis()); + MapField *field = (MapField*)Z_OBJ_P(&intern->map_field); + upb_mapiter_next(field->map, &intern->position); +} + +/** + * MapFieldIter::valid() + * + * Implements the Iterator interface. Returns true if this is a valid element. + */ +PHP_METHOD(MapFieldIter, valid) { + MapFieldIter *intern = (MapFieldIter*)Z_OBJ_P(getThis()); + MapField *field = (MapField*)Z_OBJ_P(&intern->map_field); + bool done = upb_mapiter_done(field->map, intern->position); + RETURN_BOOL(!done); +} + +static zend_function_entry map_field_iter_methods[] = { + PHP_ME(MapFieldIter, rewind, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(MapFieldIter, current, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(MapFieldIter, key, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(MapFieldIter, next, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(MapFieldIter, valid, arginfo_void, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +// ----------------------------------------------------------------------------- +// Module init. +// ----------------------------------------------------------------------------- + +/** + * Map_ModuleInit() + * + * Called when the C extension is loaded to register all types. + */ + +void Map_ModuleInit() { + zend_class_entry tmp_ce; + zend_object_handlers *h; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\MapField", + MapField_methods); + + MapField_class_entry = zend_register_internal_class(&tmp_ce); + zend_class_implements(MapField_class_entry, 3, spl_ce_ArrayAccess, + zend_ce_aggregate, spl_ce_Countable); + MapField_class_entry->ce_flags |= ZEND_ACC_FINAL; + MapField_class_entry->create_object = MapField_create; + + h = &MapField_object_handlers; + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + h->dtor_obj = MapField_destructor; + h->get_properties = map_get_properties; + h->get_property_ptr_ptr = Map_GetPropertyPtrPtr; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\MapFieldIter", + map_field_iter_methods); + + MapFieldIter_class_entry = zend_register_internal_class(&tmp_ce); + zend_class_implements(MapFieldIter_class_entry, 1, zend_ce_iterator); + MapFieldIter_class_entry->ce_flags |= ZEND_ACC_FINAL; + MapFieldIter_class_entry->ce_flags |= ZEND_ACC_FINAL; + MapFieldIter_class_entry->create_object = MapFieldIter_create; + + h = &MapFieldIter_object_handlers; + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + h->dtor_obj = map_field_iter_dtor; +} diff --git a/php/ext/google/protobuf2/map.h b/php/ext/google/protobuf2/map.h new file mode 100644 index 0000000000..9b3c9c144c --- /dev/null +++ b/php/ext/google/protobuf2/map.h @@ -0,0 +1,60 @@ +// 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 PHP_PROTOBUF_MAP_H_ +#define PHP_PROTOBUF_MAP_H_ + +#include + +#include "php-upb.h" + +void Map_ModuleInit(); + +// Gets a upb_map* for the PHP object |val|: +// * If |val| is a RepeatedField object, we first check its type and verify +// that that the elements have the correct type for |f|. If so, we return the +// wrapped upb_map*. We also make sure that this map's arena is fused to +// |arena|, so the returned upb_map is guaranteed to live as long as +// |arena|. +// * If |val| is a PHP Map, we attempt to create a new upb_map using +// |arena| and add all of the PHP elements to it. +// +// If an error occurs, we raise a PHP error and return NULL. +upb_map *MapField_GetUpbMap(zval *val, const upb_fielddef *f, upb_arena *arena); + +// Creates a PHP MapField object for the given upb_map* and |f| and returns it +// in |val|. The PHP object will keep a reference to this |arena| to ensure the +// underlying array data stays alive. +// +// If |map| is NULL, this will return a PHP null object. +void MapField_GetPhpWrapper(zval *val, upb_map *arr, const upb_fielddef *f, + zval *arena); + +#endif // PHP_PROTOBUF_MAP_H_ diff --git a/php/ext/google/protobuf2/message.c b/php/ext/google/protobuf2/message.c new file mode 100644 index 0000000000..20dd37a76e --- /dev/null +++ b/php/ext/google/protobuf2/message.c @@ -0,0 +1,841 @@ +// 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 "message.h" + +#include +#include +#include + +// This is not self-contained: it must be after other Zend includes. +#include + +#include "arena.h" +#include "array.h" +#include "convert.h" +#include "def.h" +#include "map.h" +#include "php-upb.h" +#include "protobuf.h" + +// ----------------------------------------------------------------------------- +// Message +// ----------------------------------------------------------------------------- + +typedef struct { + zend_object std; + zval arena; + const Descriptor* desc; + upb_msg *msg; +} Message; + +zend_class_entry *message_ce; +static zend_object_handlers message_object_handlers; + +// PHP Object Handlers ///////////////////////////////////////////////////////// + +/** + * Message_create() + * + * PHP class entry function to allocate and initialize a new Message object. + */ +static zend_object* Message_create(zend_class_entry *class_type) { + Message *intern = emalloc(sizeof(Message)); + // XXX(haberman): verify whether we actually want to take this route. + class_type->default_properties_count = 0; + zend_object_std_init(&intern->std, class_type); + intern->std.handlers = &message_object_handlers; + Arena_Init(&intern->arena); + return &intern->std; +} + +/** + * Message_dtor() + * + * Object handler to destroy a Message. This releases all resources associated + * with the message. Note that it is possible to access a destroyed object from + * PHP in rare cases. + */ +static void Message_dtor(zend_object* obj) { + Message* intern = (Message*)obj; + ObjCache_Delete(intern->msg); + zval_dtor(&intern->arena); + zend_object_std_dtor(&intern->std); +} + +/** + * get_field() + * + * Helper function to look up a field given a member name (as a string). + */ +static const upb_fielddef *get_field(Message *msg, zval *member) { + const upb_msgdef *m = msg->desc->msgdef; + const upb_fielddef *f = + upb_msgdef_ntof(m, Z_STRVAL_P(member), Z_STRLEN_P(member)); + + if (!f) { + zend_throw_exception_ex(NULL, 0, "No such property %s.", + ZSTR_VAL(msg->desc->class_entry->name)); + } + + return f; +} + +/** + * Message_read_property() + * + * Object handler for reading a property in PHP. Called when PHP code does: + * + * $x = $message->foobar; + * + * Note that all properties of generated messages are private, so this should + * only be possible to invoke from generated code, which has accessors like: + * + * public function getOptionalInt32() + * { + * return $this->optional_int32; + * } + * + * We lookup the field and return the scalar, RepeatedField, or MapField for + * this field. + */ +static zval *Message_read_property(zval *obj, zval *member, int type, + void **cache_slot, zval *rv) { + Message* intern = (Message*)Z_OBJ_P(obj); + const upb_fielddef *f = get_field(intern, member); + upb_arena *arena = Arena_Get(&intern->arena); + + if (!f) return NULL; + + if (upb_fielddef_ismap(f)) { + upb_mutmsgval msgval = upb_msg_mutable(intern->msg, f, arena); + MapField_GetPhpWrapper(rv, msgval.map, f, &intern->arena); + } else if (upb_fielddef_isseq(f)) { + upb_mutmsgval msgval = upb_msg_mutable(intern->msg, f, arena); + RepeatedField_GetPhpWrapper(rv, msgval.array, f, &intern->arena); + } else { + upb_msgval msgval = upb_msg_get(intern->msg, f); + const Descriptor *subdesc = Descriptor_GetFromFieldDef(f); + Convert_UpbToPhp(msgval, rv, upb_fielddef_type(f), subdesc, &intern->arena); + } + + return rv; +} + +/** + * Message_write_property() + * + * Object handler for writing a property in PHP. Called when PHP code does: + * + * $message->foobar = $x; + * + * Note that all properties of generated messages are private, so this should + * only be possible to invoke from generated code, which has accessors like: + * + * public function setOptionalInt32($var) + * { + * GPBUtil::checkInt32($var); + * $this->optional_int32 = $var; + * + * return $this; + * } + * + * The C extension version of checkInt32() doesn't actually check anything, so + * we perform all checking and conversion in this function. + */ +static void Message_write_property(zval *obj, zval *member, zval *val, + void **cache_slot) { + Message* intern = (Message*)Z_OBJ_P(obj); + const upb_fielddef *f = get_field(intern, member); + upb_arena *arena = Arena_Get(&intern->arena); + upb_msgval msgval; + + if (!f) return; + + if (upb_fielddef_ismap(f)) { + msgval.map_val = MapField_GetUpbMap(val, f, arena); + if (!msgval.map_val) return; + } else if (upb_fielddef_isseq(f)) { + msgval.array_val = RepeatedField_GetUpbArray(val, f, arena); + if (!msgval.array_val) return; + } else { + upb_fieldtype_t type = upb_fielddef_type(f); + const Descriptor *subdesc = Descriptor_GetFromFieldDef(f); + bool ok = Convert_PhpToUpb(val, &msgval, type, subdesc, arena); + if (!ok) return; + } + + upb_msg_set(intern->msg, f, msgval, arena); +} + +/** + * Message_get_property_ptr_ptr() + * + * Object handler for the get_property_ptr_ptr event in PHP. This returns a + * reference to our internal properties. We don't support this, so we return + * NULL. + */ +static zval *Message_get_property_ptr_ptr(zval *object, zval *member, int type, + void **cache_slot) { + return NULL; // We do not have a properties table. +} + +/** + * Message_get_properties() + * + * Object handler for the get_properties event in PHP. This returns a HashTable + * of our internal properties. We don't support this, so we return NULL. + */ +static HashTable* Message_get_properties(zval* object TSRMLS_DC) { + return NULL; // We don't offer direct references to our properties. +} + +// C Functions from message.h. ///////////////////////////////////////////////// + +// These are documented in the header file. + +void Message_GetPhpWrapper(zval *val, const Descriptor *desc, upb_msg *msg, + zval *arena) { + if (!msg) { + ZVAL_NULL(val); + return; + } + + if (!ObjCache_Get(msg, val)) { + Message *intern = emalloc(sizeof(Message)); + // XXX(haberman): verify whether we actually want to take this route. + desc->class_entry->default_properties_count = 0; + zend_object_std_init(&intern->std, desc->class_entry); + intern->std.handlers = &message_object_handlers; + ZVAL_COPY(&intern->arena, arena); + intern->desc = desc; + intern->msg = msg; + ZVAL_OBJ(val, &intern->std); + ObjCache_Add(intern->msg, &intern->std); + } +} + +bool Message_GetUpbMessage(zval *val, const Descriptor *desc, upb_arena *arena, + upb_msg **msg) { + PBPHP_ASSERT(desc); + + if (Z_ISREF_P(val)) { + ZVAL_DEREF(val); + } + + if (Z_TYPE_P(val) == IS_NULL) { + *msg = NULL; + return true; + } + + if (Z_TYPE_P(val) == IS_OBJECT && + instanceof_function(Z_OBJCE_P(val), desc->class_entry)) { + Message *intern = (Message*)Z_OBJ_P(val); + upb_arena_fuse(arena, Arena_Get(&intern->arena)); + *msg = intern->msg; + return true; + } else { + zend_throw_exception_ex(NULL, 0, "Given value is not an instance of %s.", + ZSTR_VAL(desc->class_entry->name)); + return false; + } +} + +// Message PHP methods ///////////////////////////////////////////////////////// + +/** + * Message_InitFromPhp() + * + * Helper method to handle the initialization of a message from a PHP value, eg. + * + * $m = new TestMessage([ + * 'optional_int32' => -42, + * 'optional_bool' => true, + * 'optional_string' => 'a', + * 'optional_enum' => TestEnum::ONE, + * 'optional_message' => new Sub([ + * 'a' => 33 + * ]), + * 'repeated_int32' => [-42, -52], + * 'repeated_enum' => [TestEnum::ZERO, TestEnum::ONE], + * 'repeated_message' => [new Sub(['a' => 34]), + * new Sub(['a' => 35])], + * 'map_int32_int32' => [-62 => -62], + * 'map_int32_enum' => [1 => TestEnum::ONE], + * 'map_int32_message' => [1 => new Sub(['a' => 36])], + * ]); + * + * The initializer must be an array. + */ +bool Message_InitFromPhp(upb_msg *msg, const upb_msgdef *m, zval *init, + upb_arena *arena) { + HashTable* table = HASH_OF(init); + HashPosition pos; + + if (Z_ISREF_P(init)) { + ZVAL_DEREF(init); + } + + if (Z_TYPE_P(init) != IS_ARRAY) { + zend_throw_exception_ex(NULL, 0, + "Initializer for a message %s must be an array.", + upb_msgdef_fullname(m)); + return false; + } + + zend_hash_internal_pointer_reset_ex(table, &pos); + + while (true) { // Iterate over key/value pairs. + zval key; + zval *val; + const upb_fielddef *f; + upb_msgval msgval; + + zend_hash_get_current_key_zval_ex(table, &key, &pos); + val = zend_hash_get_current_data_ex(table, &pos); + + if (!val) return true; // Finished iteration. + + if (Z_ISREF_P(val)) { + ZVAL_DEREF(val); + } + + f = upb_msgdef_ntof(m, Z_STRVAL_P(&key), Z_STRLEN_P(&key)); + + if (!f) { + zend_throw_exception_ex(NULL, 0, + "No such field %s", Z_STRVAL_P(&key)); + return false; + } + + if (upb_fielddef_ismap(f)) { + msgval.map_val = MapField_GetUpbMap(val, f, arena); + if (!msgval.map_val) return false; + } else if (upb_fielddef_isseq(f)) { + msgval.array_val = RepeatedField_GetUpbArray(val, f, arena); + if (!msgval.array_val) return false; + } else { + const Descriptor *desc = Descriptor_GetFromFieldDef(f); + upb_fieldtype_t type = upb_fielddef_type(f); + if (!Convert_PhpToUpbAutoWrap(val, &msgval, type, desc, arena)) { + return false; + } + } + + upb_msg_set(msg, f, msgval, arena); + zend_hash_move_forward_ex(table, &pos); + zval_dtor(&key); + } +} + +/** + * Message::__construct() + * + * Constructor for Message. + * @param array Map of initial values ['k' = val] + */ +PHP_METHOD(Message, __construct) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const Descriptor* desc = Descriptor_GetFromClassEntry(Z_OBJCE_P(getThis())); + const upb_msgdef *msgdef = desc->msgdef; + upb_arena *arena = Arena_Get(&intern->arena); + zval *init_arr = NULL; + + intern->desc = desc; + intern->msg = upb_msg_new(msgdef, arena); + ObjCache_Add(intern->msg, &intern->std); + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|a!", &init_arr) == FAILURE) { + return; + } + + if (init_arr) { + Message_InitFromPhp(intern->msg, desc->msgdef, init_arr, arena); + } +} + +/** + * Message::discardUnknownFields() + * + * Discards any unknown fields for this message or any submessages. + */ +PHP_METHOD(Message, discardUnknownFields) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + upb_msg_discardunknown(intern->msg, intern->desc->msgdef, 64); +} + +/** + * Message::clear() + * + * Clears all fields of this message. + */ +PHP_METHOD(Message, clear) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + upb_msg_clear(intern->msg, intern->desc->msgdef); +} + +/** + * Message::mergeFrom() + * + * Merges from the given message, which must be of the same class as us. + * @param object Message to merge from. + */ +PHP_METHOD(Message, mergeFrom) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + Message* from; + upb_arena *arena = Arena_Get(&intern->arena); + const upb_msglayout *l = upb_msgdef_layout(intern->desc->msgdef); + zval* value; + char *pb; + size_t size; + bool ok; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &value, + intern->desc->class_entry) == FAILURE) { + return; + } + + from = (Message*)Z_OBJ_P(value); + + // Should be guaranteed since we passed the class type to + // zend_parse_parameters(). + PBPHP_ASSERT(from->desc == intern->desc); + + // TODO(haberman): use a temp arena for this once we can make upb_decode() + // copy strings. + pb = upb_encode(from->msg, l, arena, &size); + + if (!pb) { + zend_throw_exception_ex(NULL, 0, "Max nesting exceeded"); + return; + } + + ok = upb_decode(pb, size, intern->msg, l, arena); + PBPHP_ASSERT(ok); +} + +/** + * Message::mergeFromString() + * + * Merges from the given string. + * @param string Binary protobuf data to merge. + */ +PHP_METHOD(Message, mergeFromString) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + char *data = NULL; + char *data_copy = NULL; + zend_long data_len; + const upb_msglayout *l = upb_msgdef_layout(intern->desc->msgdef); + upb_arena *arena = Arena_Get(&intern->arena); + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &data, &data_len) == + FAILURE) { + return; + } + + // TODO(haberman): avoid this copy when we can make the decoder copy. + data_copy = upb_arena_malloc(arena, data_len); + memcpy(data_copy, data, data_len); + + if (!upb_decode(data_copy, data_len, intern->msg, l, arena)) { + zend_throw_exception_ex(NULL, 0, "Error occurred during parsing"); + return; + } +} + +/** + * Message::serializeToString() + * + * Serializes this message instance to protobuf data. + * @return string Serialized protobuf data. + */ +PHP_METHOD(Message, serializeToString) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_msglayout *l = upb_msgdef_layout(intern->desc->msgdef); + upb_arena *tmp_arena = upb_arena_new(); + char *data; + size_t size; + + data = upb_encode(intern->msg, l, tmp_arena, &size); + + if (!data) { + zend_throw_exception_ex(NULL, 0, "Error occurred during serialization"); + upb_arena_free(tmp_arena); + return; + } + + RETVAL_STRINGL(data, size); + upb_arena_free(tmp_arena); +} + +/** + * Message::mergeFromJsonString() + * + * Merges the JSON data parsed from the given string. + * @param string Serialized JSON data. + */ +PHP_METHOD(Message, mergeFromJsonString) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + char *data = NULL; + char *data_copy = NULL; + zend_long data_len; + upb_arena *arena = Arena_Get(&intern->arena); + upb_status status; + zend_bool ignore_json_unknown = false; + int options = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|b", &data, &data_len, + &ignore_json_unknown) == FAILURE) { + return; + } + + // TODO(haberman): avoid this copy when we can make the decoder copy. + data_copy = upb_arena_malloc(arena, data_len + 1); + memcpy(data_copy, data, data_len); + data_copy[data_len] = '\0'; + + if (ignore_json_unknown) { + options |= UPB_JSONDEC_IGNOREUNKNOWN; + } + + upb_status_clear(&status); + if (!upb_json_decode(data_copy, data_len, intern->msg, intern->desc->msgdef, + DescriptorPool_GetSymbolTable(), options, arena, + &status)) { + zend_throw_exception_ex(NULL, 0, "Error occurred during parsing: %s", + upb_status_errmsg(&status)); + return; + } +} + +/** + * Message::serializeToJsonString() + * + * Serializes this object to JSON. + * @return string Serialized JSON data. + */ +PHP_METHOD(Message, serializeToJsonString) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + size_t size; + int options = 0; + char buf[1024]; + zend_bool preserve_proto_fieldnames = false; + upb_status status; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", + &preserve_proto_fieldnames) == FAILURE) { + return; + } + + if (preserve_proto_fieldnames) { + options |= UPB_JSONENC_PROTONAMES; + } + + upb_status_clear(&status); + size = upb_json_encode(intern->msg, intern->desc->msgdef, + DescriptorPool_GetSymbolTable(), options, buf, + sizeof(buf), &status); + + if (!upb_ok(&status)) { + zend_throw_exception_ex(NULL, 0, + "Error occurred during JSON serialization: %s", + upb_status_errmsg(&status)); + return; + } + + if (size >= sizeof(buf)) { + char *buf2 = malloc(size + 1); + upb_json_encode(intern->msg, intern->desc->msgdef, + DescriptorPool_GetSymbolTable(), options, buf2, size + 1, + &status); + RETVAL_STRINGL(buf2, size); + free(buf2); + } else { + RETVAL_STRINGL(buf, size); + } +} + +/** + * Message::readWrapperValue() + * + * Returns an unboxed value for the given field. This is called from generated + * methods for wrapper fields, eg. + * + * public function getDoubleValueUnwrapped() + * { + * return $this->readWrapperValue("double_value"); + * } + * + * @return Unwrapped field value or null. + */ +PHP_METHOD(Message, readWrapperValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + char* member; + const upb_fielddef *f; + zend_long size; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &member, &size) == FAILURE) { + return; + } + + f = upb_msgdef_ntof(intern->desc->msgdef, member, size); + + if (!f || !upb_msgdef_iswrapper(upb_fielddef_msgsubdef(f))) { + zend_throw_exception_ex(NULL, 0, "Message %s has no field %s", + upb_msgdef_fullname(intern->desc->msgdef), member); + return; + } + + if (upb_msg_has(intern->msg, f)) { + const upb_msg *wrapper = upb_msg_get(intern->msg, f).msg_val; + const upb_msgdef *m = upb_fielddef_msgsubdef(f); + const upb_fielddef *val_f = upb_msgdef_itof(m, 1); + const upb_fieldtype_t val_type = upb_fielddef_type(val_f); + upb_msgval msgval = upb_msg_get(wrapper, val_f); + zval ret; + Convert_UpbToPhp(msgval, &ret, val_type, NULL, &intern->arena); + RETURN_ZVAL(&ret, 1, 0); + } else { + RETURN_NULL(); + } +} + +/** + * Message::writeWrapperValue() + * + * Sets the given wrapper field to the given unboxed value. This is called from + * generated methods for wrapper fields, eg. + * + * + * public function setDoubleValueUnwrapped($var) + * { + * $this->writeWrapperValue("double_value", $var); + * return $this; + * } + * + * @param Unwrapped field value or null. + */ +PHP_METHOD(Message, writeWrapperValue) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + upb_arena *arena = Arena_Get(&intern->arena); + char* member; + const upb_fielddef *f; + upb_msgval msgval; + zend_long size; + zval* val; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz", &member, &size, &val) == + FAILURE) { + return; + } + + f = upb_msgdef_ntof(intern->desc->msgdef, member, size); + + if (!f || !upb_msgdef_iswrapper(upb_fielddef_msgsubdef(f))) { + zend_throw_exception_ex(NULL, 0, "Message %s has no field %s", + upb_msgdef_fullname(intern->desc->msgdef), member); + return; + } + + if (Z_ISREF_P(val)) { + ZVAL_DEREF(val); + } + + if (Z_TYPE_P(val) == IS_NULL) { + upb_msg_clearfield(intern->msg, f); + } else { + const upb_msgdef *m = upb_fielddef_msgsubdef(f); + const upb_fielddef *val_f = upb_msgdef_itof(m, 1); + upb_fieldtype_t val_type = upb_fielddef_type(val_f); + upb_msg *wrapper; + + if (!Convert_PhpToUpb(val, &msgval, val_type, NULL, arena)) { + return; // Error is already set. + } + + wrapper = upb_msg_mutable(intern->msg, f, arena).msg; + upb_msg_set(wrapper, val_f, msgval, arena); + } +} + +/** + * Message::whichOneof() + * + * Given a oneof name, returns the name of the field that is set for this oneof, + * or otherwise the empty string. + * + * @return string The field name in this oneof that is currently set. + */ +PHP_METHOD(Message, whichOneof) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_oneofdef* oneof; + const upb_fielddef* field; + char* name; + zend_long len; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &len) == FAILURE) { + return; + } + + oneof = upb_msgdef_ntoo(intern->desc->msgdef, name, len); + + if (!oneof) { + zend_throw_exception_ex(NULL, 0, "Message %s has no oneof %s", + upb_msgdef_fullname(intern->desc->msgdef), name); + return; + } + + field = upb_msg_whichoneof(intern->msg, oneof); + RETURN_STRING(field ? upb_fielddef_name(field) : ""); +} + +/** + * Message::readOneof() + * + * Returns the contents of the given oneof field, given a field number. Called + * from generated code methods such as: + * + * public function getDoubleValueOneof() + * { + * return $this->readOneof(10); + * } + * + * @return object The oneof's field value. + */ +PHP_METHOD(Message, readOneof) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + zend_long field_num; + const upb_fielddef* f; + zval ret; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &field_num) == FAILURE) { + return; + } + + f = upb_msgdef_itof(intern->desc->msgdef, field_num); + + if (!f || !upb_fielddef_realcontainingoneof(f)) { + php_error_docref(NULL, E_USER_ERROR, + "Internal error, no such oneof field %d\n", + (int)field_num); + } + + { + upb_msgval msgval = upb_msg_get(intern->msg, f); + const Descriptor *subdesc = Descriptor_GetFromFieldDef(f); + Convert_UpbToPhp(msgval, &ret, upb_fielddef_type(f), subdesc, + &intern->arena); + } + + RETURN_ZVAL(&ret, 1, 0); +} + +/** + * Message::writeOneof() + * + * Sets the contents of the given oneof field, given a field number. Called + * from generated code methods such as: + * + * public function setDoubleValueOneof($var) + * { + * GPBUtil::checkMessage($var, \Google\Protobuf\DoubleValue::class); + * $this->writeOneof(10, $var); + * + * return $this; + * } + * + * The C extension version of GPBUtil::check*() does nothing, so we perform + * all type checking and conversion here. + * + * @param integer The field number we are setting. + * @param object The field value we want to set. + */ +PHP_METHOD(Message, writeOneof) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + zend_long field_num; + const upb_fielddef* f; + upb_arena *arena = Arena_Get(&intern->arena); + upb_msgval msgval; + zval* val; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz", &field_num, &val) == + FAILURE) { + return; + } + + f = upb_msgdef_itof(intern->desc->msgdef, field_num); + + if (!Convert_PhpToUpb(val, &msgval, upb_fielddef_type(f), + Descriptor_GetFromFieldDef(f), arena)) { + return; + } + + upb_msg_set(intern->msg, f, msgval, arena); +} + +static zend_function_entry Message_methods[] = { + PHP_ME(Message, clear, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Message, discardUnknownFields, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Message, serializeToString, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Message, mergeFromString, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Message, serializeToJsonString, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Message, mergeFromJsonString, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Message, mergeFrom, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Message, readWrapperValue, NULL, ZEND_ACC_PROTECTED) + PHP_ME(Message, writeWrapperValue, NULL, ZEND_ACC_PROTECTED) + PHP_ME(Message, readOneof, NULL, ZEND_ACC_PROTECTED) + PHP_ME(Message, writeOneof, NULL, ZEND_ACC_PROTECTED) + PHP_ME(Message, whichOneof, NULL, ZEND_ACC_PROTECTED) + PHP_ME(Message, __construct, NULL, ZEND_ACC_PROTECTED) + ZEND_FE_END +}; + +/** + * Message_ModuleInit() + * + * Called when the C extension is loaded to register all types. + */ +void Message_ModuleInit() { + zend_class_entry tmp_ce; + zend_object_handlers *h = &message_object_handlers; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\Message", + Message_methods); + + message_ce = zend_register_internal_class(&tmp_ce); + message_ce->create_object = Message_create; + + memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); + h->dtor_obj = Message_dtor; + h->read_property = Message_read_property; + h->write_property = Message_write_property; + h->get_properties = Message_get_properties; + h->get_property_ptr_ptr = Message_get_property_ptr_ptr; +} diff --git a/php/ext/google/protobuf2/message.h b/php/ext/google/protobuf2/message.h new file mode 100644 index 0000000000..5083976016 --- /dev/null +++ b/php/ext/google/protobuf2/message.h @@ -0,0 +1,59 @@ +// 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 PHP_PROTOBUF_MESSAGE_H_ +#define PHP_PROTOBUF_MESSAGE_H_ + +#include + +#include "def.h" + +// Registers the PHP Message class. +void Message_ModuleInit(); + +// Gets a upb_msg* for the PHP object |val|, which must either be a Message +// object or 'null'. Returns true and stores the message in |msg| if the +// conversion succeeded (we can't return upb_msg* because null->NULL is a valid +// conversion). Returns false and raises a PHP error if this isn't a Message +// object or null, or if the Message object doesn't match this Descriptor. +// +// The given |arena| will be fused to this message's arena. +bool Message_GetUpbMessage(zval *val, const Descriptor *desc, upb_arena *arena, + upb_msg **msg); + +// Gets or creates a PHP Message object to wrap the given upb_msg* and |desc| +// and returns it in |val|. The PHP object will keep a reference to this |arena| +// to ensure the underlying message data stays alive. +// +// If |msg| is NULL, this will return a PHP null. +void Message_GetPhpWrapper(zval *val, const Descriptor *desc, upb_msg *msg, + zval *arena); + +#endif // PHP_PROTOBUF_MESSAGE_H_ diff --git a/php/ext/google/protobuf2/names.c b/php/ext/google/protobuf2/names.c new file mode 100644 index 0000000000..ff04b3cbc3 --- /dev/null +++ b/php/ext/google/protobuf2/names.c @@ -0,0 +1,226 @@ +// 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. + +#include "names.h" + +#include + +#include "protobuf.h" + +/* stringsink *****************************************************************/ + +typedef struct { + char *ptr; + size_t len, size; +} stringsink; + +static size_t stringsink_string(stringsink *sink, const char *ptr, size_t len) { + size_t new_size = sink->size; + + 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; +} + +static void stringsink_init(stringsink *sink) { + sink->size = 32; + sink->ptr = malloc(sink->size); + PBPHP_ASSERT(sink->ptr != NULL); + sink->len = 0; +} + +static void stringsink_uninit(stringsink *sink) { free(sink->ptr); } + +/* def name -> classname ******************************************************/ + +const char *const kReservedNames[] = { + "abstract", "and", "array", "as", "break", + "callable", "case", "catch", "class", "clone", + "const", "continue", "declare", "default", "die", + "do", "echo", "else", "elseif", "empty", + "enddeclare", "endfor", "endforeach", "endif", "endswitch", + "endwhile", "eval", "exit", "extends", "final", + "for", "foreach", "function", "global", "goto", + "if", "implements", "include", "include_once", "instanceof", + "insteadof", "interface", "isset", "list", "namespace", + "new", "or", "print", "private", "protected", + "public", "require", "require_once", "return", "static", + "switch", "throw", "trait", "try", "unset", + "use", "var", "while", "xor", "int", + "float", "bool", "string", "true", "false", + "null", "void", "iterable", NULL}; + +bool is_reserved_name(const char* name) { + int i; + for (i = 0; kReservedNames[i]; i++) { + if (strcmp(kReservedNames[i], name) == 0) { + return true; + } + } + return false; +} + +static char nolocale_tolower(char ch) { + if (ch >= 'A' && ch <= 'Z') { + return ch - ('A' - 'a'); + } else { + return ch; + } +} + +static char nolocale_toupper(char ch) { + if (ch >= 'a' && ch <= 'z') { + return ch - ('a' - 'A'); + } else { + return ch; + } +} + +static bool is_reserved(const char *segment, int length) { + bool result; + char* lower = calloc(1, length + 1); + memcpy(lower, segment, length); + int i = 0; + while(lower[i]) { + lower[i] = nolocale_tolower(lower[i]); + i++; + } + lower[length] = 0; + result = is_reserved_name(lower); + free(lower); + return result; +} + +static void fill_prefix(const char *segment, int length, + const char *prefix_given, + const char *package_name, + stringsink *classname) { + if (prefix_given != NULL && strcmp(prefix_given, "") != 0) { + stringsink_string(classname, prefix_given, strlen(prefix_given)); + } else { + if (is_reserved(segment, length)) { + if (package_name != NULL && + strcmp("google.protobuf", package_name) == 0) { + stringsink_string(classname, "GPB", 3); + } else { + stringsink_string(classname, "PB", 2); + } + } + } +} + +static void fill_segment(const char *segment, int length, + stringsink *classname, bool use_camel) { + if (use_camel && (segment[0] < 'A' || segment[0] > 'Z')) { + char first = nolocale_toupper(segment[0]); + stringsink_string(classname, &first, 1); + stringsink_string(classname, segment + 1, length - 1); + } else { + stringsink_string(classname, segment, length); + } +} + +static void fill_namespace(const char *package, const char *php_namespace, + stringsink *classname) { + if (php_namespace != NULL) { + if (strlen(php_namespace) != 0) { + stringsink_string(classname, php_namespace, strlen(php_namespace)); + stringsink_string(classname, "\\", 1); + } + } else if (package != NULL) { + int i = 0, j = 0; + size_t package_len = strlen(package); + while (i < package_len) { + j = i; + while (j < package_len && package[j] != '.') { + j++; + } + fill_prefix(package + i, j - i, "", package, classname); + fill_segment(package + i, j - i, classname, true); + stringsink_string(classname, "\\", 1); + i = j + 1; + } + } +} + +static void fill_classname(const char *fullname, + const char *package, + const char *prefix, + stringsink *classname) { + int classname_start = 0; + if (package != NULL) { + size_t package_len = strlen(package); + classname_start = package_len == 0 ? 0 : package_len + 1; + } + size_t fullname_len = strlen(fullname); + + int i = classname_start, j; + while (i < fullname_len) { + j = i; + while (j < fullname_len && fullname[j] != '.') { + j++; + } + fill_prefix(fullname + i, j - i, prefix, package, classname); + fill_segment(fullname + i, j - i, classname, false); + if (j != fullname_len) { + stringsink_string(classname, "\\", 1); + } + i = j + 1; + } +} + +char *GetPhpClassname(const upb_filedef *file, const char *fullname) { + // Prepend '.' to package name to make it absolute. In the 5 additional + // bytes allocated, one for '.', one for trailing 0, and 3 for 'GPB' if + // given message is google.protobuf.Empty. + const char *package = upb_filedef_package(file); + const char *php_namespace = upb_filedef_phpnamespace(file); + const char *prefix = upb_filedef_phpprefix(file); + char *ret; + stringsink namesink; + stringsink_init(&namesink); + + fill_namespace(package, php_namespace, &namesink); + fill_classname(fullname, package, prefix, &namesink); + stringsink_string(&namesink, "\0", 1); + ret = strdup(namesink.ptr); + stringsink_uninit(&namesink); + return ret; +} diff --git a/php/ext/google/protobuf2/names.h b/php/ext/google/protobuf2/names.h new file mode 100644 index 0000000000..75101c5a78 --- /dev/null +++ b/php/ext/google/protobuf2/names.h @@ -0,0 +1,40 @@ +// 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 PHP_PROTOBUF_NAMES_H_ +#define PHP_PROTOBUF_NAMES_H_ + +#include "php-upb.h" + +// Translates a protobuf symbol name (eg. foo.bar.Baz) into a PHP class name +// (eg. \Foo\Bar\Baz). +char *GetPhpClassname(const upb_filedef *file, const char *fullname); + +#endif // PHP_PROTOBUF_NAMES_H_ diff --git a/php/ext/google/protobuf2/php-upb.c b/php/ext/google/protobuf2/php-upb.c new file mode 100644 index 0000000000..f5ea2ef20a --- /dev/null +++ b/php/ext/google/protobuf2/php-upb.c @@ -0,0 +1,8077 @@ +/* Amalgamated source file */ +#include "php-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 +#include + +#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 + +/* 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 +#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 +#include +#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() +#elif defined _MSC_VER +#define UPB_ASSUME(expr) if (!(expr)) __assume(0) +#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 +#ifdef INFINITY +#define UPB_INFINITY INFINITY +#else +#define UPB_INFINITY (1.0 / 0.0) +#endif + +#include +#include + + + +/* 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, 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; +} + +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; + size_t 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, val.str_val.size); + 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 */ + 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 { + 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 + + + +#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 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); + upb_map_entry ent; + _upb_map_fromkey(key, &ent.k, map->key_size); + _upb_map_fromvalue(val, &ent.v, map->val_size); + CHK(upb_encode_scalarfield(e, &ent.v, entry, val_field, false)); + CHK(upb_encode_scalarfield(e, &ent.k, 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_hasbit_field(msg, f)) { + continue; + } + } else { + /* Field is in a oneof. */ + if (_upb_getoneofcase_field(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 const upb_msg_internal *upb_msg_getinternal_const(const upb_msg *msg) { + ptrdiff_t size = sizeof(upb_msg_internal); + return UPB_PTR_AT(msg, -size, upb_msg_internal); +} + +static upb_msg_internal *upb_msg_getinternal(upb_msg *msg) { + return (upb_msg_internal*)upb_msg_getinternal_const(msg); +} + +void _upb_msg_clear(upb_msg *msg, const upb_msglayout *l) { + ptrdiff_t internal = upb_msg_internalsize(l); + void *mem = UPB_PTR_AT(msg, -internal, char); + memset(mem, 0, l->size + internal); +} + +upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a) { + void *mem = upb_arena_malloc(a, upb_msg_sizeof(l)); + upb_msg *msg; + + if (!mem) { + return NULL; + } + + msg = UPB_PTR_AT(mem, upb_msg_internalsize(l), upb_msg); + _upb_msg_clear(msg, l); + 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; +} + +void _upb_msg_discardunknown_shallow(upb_msg *msg) { + upb_msg_internal *in = upb_msg_getinternal(msg); + 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); + *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; +} + +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 && _upb_array_resize(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 || !_upb_array_resize(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 + + +#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 - 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 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 && (len == 0 || memcmp(str, k2.str.str, len) == 0); +} + +bool upb_strtable_init2(upb_strtable *t, upb_ctype_t ctype, upb_alloc *a) { + UPB_UNUSED(ctype); /* TODO(haberman): rm */ + 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) { + 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_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; /* fallthrough */ + case 2: t |= data[1] << 8; /* fallthrough */ + 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; /* fallthrough */ + case 2: d |= data[1] << 8; /* fallthrough */ + case 1: d |= data[0]; /* fallthrough */ + } + + k = (t >> sr) | (d << sl); + MIX(h,k,m); + + data += align; + len -= align; + + /* ---------- + * Handle tail bytes */ + + switch(len) { + case 3: h ^= data[2] << 16; /* fallthrough */ + case 2: h ^= data[1] << 8; /* fallthrough */ + case 1: h ^= data[0]; h *= m; /* fallthrough */ + }; + } else { + switch(len) { + case 3: d |= data[2] << 16; /* fallthrough */ + case 2: d |= data[1] << 8; /* fallthrough */ + case 1: d |= data[0]; /* fallthrough */ + 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; /* fallthrough */ + case 2: h ^= data[1] << 8; /* fallthrough */ + 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 +#include +#include +#include +#include +#include +#include + + +/* 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'; +} + +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); + _upb_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. */ + +typedef struct mem_block { + struct mem_block *next; + uint32_t size; + uint32_t cleanups; + /* Data follows. */ +} mem_block; + +typedef struct cleanup_ent { + upb_cleanup_func *cleanup; + void *ud; +} cleanup_ent; + +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; +}; + +static const size_t memblock_reserve = UPB_ALIGN_UP(sizeof(mem_block), 16); + +static void upb_arena_addblock(upb_arena *a, void *ptr, size_t size) { + mem_block *block = ptr; + + block->next = a->freelist; + block->size = (uint32_t)size; + block->cleanups = 0; + a->freelist = block; + a->last_size = block->size; + if (!a->freelist_tail) a->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; + + /* TODO(haberman): ASAN poison. */ +} + +static bool upb_arena_allocblock(upb_arena *a, size_t size) { + size_t block_size = UPB_MAX(size, a->last_size * 2) + memblock_reserve; + mem_block *block = upb_malloc(a->block_alloc, block_size); + + if (!block) return false; + upb_arena_addblock(a, block, block_size); + return true; +} + +static bool arena_has(upb_arena *a, size_t size) { + _upb_arena_head *h = (_upb_arena_head*)a; + return (size_t)(h->end - h->ptr) >= size; +} + +void *_upb_arena_slowmalloc(upb_arena *a, size_t size) { + if (!upb_arena_allocblock(a, size)) return NULL; /* Out of memory. */ + UPB_ASSERT(arena_has(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); +} + +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; +} + +/* 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, 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); + n -= sizeof(*a); + + a->head.alloc.func = &upb_arena_doalloc; + a->block_alloc = alloc; + a->parent = a; + a->refcount = 1; + a->last_size = 128; + a->head.ptr = mem; + a->head.end = UPB_PTR_AT(mem, n, 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 || !arena_has(a, sizeof(cleanup_ent))) { + if (!upb_arena_allocblock(a, 128)) return false; /* Out of memory. */ + UPB_ASSERT(arena_has(a, sizeof(cleanup_ent))); + } + + a->head.end -= sizeof(cleanup_ent); + ent = (cleanup_ent*)a->head.end; + (*a->cleanups)++; + + 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; +} +/* 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 + + +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, +}; + + +/* 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. */ + + +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; + +static const upb_msglayout *layouts[27] = { + &google_protobuf_FileDescriptorSet_msginit, + &google_protobuf_FileDescriptorProto_msginit, + &google_protobuf_DescriptorProto_msginit, + &google_protobuf_DescriptorProto_ExtensionRange_msginit, + &google_protobuf_DescriptorProto_ReservedRange_msginit, + &google_protobuf_ExtensionRangeOptions_msginit, + &google_protobuf_FieldDescriptorProto_msginit, + &google_protobuf_OneofDescriptorProto_msginit, + &google_protobuf_EnumDescriptorProto_msginit, + &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, + &google_protobuf_EnumValueDescriptorProto_msginit, + &google_protobuf_ServiceDescriptorProto_msginit, + &google_protobuf_MethodDescriptorProto_msginit, + &google_protobuf_FileOptions_msginit, + &google_protobuf_MessageOptions_msginit, + &google_protobuf_FieldOptions_msginit, + &google_protobuf_OneofOptions_msginit, + &google_protobuf_EnumOptions_msginit, + &google_protobuf_EnumValueOptions_msginit, + &google_protobuf_ServiceOptions_msginit, + &google_protobuf_MethodOptions_msginit, + &google_protobuf_UninterpretedOption_msginit, + &google_protobuf_UninterpretedOption_NamePart_msginit, + &google_protobuf_SourceCodeInfo_msginit, + &google_protobuf_SourceCodeInfo_Location_msginit, + &google_protobuf_GeneratedCodeInfo_msginit, + &google_protobuf_GeneratedCodeInfo_Annotation_msginit, +}; + +static const char descriptor[7619] = {'\n', ' ', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'e', 's', 'c', 'r', 'i', 'p', +'t', 'o', 'r', '.', 'p', 'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', +'f', '\"', 'M', '\n', '\021', 'F', 'i', 'l', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'S', 'e', 't', '\022', '8', '\n', +'\004', 'f', 'i', 'l', 'e', '\030', '\001', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', +'o', 'b', 'u', 'f', '.', 'F', 'i', 'l', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', +'\004', 'f', 'i', 'l', 'e', '\"', '\344', '\004', '\n', '\023', 'F', 'i', 'l', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', +'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', +'\030', '\n', '\007', 'p', 'a', 'c', 'k', 'a', 'g', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\007', 'p', 'a', 'c', 'k', 'a', 'g', 'e', +'\022', '\036', '\n', '\n', 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'y', '\030', '\003', ' ', '\003', '(', '\t', 'R', '\n', 'd', 'e', 'p', +'e', 'n', 'd', 'e', 'n', 'c', 'y', '\022', '+', '\n', '\021', 'p', 'u', 'b', 'l', 'i', 'c', '_', 'd', 'e', 'p', 'e', 'n', 'd', 'e', +'n', 'c', 'y', '\030', '\n', ' ', '\003', '(', '\005', 'R', '\020', 'p', 'u', 'b', 'l', 'i', 'c', 'D', 'e', 'p', 'e', 'n', 'd', 'e', 'n', +'c', 'y', '\022', '\'', '\n', '\017', 'w', 'e', 'a', 'k', '_', 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'y', '\030', '\013', ' ', '\003', +'(', '\005', 'R', '\016', 'w', 'e', 'a', 'k', 'D', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'y', '\022', 'C', '\n', '\014', 'm', 'e', 's', +'s', 'a', 'g', 'e', '_', 't', 'y', 'p', 'e', '\030', '\004', ' ', '\003', '(', '\013', '2', ' ', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', +'\013', 'm', 'e', 's', 's', 'a', 'g', 'e', 'T', 'y', 'p', 'e', '\022', 'A', '\n', '\t', 'e', 'n', 'u', 'm', '_', 't', 'y', 'p', 'e', +'\030', '\005', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', +'E', 'n', 'u', 'm', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\010', 'e', 'n', 'u', 'm', +'T', 'y', 'p', 'e', '\022', 'A', '\n', '\007', 's', 'e', 'r', 'v', 'i', 'c', 'e', '\030', '\006', ' ', '\003', '(', '\013', '2', '\'', '.', 'g', +'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'D', 'e', 's', +'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\007', 's', 'e', 'r', 'v', 'i', 'c', 'e', '\022', 'C', '\n', '\t', +'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\030', '\007', ' ', '\003', '(', '\013', '2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', +'r', 'o', 't', 'o', 'R', '\t', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\022', '6', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', +'s', '\030', '\010', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', +'.', 'F', 'i', 'l', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\022', 'I', '\n', '\020', +'s', 'o', 'u', 'r', 'c', 'e', '_', 'c', 'o', 'd', 'e', '_', 'i', 'n', 'f', 'o', '\030', '\t', ' ', '\001', '(', '\013', '2', '\037', '.', +'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'd', +'e', 'I', 'n', 'f', 'o', 'R', '\016', 's', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '\022', '\026', '\n', '\006', +'s', 'y', 'n', 't', 'a', 'x', '\030', '\014', ' ', '\001', '(', '\t', 'R', '\006', 's', 'y', 'n', 't', 'a', 'x', '\"', '\271', '\006', '\n', '\017', +'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', +' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', ';', '\n', '\005', 'f', 'i', 'e', 'l', 'd', '\030', '\002', ' ', '\003', '(', '\013', +'2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'D', +'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\005', 'f', 'i', 'e', 'l', 'd', '\022', 'C', '\n', '\t', +'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\030', '\006', ' ', '\003', '(', '\013', '2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', +'r', 'o', 't', 'o', 'R', '\t', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\022', 'A', '\n', '\013', 'n', 'e', 's', 't', 'e', 'd', +'_', 't', 'y', 'p', 'e', '\030', '\003', ' ', '\003', '(', '\013', '2', ' ', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', +'o', 'b', 'u', 'f', '.', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\n', 'n', 'e', 's', +'t', 'e', 'd', 'T', 'y', 'p', 'e', '\022', 'A', '\n', '\t', 'e', 'n', 'u', 'm', '_', 't', 'y', 'p', 'e', '\030', '\004', ' ', '\003', '(', +'\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'D', +'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\010', 'e', 'n', 'u', 'm', 'T', 'y', 'p', 'e', '\022', +'X', '\n', '\017', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '_', 'r', 'a', 'n', 'g', 'e', '\030', '\005', ' ', '\003', '(', '\013', '2', +'/', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'e', 's', 'c', 'r', 'i', 'p', +'t', 'o', 'r', 'P', 'r', 'o', 't', 'o', '.', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', 'R', '\016', +'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', '\022', 'D', '\n', '\n', 'o', 'n', 'e', 'o', 'f', '_', 'd', +'e', 'c', 'l', '\030', '\010', ' ', '\003', '(', '\013', '2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', +'u', 'f', '.', 'O', 'n', 'e', 'o', 'f', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\t', +'o', 'n', 'e', 'o', 'f', 'D', 'e', 'c', 'l', '\022', '9', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\007', ' ', '\001', '(', +'\013', '2', '\037', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', 'e', 's', 's', 'a', +'g', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\022', 'U', '\n', '\016', 'r', 'e', 's', +'e', 'r', 'v', 'e', 'd', '_', 'r', 'a', 'n', 'g', 'e', '\030', '\t', ' ', '\003', '(', '\013', '2', '.', '.', 'g', 'o', 'o', 'g', 'l', +'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', +'o', '.', 'R', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'R', 'a', 'n', 'g', 'e', 'R', '\r', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', +'R', 'a', 'n', 'g', 'e', '\022', '#', '\n', '\r', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', '_', 'n', 'a', 'm', 'e', '\030', '\n', ' ', +'\003', '(', '\t', 'R', '\014', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'N', 'a', 'm', 'e', '\032', 'z', '\n', '\016', 'E', 'x', 't', 'e', +'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', '\022', '\024', '\n', '\005', 's', 't', 'a', 'r', 't', '\030', '\001', ' ', '\001', '(', '\005', +'R', '\005', 's', 't', 'a', 'r', 't', '\022', '\020', '\n', '\003', 'e', 'n', 'd', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\003', 'e', 'n', 'd', +'\022', '@', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\001', '(', '\013', '2', '&', '.', 'g', 'o', 'o', 'g', 'l', +'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', +'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\032', '7', '\n', '\r', 'R', 'e', 's', 'e', 'r', +'v', 'e', 'd', 'R', 'a', 'n', 'g', 'e', '\022', '\024', '\n', '\005', 's', 't', 'a', 'r', 't', '\030', '\001', ' ', '\001', '(', '\005', 'R', '\005', +'s', 't', 'a', 'r', 't', '\022', '\020', '\n', '\003', 'e', 'n', 'd', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\003', 'e', 'n', 'd', '\"', '|', +'\n', '\025', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', 'X', +'\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', +' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', +'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', +'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', '\"', +'\301', '\006', '\n', '\024', 'F', 'i', 'e', 'l', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', +'\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '\026', '\n', '\006', 'n', 'u', +'m', 'b', 'e', 'r', '\030', '\003', ' ', '\001', '(', '\005', 'R', '\006', 'n', 'u', 'm', 'b', 'e', 'r', '\022', 'A', '\n', '\005', 'l', 'a', 'b', +'e', 'l', '\030', '\004', ' ', '\001', '(', '\016', '2', '+', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', +'f', '.', 'F', 'i', 'e', 'l', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '.', 'L', 'a', +'b', 'e', 'l', 'R', '\005', 'l', 'a', 'b', 'e', 'l', '\022', '>', '\n', '\004', 't', 'y', 'p', 'e', '\030', '\005', ' ', '\001', '(', '\016', '2', +'*', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'D', 'e', +'s', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '.', 'T', 'y', 'p', 'e', 'R', '\004', 't', 'y', 'p', 'e', '\022', +'\033', '\n', '\t', 't', 'y', 'p', 'e', '_', 'n', 'a', 'm', 'e', '\030', '\006', ' ', '\001', '(', '\t', 'R', '\010', 't', 'y', 'p', 'e', 'N', +'a', 'm', 'e', '\022', '\032', '\n', '\010', 'e', 'x', 't', 'e', 'n', 'd', 'e', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\010', 'e', 'x', +'t', 'e', 'n', 'd', 'e', 'e', '\022', '#', '\n', '\r', 'd', 'e', 'f', 'a', 'u', 'l', 't', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\007', +' ', '\001', '(', '\t', 'R', '\014', 'd', 'e', 'f', 'a', 'u', 'l', 't', 'V', 'a', 'l', 'u', 'e', '\022', '\037', '\n', '\013', 'o', 'n', 'e', +'o', 'f', '_', 'i', 'n', 'd', 'e', 'x', '\030', '\t', ' ', '\001', '(', '\005', 'R', '\n', 'o', 'n', 'e', 'o', 'f', 'I', 'n', 'd', 'e', +'x', '\022', '\033', '\n', '\t', 'j', 's', 'o', 'n', '_', 'n', 'a', 'm', 'e', '\030', '\n', ' ', '\001', '(', '\t', 'R', '\010', 'j', 's', 'o', +'n', 'N', 'a', 'm', 'e', '\022', '7', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\010', ' ', '\001', '(', '\013', '2', '\035', '.', +'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', +'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\022', '\'', '\n', '\017', 'p', 'r', 'o', 't', 'o', '3', '_', 'o', 'p', +'t', 'i', 'o', 'n', 'a', 'l', '\030', '\021', ' ', '\001', '(', '\010', 'R', '\016', 'p', 'r', 'o', 't', 'o', '3', 'O', 'p', 't', 'i', 'o', +'n', 'a', 'l', '\"', '\266', '\002', '\n', '\004', 'T', 'y', 'p', 'e', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'D', 'O', 'U', 'B', +'L', 'E', '\020', '\001', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'F', 'L', 'O', 'A', 'T', '\020', '\002', '\022', '\016', '\n', '\n', 'T', +'Y', 'P', 'E', '_', 'I', 'N', 'T', '6', '4', '\020', '\003', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'U', 'I', 'N', 'T', '6', +'4', '\020', '\004', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'I', 'N', 'T', '3', '2', '\020', '\005', '\022', '\020', '\n', '\014', 'T', 'Y', +'P', 'E', '_', 'F', 'I', 'X', 'E', 'D', '6', '4', '\020', '\006', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', 'F', 'I', 'X', 'E', +'D', '3', '2', '\020', '\007', '\022', '\r', '\n', '\t', 'T', 'Y', 'P', 'E', '_', 'B', 'O', 'O', 'L', '\020', '\010', '\022', '\017', '\n', '\013', 'T', +'Y', 'P', 'E', '_', 'S', 'T', 'R', 'I', 'N', 'G', '\020', '\t', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'G', 'R', 'O', 'U', +'P', '\020', '\n', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', 'M', 'E', 'S', 'S', 'A', 'G', 'E', '\020', '\013', '\022', '\016', '\n', '\n', +'T', 'Y', 'P', 'E', '_', 'B', 'Y', 'T', 'E', 'S', '\020', '\014', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'U', 'I', 'N', 'T', +'3', '2', '\020', '\r', '\022', '\r', '\n', '\t', 'T', 'Y', 'P', 'E', '_', 'E', 'N', 'U', 'M', '\020', '\016', '\022', '\021', '\n', '\r', 'T', 'Y', +'P', 'E', '_', 'S', 'F', 'I', 'X', 'E', 'D', '3', '2', '\020', '\017', '\022', '\021', '\n', '\r', 'T', 'Y', 'P', 'E', '_', 'S', 'F', 'I', +'X', 'E', 'D', '6', '4', '\020', '\020', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'S', 'I', 'N', 'T', '3', '2', '\020', '\021', '\022', +'\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'S', 'I', 'N', 'T', '6', '4', '\020', '\022', '\"', 'C', '\n', '\005', 'L', 'a', 'b', 'e', 'l', +'\022', '\022', '\n', '\016', 'L', 'A', 'B', 'E', 'L', '_', 'O', 'P', 'T', 'I', 'O', 'N', 'A', 'L', '\020', '\001', '\022', '\022', '\n', '\016', 'L', +'A', 'B', 'E', 'L', '_', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D', '\020', '\002', '\022', '\022', '\n', '\016', 'L', 'A', 'B', 'E', 'L', '_', +'R', 'E', 'P', 'E', 'A', 'T', 'E', 'D', '\020', '\003', '\"', 'c', '\n', '\024', 'O', 'n', 'e', 'o', 'f', 'D', 'e', 's', 'c', 'r', 'i', +'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', +'n', 'a', 'm', 'e', '\022', '7', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', '\035', '.', 'g', +'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'O', 'n', 'e', 'o', 'f', 'O', 'p', 't', 'i', 'o', +'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\"', '\343', '\002', '\n', '\023', 'E', 'n', 'u', 'm', 'D', 'e', 's', 'c', 'r', +'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', +'\004', 'n', 'a', 'm', 'e', '\022', '?', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\003', '(', '\013', '2', ')', '.', 'g', 'o', +'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', 'D', 'e', +'s', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\005', 'v', 'a', 'l', 'u', 'e', '\022', '6', '\n', '\007', 'o', +'p', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', +'t', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', +'s', '\022', ']', '\n', '\016', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', '_', 'r', 'a', 'n', 'g', 'e', '\030', '\004', ' ', '\003', '(', '\013', +'2', '6', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'D', 'e', +'s', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '.', 'E', 'n', 'u', 'm', 'R', 'e', 's', 'e', 'r', 'v', 'e', +'d', 'R', 'a', 'n', 'g', 'e', 'R', '\r', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'R', 'a', 'n', 'g', 'e', '\022', '#', '\n', '\r', +'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', '_', 'n', 'a', 'm', 'e', '\030', '\005', ' ', '\003', '(', '\t', 'R', '\014', 'r', 'e', 's', 'e', +'r', 'v', 'e', 'd', 'N', 'a', 'm', 'e', '\032', ';', '\n', '\021', 'E', 'n', 'u', 'm', 'R', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'R', +'a', 'n', 'g', 'e', '\022', '\024', '\n', '\005', 's', 't', 'a', 'r', 't', '\030', '\001', ' ', '\001', '(', '\005', 'R', '\005', 's', 't', 'a', 'r', +'t', '\022', '\020', '\n', '\003', 'e', 'n', 'd', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\003', 'e', 'n', 'd', '\"', '\203', '\001', '\n', '\030', 'E', +'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', +'\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '\026', '\n', '\006', 'n', 'u', 'm', +'b', 'e', 'r', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\006', 'n', 'u', 'm', 'b', 'e', 'r', '\022', ';', '\n', '\007', 'o', 'p', 't', 'i', +'o', 'n', 's', '\030', '\003', ' ', '\001', '(', '\013', '2', '!', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', +'u', 'f', '.', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', +'o', 'n', 's', '\"', '\247', '\001', '\n', '\026', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', +'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', +'\022', '>', '\n', '\006', 'm', 'e', 't', 'h', 'o', 'd', '\030', '\002', ' ', '\003', '(', '\013', '2', '&', '.', 'g', 'o', 'o', 'g', 'l', 'e', +'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', 'e', 't', 'h', 'o', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', +'r', 'P', 'r', 'o', 't', 'o', 'R', '\006', 'm', 'e', 't', 'h', 'o', 'd', '\022', '9', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', +'\030', '\003', ' ', '\001', '(', '\013', '2', '\037', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', +'S', 'e', 'r', 'v', 'i', 'c', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\"', '\211', +'\002', '\n', '\025', 'M', 'e', 't', 'h', 'o', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', +'\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '\035', '\n', '\n', 'i', 'n', +'p', 'u', 't', '_', 't', 'y', 'p', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\t', 'i', 'n', 'p', 'u', 't', 'T', 'y', 'p', 'e', +'\022', '\037', '\n', '\013', 'o', 'u', 't', 'p', 'u', 't', '_', 't', 'y', 'p', 'e', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\n', 'o', 'u', +'t', 'p', 'u', 't', 'T', 'y', 'p', 'e', '\022', '8', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\004', ' ', '\001', '(', '\013', +'2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', 'e', 't', 'h', 'o', 'd', +'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\022', '0', '\n', '\020', 'c', 'l', 'i', 'e', 'n', +'t', '_', 's', 't', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\030', '\005', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', +'\017', 'c', 'l', 'i', 'e', 'n', 't', 'S', 't', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\022', '0', '\n', '\020', 's', 'e', 'r', 'v', 'e', +'r', '_', 's', 't', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\030', '\006', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', +'\017', 's', 'e', 'r', 'v', 'e', 'r', 'S', 't', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\"', '\221', '\t', '\n', '\013', 'F', 'i', 'l', 'e', +'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '!', '\n', '\014', 'j', 'a', 'v', 'a', '_', 'p', 'a', 'c', 'k', 'a', 'g', 'e', '\030', '\001', +' ', '\001', '(', '\t', 'R', '\013', 'j', 'a', 'v', 'a', 'P', 'a', 'c', 'k', 'a', 'g', 'e', '\022', '0', '\n', '\024', 'j', 'a', 'v', 'a', +'_', 'o', 'u', 't', 'e', 'r', '_', 'c', 'l', 'a', 's', 's', 'n', 'a', 'm', 'e', '\030', '\010', ' ', '\001', '(', '\t', 'R', '\022', 'j', +'a', 'v', 'a', 'O', 'u', 't', 'e', 'r', 'C', 'l', 'a', 's', 's', 'n', 'a', 'm', 'e', '\022', '5', '\n', '\023', 'j', 'a', 'v', 'a', +'_', 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', '_', 'f', 'i', 'l', 'e', 's', '\030', '\n', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', +'l', 's', 'e', 'R', '\021', 'j', 'a', 'v', 'a', 'M', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'F', 'i', 'l', 'e', 's', '\022', 'D', '\n', +'\035', 'j', 'a', 'v', 'a', '_', 'g', 'e', 'n', 'e', 'r', 'a', 't', 'e', '_', 'e', 'q', 'u', 'a', 'l', 's', '_', 'a', 'n', 'd', +'_', 'h', 'a', 's', 'h', '\030', '\024', ' ', '\001', '(', '\010', 'B', '\002', '\030', '\001', 'R', '\031', 'j', 'a', 'v', 'a', 'G', 'e', 'n', 'e', +'r', 'a', 't', 'e', 'E', 'q', 'u', 'a', 'l', 's', 'A', 'n', 'd', 'H', 'a', 's', 'h', '\022', ':', '\n', '\026', 'j', 'a', 'v', 'a', +'_', 's', 't', 'r', 'i', 'n', 'g', '_', 'c', 'h', 'e', 'c', 'k', '_', 'u', 't', 'f', '8', '\030', '\033', ' ', '\001', '(', '\010', ':', +'\005', 'f', 'a', 'l', 's', 'e', 'R', '\023', 'j', 'a', 'v', 'a', 'S', 't', 'r', 'i', 'n', 'g', 'C', 'h', 'e', 'c', 'k', 'U', 't', +'f', '8', '\022', 'S', '\n', '\014', 'o', 'p', 't', 'i', 'm', 'i', 'z', 'e', '_', 'f', 'o', 'r', '\030', '\t', ' ', '\001', '(', '\016', '2', +')', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'l', 'e', 'O', 'p', 't', +'i', 'o', 'n', 's', '.', 'O', 'p', 't', 'i', 'm', 'i', 'z', 'e', 'M', 'o', 'd', 'e', ':', '\005', 'S', 'P', 'E', 'E', 'D', 'R', +'\013', 'o', 'p', 't', 'i', 'm', 'i', 'z', 'e', 'F', 'o', 'r', '\022', '\035', '\n', '\n', 'g', 'o', '_', 'p', 'a', 'c', 'k', 'a', 'g', +'e', '\030', '\013', ' ', '\001', '(', '\t', 'R', '\t', 'g', 'o', 'P', 'a', 'c', 'k', 'a', 'g', 'e', '\022', '5', '\n', '\023', 'c', 'c', '_', +'g', 'e', 'n', 'e', 'r', 'i', 'c', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\030', '\020', ' ', '\001', '(', '\010', ':', '\005', 'f', +'a', 'l', 's', 'e', 'R', '\021', 'c', 'c', 'G', 'e', 'n', 'e', 'r', 'i', 'c', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\022', '9', +'\n', '\025', 'j', 'a', 'v', 'a', '_', 'g', 'e', 'n', 'e', 'r', 'i', 'c', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\030', '\021', +' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\023', 'j', 'a', 'v', 'a', 'G', 'e', 'n', 'e', 'r', 'i', 'c', 'S', +'e', 'r', 'v', 'i', 'c', 'e', 's', '\022', '5', '\n', '\023', 'p', 'y', '_', 'g', 'e', 'n', 'e', 'r', 'i', 'c', '_', 's', 'e', 'r', +'v', 'i', 'c', 'e', 's', '\030', '\022', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\021', 'p', 'y', 'G', 'e', 'n', +'e', 'r', 'i', 'c', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\022', '7', '\n', '\024', 'p', 'h', 'p', '_', 'g', 'e', 'n', 'e', 'r', +'i', 'c', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\030', '*', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', +'\022', 'p', 'h', 'p', 'G', 'e', 'n', 'e', 'r', 'i', 'c', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\022', '%', '\n', '\n', 'd', 'e', +'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\027', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', +'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', '.', '\n', '\020', 'c', 'c', '_', 'e', 'n', 'a', 'b', 'l', 'e', '_', 'a', 'r', 'e', +'n', 'a', 's', '\030', '\037', ' ', '\001', '(', '\010', ':', '\004', 't', 'r', 'u', 'e', 'R', '\016', 'c', 'c', 'E', 'n', 'a', 'b', 'l', 'e', +'A', 'r', 'e', 'n', 'a', 's', '\022', '*', '\n', '\021', 'o', 'b', 'j', 'c', '_', 'c', 'l', 'a', 's', 's', '_', 'p', 'r', 'e', 'f', +'i', 'x', '\030', '$', ' ', '\001', '(', '\t', 'R', '\017', 'o', 'b', 'j', 'c', 'C', 'l', 'a', 's', 's', 'P', 'r', 'e', 'f', 'i', 'x', +'\022', ')', '\n', '\020', 'c', 's', 'h', 'a', 'r', 'p', '_', 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\030', '%', ' ', '\001', '(', +'\t', 'R', '\017', 'c', 's', 'h', 'a', 'r', 'p', 'N', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\022', '!', '\n', '\014', 's', 'w', 'i', +'f', 't', '_', 'p', 'r', 'e', 'f', 'i', 'x', '\030', '\'', ' ', '\001', '(', '\t', 'R', '\013', 's', 'w', 'i', 'f', 't', 'P', 'r', 'e', +'f', 'i', 'x', '\022', '(', '\n', '\020', 'p', 'h', 'p', '_', 'c', 'l', 'a', 's', 's', '_', 'p', 'r', 'e', 'f', 'i', 'x', '\030', '(', +' ', '\001', '(', '\t', 'R', '\016', 'p', 'h', 'p', 'C', 'l', 'a', 's', 's', 'P', 'r', 'e', 'f', 'i', 'x', '\022', '#', '\n', '\r', 'p', +'h', 'p', '_', 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\030', ')', ' ', '\001', '(', '\t', 'R', '\014', 'p', 'h', 'p', 'N', 'a', +'m', 'e', 's', 'p', 'a', 'c', 'e', '\022', '4', '\n', '\026', 'p', 'h', 'p', '_', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '_', 'n', +'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\030', ',', ' ', '\001', '(', '\t', 'R', '\024', 'p', 'h', 'p', 'M', 'e', 't', 'a', 'd', 'a', +'t', 'a', 'N', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\022', '!', '\n', '\014', 'r', 'u', 'b', 'y', '_', 'p', 'a', 'c', 'k', 'a', +'g', 'e', '\030', '-', ' ', '\001', '(', '\t', 'R', '\013', 'r', 'u', 'b', 'y', 'P', 'a', 'c', 'k', 'a', 'g', 'e', '\022', 'X', '\n', '\024', +'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', +'(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', +'t', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', +'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '\"', ':', '\n', '\014', 'O', 'p', 't', 'i', 'm', 'i', 'z', 'e', 'M', 'o', +'d', 'e', '\022', '\t', '\n', '\005', 'S', 'P', 'E', 'E', 'D', '\020', '\001', '\022', '\r', '\n', '\t', 'C', 'O', 'D', 'E', '_', 'S', 'I', 'Z', +'E', '\020', '\002', '\022', '\020', '\n', '\014', 'L', 'I', 'T', 'E', '_', 'R', 'U', 'N', 'T', 'I', 'M', 'E', '\020', '\003', '*', '\t', '\010', '\350', +'\007', '\020', '\200', '\200', '\200', '\200', '\002', 'J', '\004', '\010', '&', '\020', '\'', '\"', '\321', '\002', '\n', '\016', 'M', 'e', 's', 's', 'a', 'g', 'e', +'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '<', '\n', '\027', 'm', 'e', 's', 's', 'a', 'g', 'e', '_', 's', 'e', 't', '_', 'w', 'i', +'r', 'e', '_', 'f', 'o', 'r', 'm', 'a', 't', '\030', '\001', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\024', 'm', +'e', 's', 's', 'a', 'g', 'e', 'S', 'e', 't', 'W', 'i', 'r', 'e', 'F', 'o', 'r', 'm', 'a', 't', '\022', 'L', '\n', '\037', 'n', 'o', +'_', 's', 't', 'a', 'n', 'd', 'a', 'r', 'd', '_', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', '_', 'a', 'c', 'c', 'e', +'s', 's', 'o', 'r', '\030', '\002', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\034', 'n', 'o', 'S', 't', 'a', 'n', +'d', 'a', 'r', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'A', 'c', 'c', 'e', 's', 's', 'o', 'r', '\022', '%', '\n', +'\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\003', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', +'\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', '\033', '\n', '\t', 'm', 'a', 'p', '_', 'e', 'n', 't', 'r', 'y', '\030', +'\007', ' ', '\001', '(', '\010', 'R', '\010', 'm', 'a', 'p', 'E', 'n', 't', 'r', 'y', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', +'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', +'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', +'t', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', +'p', 't', 'i', 'o', 'n', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', 'J', '\004', '\010', '\010', '\020', '\t', 'J', '\004', '\010', +'\t', '\020', '\n', '\"', '\342', '\003', '\n', '\014', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', 'A', '\n', '\005', 'c', +'t', 'y', 'p', 'e', '\030', '\001', ' ', '\001', '(', '\016', '2', '#', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', +'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'C', 'T', 'y', 'p', 'e', ':', '\006', 'S', +'T', 'R', 'I', 'N', 'G', 'R', '\005', 'c', 't', 'y', 'p', 'e', '\022', '\026', '\n', '\006', 'p', 'a', 'c', 'k', 'e', 'd', '\030', '\002', ' ', +'\001', '(', '\010', 'R', '\006', 'p', 'a', 'c', 'k', 'e', 'd', '\022', 'G', '\n', '\006', 'j', 's', 't', 'y', 'p', 'e', '\030', '\006', ' ', '\001', +'(', '\016', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', +'d', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'J', 'S', 'T', 'y', 'p', 'e', ':', '\t', 'J', 'S', '_', 'N', 'O', 'R', 'M', 'A', +'L', 'R', '\006', 'j', 's', 't', 'y', 'p', 'e', '\022', '\031', '\n', '\004', 'l', 'a', 'z', 'y', '\030', '\005', ' ', '\001', '(', '\010', ':', '\005', +'f', 'a', 'l', 's', 'e', 'R', '\004', 'l', 'a', 'z', 'y', '\022', '%', '\n', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', +'\030', '\003', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', +'\022', '\031', '\n', '\004', 'w', 'e', 'a', 'k', '\030', '\n', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\004', 'w', 'e', +'a', 'k', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', +'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', +'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', +'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '\"', '/', '\n', '\005', 'C', 'T', 'y', 'p', +'e', '\022', '\n', '\n', '\006', 'S', 'T', 'R', 'I', 'N', 'G', '\020', '\000', '\022', '\010', '\n', '\004', 'C', 'O', 'R', 'D', '\020', '\001', '\022', '\020', +'\n', '\014', 'S', 'T', 'R', 'I', 'N', 'G', '_', 'P', 'I', 'E', 'C', 'E', '\020', '\002', '\"', '5', '\n', '\006', 'J', 'S', 'T', 'y', 'p', +'e', '\022', '\r', '\n', '\t', 'J', 'S', '_', 'N', 'O', 'R', 'M', 'A', 'L', '\020', '\000', '\022', '\r', '\n', '\t', 'J', 'S', '_', 'S', 'T', +'R', 'I', 'N', 'G', '\020', '\001', '\022', '\r', '\n', '\t', 'J', 'S', '_', 'N', 'U', 'M', 'B', 'E', 'R', '\020', '\002', '*', '\t', '\010', '\350', +'\007', '\020', '\200', '\200', '\200', '\200', '\002', 'J', '\004', '\010', '\004', '\020', '\005', '\"', 's', '\n', '\014', 'O', 'n', 'e', 'o', 'f', 'O', 'p', 't', +'i', 'o', 'n', 's', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', +'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', +'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', +'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', '\t', '\010', '\350', '\007', '\020', +'\200', '\200', '\200', '\200', '\002', '\"', '\300', '\001', '\n', '\013', 'E', 'n', 'u', 'm', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '\037', '\n', '\013', +'a', 'l', 'l', 'o', 'w', '_', 'a', 'l', 'i', 'a', 's', '\030', '\002', ' ', '\001', '(', '\010', 'R', '\n', 'a', 'l', 'l', 'o', 'w', 'A', +'l', 'i', 'a', 's', '\022', '%', '\n', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\003', ' ', '\001', '(', '\010', ':', +'\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', 'X', '\n', '\024', 'u', 'n', 'i', +'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', +'$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', +'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', +'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', 'J', '\004', '\010', '\005', '\020', '\006', +'\"', '\236', '\001', '\n', '\020', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '%', '\n', '\n', +'d', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\001', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', +'d', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', +'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', +'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', +'t', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', +'*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', '\"', '\234', '\001', '\n', '\016', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'O', 'p', +'t', 'i', 'o', 'n', 's', '\022', '%', '\n', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '!', ' ', '\001', '(', '\010', +':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', 'X', '\n', '\024', 'u', 'n', +'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', +'2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', +'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', +'t', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', '\"', '\340', '\002', '\n', '\r', +'M', 'e', 't', 'h', 'o', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '%', '\n', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', +'e', 'd', '\030', '!', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', +'e', 'd', '\022', 'q', '\n', '\021', 'i', 'd', 'e', 'm', 'p', 'o', 't', 'e', 'n', 'c', 'y', '_', 'l', 'e', 'v', 'e', 'l', '\030', '\"', +' ', '\001', '(', '\016', '2', '/', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', 'e', +'t', 'h', 'o', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'I', 'd', 'e', 'm', 'p', 'o', 't', 'e', 'n', 'c', 'y', 'L', 'e', +'v', 'e', 'l', ':', '\023', 'I', 'D', 'E', 'M', 'P', 'O', 'T', 'E', 'N', 'C', 'Y', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', 'R', +'\020', 'i', 'd', 'e', 'm', 'p', 'o', 't', 'e', 'n', 'c', 'y', 'L', 'e', 'v', 'e', 'l', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', +'t', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', +'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', +'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', +'d', 'O', 'p', 't', 'i', 'o', 'n', '\"', 'P', '\n', '\020', 'I', 'd', 'e', 'm', 'p', 'o', 't', 'e', 'n', 'c', 'y', 'L', 'e', 'v', +'e', 'l', '\022', '\027', '\n', '\023', 'I', 'D', 'E', 'M', 'P', 'O', 'T', 'E', 'N', 'C', 'Y', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', +'\020', '\000', '\022', '\023', '\n', '\017', 'N', 'O', '_', 'S', 'I', 'D', 'E', '_', 'E', 'F', 'F', 'E', 'C', 'T', 'S', '\020', '\001', '\022', '\016', +'\n', '\n', 'I', 'D', 'E', 'M', 'P', 'O', 'T', 'E', 'N', 'T', '\020', '\002', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', +'\"', '\232', '\003', '\n', '\023', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '\022', +'A', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\002', ' ', '\003', '(', '\013', '2', '-', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', +'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', +'n', '.', 'N', 'a', 'm', 'e', 'P', 'a', 'r', 't', 'R', '\004', 'n', 'a', 'm', 'e', '\022', ')', '\n', '\020', 'i', 'd', 'e', 'n', 't', +'i', 'f', 'i', 'e', 'r', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\017', 'i', 'd', 'e', 'n', 't', 'i', +'f', 'i', 'e', 'r', 'V', 'a', 'l', 'u', 'e', '\022', ',', '\n', '\022', 'p', 'o', 's', 'i', 't', 'i', 'v', 'e', '_', 'i', 'n', 't', +'_', 'v', 'a', 'l', 'u', 'e', '\030', '\004', ' ', '\001', '(', '\004', 'R', '\020', 'p', 'o', 's', 'i', 't', 'i', 'v', 'e', 'I', 'n', 't', +'V', 'a', 'l', 'u', 'e', '\022', ',', '\n', '\022', 'n', 'e', 'g', 'a', 't', 'i', 'v', 'e', '_', 'i', 'n', 't', '_', 'v', 'a', 'l', +'u', 'e', '\030', '\005', ' ', '\001', '(', '\003', 'R', '\020', 'n', 'e', 'g', 'a', 't', 'i', 'v', 'e', 'I', 'n', 't', 'V', 'a', 'l', 'u', +'e', '\022', '!', '\n', '\014', 'd', 'o', 'u', 'b', 'l', 'e', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\006', ' ', '\001', '(', '\001', 'R', '\013', +'d', 'o', 'u', 'b', 'l', 'e', 'V', 'a', 'l', 'u', 'e', '\022', '!', '\n', '\014', 's', 't', 'r', 'i', 'n', 'g', '_', 'v', 'a', 'l', +'u', 'e', '\030', '\007', ' ', '\001', '(', '\014', 'R', '\013', 's', 't', 'r', 'i', 'n', 'g', 'V', 'a', 'l', 'u', 'e', '\022', '\'', '\n', '\017', +'a', 'g', 'g', 'r', 'e', 'g', 'a', 't', 'e', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\010', ' ', '\001', '(', '\t', 'R', '\016', 'a', 'g', +'g', 'r', 'e', 'g', 'a', 't', 'e', 'V', 'a', 'l', 'u', 'e', '\032', 'J', '\n', '\010', 'N', 'a', 'm', 'e', 'P', 'a', 'r', 't', '\022', +'\033', '\n', '\t', 'n', 'a', 'm', 'e', '_', 'p', 'a', 'r', 't', '\030', '\001', ' ', '\002', '(', '\t', 'R', '\010', 'n', 'a', 'm', 'e', 'P', +'a', 'r', 't', '\022', '!', '\n', '\014', 'i', 's', '_', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\030', '\002', ' ', '\002', '(', '\010', +'R', '\013', 'i', 's', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\"', '\247', '\002', '\n', '\016', 'S', 'o', 'u', 'r', 'c', 'e', 'C', +'o', 'd', 'e', 'I', 'n', 'f', 'o', '\022', 'D', '\n', '\010', 'l', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\030', '\001', ' ', '\003', '(', '\013', +'2', '(', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'o', 'u', 'r', 'c', 'e', +'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '.', 'L', 'o', 'c', 'a', 't', 'i', 'o', 'n', 'R', '\010', 'l', 'o', 'c', 'a', 't', 'i', +'o', 'n', '\032', '\316', '\001', '\n', '\010', 'L', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\022', '\026', '\n', '\004', 'p', 'a', 't', 'h', '\030', '\001', +' ', '\003', '(', '\005', 'B', '\002', '\020', '\001', 'R', '\004', 'p', 'a', 't', 'h', '\022', '\026', '\n', '\004', 's', 'p', 'a', 'n', '\030', '\002', ' ', +'\003', '(', '\005', 'B', '\002', '\020', '\001', 'R', '\004', 's', 'p', 'a', 'n', '\022', ')', '\n', '\020', 'l', 'e', 'a', 'd', 'i', 'n', 'g', '_', +'c', 'o', 'm', 'm', 'e', 'n', 't', 's', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\017', 'l', 'e', 'a', 'd', 'i', 'n', 'g', 'C', 'o', +'m', 'm', 'e', 'n', 't', 's', '\022', '+', '\n', '\021', 't', 'r', 'a', 'i', 'l', 'i', 'n', 'g', '_', 'c', 'o', 'm', 'm', 'e', 'n', +'t', 's', '\030', '\004', ' ', '\001', '(', '\t', 'R', '\020', 't', 'r', 'a', 'i', 'l', 'i', 'n', 'g', 'C', 'o', 'm', 'm', 'e', 'n', 't', +'s', '\022', ':', '\n', '\031', 'l', 'e', 'a', 'd', 'i', 'n', 'g', '_', 'd', 'e', 't', 'a', 'c', 'h', 'e', 'd', '_', 'c', 'o', 'm', +'m', 'e', 'n', 't', 's', '\030', '\006', ' ', '\003', '(', '\t', 'R', '\027', 'l', 'e', 'a', 'd', 'i', 'n', 'g', 'D', 'e', 't', 'a', 'c', +'h', 'e', 'd', 'C', 'o', 'm', 'm', 'e', 'n', 't', 's', '\"', '\321', '\001', '\n', '\021', 'G', 'e', 'n', 'e', 'r', 'a', 't', 'e', 'd', +'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '\022', 'M', '\n', '\n', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', '\030', '\001', ' ', +'\003', '(', '\013', '2', '-', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'G', 'e', 'n', +'e', 'r', 'a', 't', 'e', 'd', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '.', 'A', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', +'R', '\n', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', '\032', 'm', '\n', '\n', 'A', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', +'n', '\022', '\026', '\n', '\004', 'p', 'a', 't', 'h', '\030', '\001', ' ', '\003', '(', '\005', 'B', '\002', '\020', '\001', 'R', '\004', 'p', 'a', 't', 'h', +'\022', '\037', '\n', '\013', 's', 'o', 'u', 'r', 'c', 'e', '_', 'f', 'i', 'l', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\n', 's', 'o', +'u', 'r', 'c', 'e', 'F', 'i', 'l', 'e', '\022', '\024', '\n', '\005', 'b', 'e', 'g', 'i', 'n', '\030', '\003', ' ', '\001', '(', '\005', 'R', '\005', +'b', 'e', 'g', 'i', 'n', '\022', '\020', '\n', '\003', 'e', 'n', 'd', '\030', '\004', ' ', '\001', '(', '\005', 'R', '\003', 'e', 'n', 'd', 'B', '\217', +'\001', '\n', '\023', 'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\020', 'D', +'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 's', 'H', '\001', 'Z', '>', 'g', 'i', 't', 'h', 'u', 'b', +'.', 'c', 'o', 'm', '/', 'g', 'o', 'l', 'a', 'n', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'p', 'r', 'o', 't', +'o', 'c', '-', 'g', 'e', 'n', '-', 'g', 'o', '/', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', ';', 'd', 'e', 's', 'c', +'r', 'i', 'p', 't', 'o', 'r', '\370', '\001', '\001', '\242', '\002', '\003', 'G', 'P', 'B', '\252', '\002', '\032', 'G', 'o', 'o', 'g', 'l', 'e', '.', +'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'R', 'e', 'f', 'l', 'e', 'c', 't', 'i', 'o', 'n', +}; + +static upb_def_init *deps[1] = { + NULL +}; + +upb_def_init google_protobuf_descriptor_proto_upbdefinit = { + deps, + layouts, + "google/protobuf/descriptor.proto", + UPB_STRVIEW_INIT(descriptor, 7619) +}; + + +#include +#include +#include +#include + + +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; + if (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 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) { + 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; +} + +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; +} + +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_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 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 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); + l->size = UPB_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; + } + + 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); + + 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 false; + 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 < (size_t)file->ext_count; i++) { + CHK(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++) { + CHK(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->symtab, m); + } + } + + return true; + } + +static bool upb_symtab_addtotabs(upb_symtab *s, symtab_addctx *ctx) { + 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; +} + +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); +} + +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); + + 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 + +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 + + +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 */ +}; + +/** 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) { + upb_oneof_iter i; + const upb_fielddef *f; + const upb_msglayout_field *field; + const upb_msgdef *m = upb_oneofdef_containingtype(o); + uint32_t oneof_case; + + /* This is far from optimal. */ + upb_oneof_begin(&i, o); + if (upb_oneof_done(&i)) return false; + f = upb_oneof_iter_field(&i); + field = upb_fielddef_layout(f); + oneof_case = _upb_getoneofcase_field(msg, field); + + return oneof_case ? upb_msgdef_itof(m, oneof_case) : NULL; +} + +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) && _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) { + size_t i = *iter; + const upb_msgval zero = {0}; + const upb_fielddef *f; + UPB_UNUSED(ext_pool); + 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; +} + +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, 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); +} + +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); */ + + +#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 + + +#include +#include +#include +#include +#include +#include +#include + + +/* 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; +} + +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); + longjmp(d->err, 1); +} + +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); + 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); + *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; + 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 (%d != %" 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; + + 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 (%d != %" 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; + + 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 = 0.0 / 0.0; + } else if (jsondec_streql(str, "Infinity")) { + val.double_val = UPB_INFINITY; + } else if (jsondec_streql(str, "-Infinity")) { + val.double_val = -UPB_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 != UPB_INFINITY && val.double_val != -UPB_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) { + if (jsondec_peek(d) == 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; + } else { + 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 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; +} + +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, "Unknown field: '" UPB_STRVIEW_FORMAT "'", + UPB_STRVIEW_ARGS(name)); + } + jsondec_skipval(d); + return; + } + + if (upb_fielddef_containingoneof(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; + + /* "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 < -315576000000LL || seconds.int64_val > 315576000000LL) { + 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": , "f2": } + * 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": } + * where 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 (setjmp(d.err)) return false; + + jsondec_tomsg(&d, msg, m); + return true; +} + + +#include +#include +#include +#include +#include +#include +#include + + + +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_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)); +} + +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 = _upb_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, ".%0.*" 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); + 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 == UPB_INFINITY) { + jsonenc_putstr(e, "\"Infinity\""); + } else if (val == -UPB_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 (full URL: " UPB_STRVIEW_FORMAT ")", (int)(end - ptr), ptr, UPB_STRVIEW_ARGS(type_url)); + } + + 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": } */ + 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 = upb_array_size(arr); + 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, "{"); + + 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. */ + upb_msg_field_iter i; + for (upb_msg_field_begin(&i, m); !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { + f = upb_msg_iter_field(&i); + 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_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/php/ext/google/protobuf2/php-upb.h b/php/ext/google/protobuf2/php-upb.h new file mode 100644 index 0000000000..a07885ff9c --- /dev/null +++ b/php/ext/google/protobuf2/php-upb.h @@ -0,0 +1,3885 @@ +/* Amalgamated source file */ +#include /* +* 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 +#include + +#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 + +/* 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 +#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 +#include +#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() +#elif defined _MSC_VER +#define UPB_ASSUME(expr) if (!(expr)) __assume(0) +#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 +#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 +#include + +/* +** 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 homogenous (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 +#include +/* +** This file contains shared definitions that are widely used across upb. +*/ + +#ifndef UPB_H_ +#define UPB_H_ + +#include +#include +#include +#include +#include +#include + + +#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); +void upb_status_vappenderrf(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! + * 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 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((size_t)(h->end - h->ptr) < size)) { + return _upb_arena_slowmalloc(a, size); + } + + ret = h->ptr; + h->ptr += size; + 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) + + +#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; /* google.protobuf.Label or _UPB_LABEL_* above. */ +} 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); + +/* 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 ~(int64_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. */ +} 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 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_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 && 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 = _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_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, 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_hasbit(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_hasbit(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_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_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_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 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 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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_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 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_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_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 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, 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_hasbit(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_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, 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_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_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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_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(92, 160), 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(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_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_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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_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_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_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_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_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_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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_hasbit(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_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_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_hasbit(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_hasbit(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_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_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_hasbit(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_hasbit(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_hasbit(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_iswrapper(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); +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); + +/* 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_ */ +/* 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_UPBDEFS_H_ +#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPBDEFS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + + +extern upb_def_init google_protobuf_descriptor_proto_upbdefinit; + +UPB_INLINE const upb_msgdef *google_protobuf_FileDescriptorSet_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.FileDescriptorSet"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_FileDescriptorProto_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.FileDescriptorProto"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_DescriptorProto_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_DescriptorProto_ExtensionRange_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto.ExtensionRange"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_DescriptorProto_ReservedRange_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto.ReservedRange"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_ExtensionRangeOptions_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.ExtensionRangeOptions"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_FieldDescriptorProto_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.FieldDescriptorProto"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_OneofDescriptorProto_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.OneofDescriptorProto"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_EnumDescriptorProto_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.EnumDescriptorProto"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_EnumDescriptorProto_EnumReservedRange_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.EnumDescriptorProto.EnumReservedRange"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_EnumValueDescriptorProto_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.EnumValueDescriptorProto"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_ServiceDescriptorProto_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.ServiceDescriptorProto"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_MethodDescriptorProto_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.MethodDescriptorProto"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_FileOptions_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.FileOptions"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_MessageOptions_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.MessageOptions"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_FieldOptions_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.FieldOptions"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_OneofOptions_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.OneofOptions"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_EnumOptions_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.EnumOptions"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_EnumValueOptions_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.EnumValueOptions"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_ServiceOptions_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.ServiceOptions"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_MethodOptions_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.MethodOptions"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_UninterpretedOption_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.UninterpretedOption"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_UninterpretedOption_NamePart_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.UninterpretedOption.NamePart"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_SourceCodeInfo_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.SourceCodeInfo"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_SourceCodeInfo_Location_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.SourceCodeInfo.Location"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_GeneratedCodeInfo_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.GeneratedCodeInfo"); +} + +UPB_INLINE const upb_msgdef *google_protobuf_GeneratedCodeInfo_Annotation_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.protobuf.GeneratedCodeInfo.Annotation"); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPBDEFS_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 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); + + +#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. TOOD(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_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/php/ext/google/protobuf2/protobuf.c b/php/ext/google/protobuf2/protobuf.c new file mode 100644 index 0000000000..15c8f9bd72 --- /dev/null +++ b/php/ext/google/protobuf2/protobuf.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. + +#include "protobuf.h" + +#include +#include + +#include "arena.h" +#include "array.h" +#include "bundled_php.h" +#include "convert.h" +#include "def.h" +#include "map.h" +#include "message.h" +#include "names.h" + +// ----------------------------------------------------------------------------- +// Module "globals" +// ----------------------------------------------------------------------------- + +// Despite the name, module "globals" are really thread-locals: +// * PROTOBUF_G(var) accesses the thread-local variable for 'var'. Either: +// * PROTOBUF_G(var) -> protobuf_globals.var (Non-ZTS / non-thread-safe) +// * PROTOBUF_G(var) -> (ZTS / thread-safe builds) + +#define PROTOBUF_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(protobuf, v) + +ZEND_BEGIN_MODULE_GLOBALS(protobuf) + // Set by the user to make the descriptor pool persist between requests. + zend_bool keep_descriptor_pool_after_request; + + // Currently we make the generated pool a "global", which means that if a user + // does explicitly create threads within their request, the other threads will + // get different results from DescriptorPool::getGeneratedPool(). We require + // that all descriptors are loaded from the main thread. + zval generated_pool; + + // A upb_symtab that we are saving for the next request so that we don't have + // to rebuild it from scratch. When keep_descriptor_pool_after_request==true, + // we steal the upb_symtab from the global DescriptorPool object just before + // destroying it. + upb_symtab *saved_symtab; + + // Object cache (see interface in protobuf.h). + HashTable object_cache; + + // Name cache (see interface in protobuf.h). + HashTable name_msg_cache; + HashTable name_enum_cache; +ZEND_END_MODULE_GLOBALS(protobuf) + +ZEND_DECLARE_MODULE_GLOBALS(protobuf) + +const zval *get_generated_pool() { + return &PROTOBUF_G(generated_pool); +} + +// This is a PHP extension (not a Zend extension). What follows is a summary of +// a PHP extension's lifetime and when various handlers are called. +// +// * PHP_GINIT_FUNCTION(protobuf) / PHP_GSHUTDOWN_FUNCTION(protobuf) +// are the constructor/destructor for the globals. The sequence over the +// course of a process lifetime is: +// +// # Process startup +// GINIT(
) +// MINIT +// +// foreach request: +// RINIT +// # Request is processed here. +// RSHUTDOWN +// +// foreach thread: +// GINIT() +// # Code for the thread runs here. +// GSHUTDOWN() +// +// # Process Shutdown +// # +// # These should be running per the docs, but I have not been able to +// # actually get the process-wide shutdown functions to run. +// # +// # MSHUTDOWN +// # GSHUTDOWN(
) +// +// * Threads can be created either explicitly by the user, inside a request, +// or implicitly by the runtime, to process multiple requests concurrently. +// If the latter is being used, then the "foreach thread" block above +// actually looks like this: +// +// foreach thread: +// GINIT() +// # A non-main thread will only receive requests when using a threaded +// # MPM with Apache +// foreach request: +// RINIT +// # Request is processed here. +// RSHUTDOWN +// GSHUTDOWN() +// +// That said, it appears that few people use threads with PHP: +// * The pthread package documented at +// https://www.php.net/manual/en/class.thread.php nas not been released +// since 2016, and the current release fails to compile against any PHP +// newer than 7.0.33. +// * The GitHub master branch supports 7.2+, but this has not been released +// to PECL. +// * Its owner has disavowed it as "broken by design" and "in an untenable +// position for the future": https://github.com/krakjoe/pthreads/issues/929 +// * The only way to use PHP with requests in different threads is to use the +// Apache 2 mod_php with the "worker" MPM. But this is explicitly +// discouraged by the documentation: https://serverfault.com/a/231660 + +static PHP_GSHUTDOWN_FUNCTION(protobuf) { + if (protobuf_globals->saved_symtab) { + upb_symtab_free(protobuf_globals->saved_symtab); + } +} + +static PHP_GINIT_FUNCTION(protobuf) { + ZVAL_NULL(&protobuf_globals->generated_pool); + protobuf_globals->saved_symtab = NULL; +} + +/** + * PHP_RINIT_FUNCTION(protobuf) + * + * This function is run at the beginning of processing each request. + */ +static PHP_RINIT_FUNCTION(protobuf) { + // Create the global generated pool. + // Reuse the symtab (if any) left to us by the last request. + upb_symtab *symtab = PROTOBUF_G(saved_symtab); + DescriptorPool_CreateWithSymbolTable(&PROTOBUF_G(generated_pool), symtab); + + // Set up autoloader for bundled sources. + zend_eval_string("spl_autoload_register('protobuf_internal_loadbundled');", + NULL, "autoload_register.php"); + + zend_hash_init(&PROTOBUF_G(object_cache), 64, NULL, NULL, 0); + zend_hash_init(&PROTOBUF_G(name_msg_cache), 64, NULL, NULL, 0); + zend_hash_init(&PROTOBUF_G(name_enum_cache), 64, NULL, NULL, 0); + + return SUCCESS; +} + +/** + * PHP_RSHUTDOWN_FUNCTION(protobuf) + * + * This function is run at the end of processing each request. + */ +static PHP_RSHUTDOWN_FUNCTION(protobuf) { + // Preserve the symtab if requested. + if (PROTOBUF_G(keep_descriptor_pool_after_request)) { + zval *zv = &PROTOBUF_G(generated_pool); + PROTOBUF_G(saved_symtab) = DescriptorPool_Steal(zv); + } + + zval_dtor(&PROTOBUF_G(generated_pool)); + zend_hash_destroy(&PROTOBUF_G(object_cache)); + zend_hash_destroy(&PROTOBUF_G(name_msg_cache)); + zend_hash_destroy(&PROTOBUF_G(name_enum_cache)); + + return SUCCESS; +} + +// ----------------------------------------------------------------------------- +// Bundled PHP sources +// ----------------------------------------------------------------------------- + +// We bundle PHP sources for well-known types into the C extension. There is no +// need to implement these in C. + +static PHP_FUNCTION(protobuf_internal_loadbundled) { + char *name = NULL; + zend_long size; + BundledPhp_File *file; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &size) != SUCCESS) { + return; + } + + for (file = bundled_files; file->filename; file++) { + if (strcmp(file->filename, name) == 0) { + zend_eval_string((char*)file->contents, NULL, (char*)file->filename); + return; + } + } +} + +ZEND_BEGIN_ARG_INFO_EX(arginfo_load_bundled_source, 0, 0, 1) + ZEND_ARG_INFO(0, class_name) +ZEND_END_ARG_INFO() + +// ----------------------------------------------------------------------------- +// Object Cache. +// ----------------------------------------------------------------------------- + +void ObjCache_Add(const void *upb_obj, zend_object *php_obj) { + zend_ulong k = (zend_ulong)upb_obj; + zend_hash_index_add_ptr(&PROTOBUF_G(object_cache), k, php_obj); +} + +void ObjCache_Delete(const void *upb_obj) { + if (upb_obj) { + zend_ulong k = (zend_ulong)upb_obj; + int ret = zend_hash_index_del(&PROTOBUF_G(object_cache), k); + PBPHP_ASSERT(ret == SUCCESS); + } +} + +bool ObjCache_Get(const void *upb_obj, zval *val) { + zend_ulong k = (zend_ulong)upb_obj; + zend_object *obj = zend_hash_index_find_ptr(&PROTOBUF_G(object_cache), k); + + if (obj) { + GC_ADDREF(obj); + ZVAL_OBJ(val, obj); + return true; + } else { + ZVAL_NULL(val); + return false; + } +} + +// ----------------------------------------------------------------------------- +// Name Cache. +// ----------------------------------------------------------------------------- + +void NameMap_AddMessage(const upb_msgdef *m) { + char *k = GetPhpClassname(upb_msgdef_file(m), upb_msgdef_fullname(m)); + zend_hash_str_add_ptr(&PROTOBUF_G(name_msg_cache), k, strlen(k), (void*)m); + free(k); +} + +void NameMap_AddEnum(const upb_enumdef *e) { + char *k = GetPhpClassname(upb_enumdef_file(e), upb_enumdef_fullname(e)); + zend_hash_str_add_ptr(&PROTOBUF_G(name_enum_cache), k, strlen(k), (void*)e); + free(k); +} + +const upb_msgdef *NameMap_GetMessage(zend_class_entry *ce) { + const upb_msgdef *ret = + zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name); + + if (!ret && ce->create_object) { + zval tmp; + zval zv; + ZVAL_OBJ(&tmp, ce->create_object(ce)); + zend_call_method_with_0_params(&tmp, ce, NULL, "__construct", &zv); + zval_ptr_dtor(&tmp); + zval_ptr_dtor(&zv); + ret = zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name); + } + + return ret; +} + +const upb_enumdef *NameMap_GetEnum(zend_class_entry *ce) { + const upb_enumdef *ret = + zend_hash_find_ptr(&PROTOBUF_G(name_enum_cache), ce->name); + return ret; +} + +// ----------------------------------------------------------------------------- +// Module init. +// ----------------------------------------------------------------------------- + +zend_function_entry protobuf_functions[] = { + PHP_FE(protobuf_internal_loadbundled, arginfo_load_bundled_source) + ZEND_FE_END +}; + +static const zend_module_dep protobuf_deps[] = { + ZEND_MOD_OPTIONAL("date") + ZEND_MOD_END +}; + +PHP_INI_BEGIN() +STD_PHP_INI_ENTRY("protobuf.keep_descriptor_pool_after_request", "0", + PHP_INI_SYSTEM, OnUpdateBool, + keep_descriptor_pool_after_request, zend_protobuf_globals, + protobuf_globals) +PHP_INI_END() + +static PHP_MINIT_FUNCTION(protobuf) { + REGISTER_INI_ENTRIES(); + Arena_ModuleInit(); + Array_ModuleInit(); + Convert_ModuleInit(); + Def_ModuleInit(); + Map_ModuleInit(); + Message_ModuleInit(); + return SUCCESS; +} + +static PHP_MSHUTDOWN_FUNCTION(protobuf) { + return SUCCESS; +} + +zend_module_entry protobuf_module_entry = { + STANDARD_MODULE_HEADER_EX, + NULL, + protobuf_deps, + "protobuf", // extension name + protobuf_functions, // function list + PHP_MINIT(protobuf), // process startup + PHP_MSHUTDOWN(protobuf), // process shutdown + PHP_RINIT(protobuf), // request shutdown + PHP_RSHUTDOWN(protobuf), // request shutdown + NULL, // extension info + "3.13.0", // extension version + PHP_MODULE_GLOBALS(protobuf), // globals descriptor + PHP_GINIT(protobuf), // globals ctor + PHP_GSHUTDOWN(protobuf), // globals dtor + NULL, // post deactivate + STANDARD_MODULE_PROPERTIES_EX +}; + +ZEND_GET_MODULE(protobuf) diff --git a/php/ext/google/protobuf2/protobuf.h b/php/ext/google/protobuf2/protobuf.h new file mode 100644 index 0000000000..6a7afae061 --- /dev/null +++ b/php/ext/google/protobuf2/protobuf.h @@ -0,0 +1,89 @@ +// 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 PHP_PROTOBUF_H_ +#define PHP_PROTOBUF_H_ + +#include +#include + +#include "php-upb.h" + +const zval *get_generated_pool(); + +#if PHP_VERSION_ID < 70300 +#define GC_ADDREF(h) ++GC_REFCOUNT(h) +#define GC_DELREF(h) --GC_REFCOUNT(h) +#endif + +// ptr -> PHP object cache. This is a weak map that caches lazily-created +// wrapper objects around upb types: +// * upb_msg* -> Message +// * upb_array* -> RepeatedField +// * upb_map*, -> MapField +// * upb_msgdef* -> Descriptor +// * upb_enumdef* -> EnumDescriptor +// * zend_class_entry* -> Descriptor +// +// Each wrapped object should add itself to the map when it is constructed, and +// remove itself from the map when it is destroyed. This is how we ensure that +// the map only contains live objects. The map is weak so it does not actually +// take references to the cached objects. +void ObjCache_Add(const void *key, zend_object *php_obj); +void ObjCache_Delete(const void *key); +bool ObjCache_Get(const void *key, zval *val); + +// PHP class name map. This is necessary because the pb_name->php_class_name +// transformation is non-reversible, so when we need to look up a msgdef or +// enumdef by PHP class, we can't turn the class name into a pb_name. +// * php_class_name -> upb_msgdef* +// * php_class_name -> upb_enumdef* +void NameMap_AddMessage(const upb_msgdef *m); +void NameMap_AddEnum(const upb_enumdef *m); +const upb_msgdef *NameMap_GetMessage(zend_class_entry *ce); +const upb_enumdef *NameMap_GetEnum(zend_class_entry *ce); + +// We need our own assert() because PHP takes control of NDEBUG in its headers. +#ifdef PBPHP_ENABLE_ASSERTS +#define PBPHP_ASSERT(x) \ + do { \ + if (!(x)) { \ + fprintf(stderr, "Assertion failure at %s:%d %s", __FILE__, __LINE__, \ + #x); \ + abort(); \ + } \ + } while (false) +#else +#define PBPHP_ASSERT(x) \ + do { \ + } while (false && (x)) +#endif + +#endif // PHP_PROTOBUF_H_ diff --git a/php/src/Google/Protobuf/Any.php b/php/src/Google/Protobuf/Any.php index 166c66a49e..2c7bc75454 100644 --- a/php/src/Google/Protobuf/Any.php +++ b/php/src/Google/Protobuf/Any.php @@ -270,7 +270,7 @@ class Any extends \Google\Protobuf\Internal\Message // Create message according to fully qualified name. $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool(); - $desc = $pool->getDescriptorByProtoName( ".".$fully_qualifed_name); + $desc = $pool->getDescriptorByProtoName($fully_qualifed_name); if (is_null($desc)) { throw new \Exception("Class ".$fully_qualifed_name ." hasn't been added to descriptor pool"); @@ -303,8 +303,7 @@ class Any extends \Google\Protobuf\Internal\Message $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool(); $desc = $pool->getDescriptorByClassName(get_class($msg)); $fully_qualifed_name = $desc->getFullName(); - $this->type_url = GPBUtil::TYPE_URL_PREFIX.substr( - $fully_qualifed_name, 1, strlen($fully_qualifed_name)); + $this->type_url = GPBUtil::TYPE_URL_PREFIX . $fully_qualifed_name; } /** @@ -317,8 +316,7 @@ class Any extends \Google\Protobuf\Internal\Message $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool(); $desc = $pool->getDescriptorByClassName($klass); $fully_qualifed_name = $desc->getFullName(); - $type_url = GPBUtil::TYPE_URL_PREFIX.substr( - $fully_qualifed_name, 1, strlen($fully_qualifed_name)); + $type_url = GPBUtil::TYPE_URL_PREFIX . $fully_qualifed_name; return $this->type_url === $type_url; } } diff --git a/php/src/Google/Protobuf/Internal/DescriptorPool.php b/php/src/Google/Protobuf/Internal/DescriptorPool.php index f96b0fb766..2880cee641 100644 --- a/php/src/Google/Protobuf/Internal/DescriptorPool.php +++ b/php/src/Google/Protobuf/Internal/DescriptorPool.php @@ -152,6 +152,9 @@ class DescriptorPool switch ($field->getType()) { case GPBType::MESSAGE: $proto = $field->getMessageType(); + if ($proto[0] == '.') { + $proto = substr($proto, 1); + } $subdesc = $this->getDescriptorByProtoName($proto); if (is_null($subdesc)) { trigger_error( @@ -162,6 +165,9 @@ class DescriptorPool break; case GPBType::ENUM: $proto = $field->getEnumType(); + if ($proto[0] == '.') { + $proto = substr($proto, 1); + } $field->setEnumType( $this->getEnumDescriptorByProtoName($proto)); break; diff --git a/php/src/Google/Protobuf/Internal/GPBUtil.php b/php/src/Google/Protobuf/Internal/GPBUtil.php index c091fc6c81..1900e71ccc 100644 --- a/php/src/Google/Protobuf/Internal/GPBUtil.php +++ b/php/src/Google/Protobuf/Internal/GPBUtil.php @@ -338,9 +338,9 @@ class GPBUtil $package = $file_proto->getPackage(); if ($package === "") { - $fullname = "." . $message_name_without_package; + $fullname = $message_name_without_package; } else { - $fullname = "." . $package . "." . $message_name_without_package; + $fullname = $package . "." . $message_name_without_package; } $class_name_without_package = diff --git a/php/tests/compile_extension.sh b/php/tests/compile_extension.sh index ae0a6a3958..37c6810b66 100755 --- a/php/tests/compile_extension.sh +++ b/php/tests/compile_extension.sh @@ -12,7 +12,18 @@ else CFLAGS="-g -O0 -Wall" fi + pushd ../ext/google/protobuf -make clean || true +phpize --clean +rm -f configure.in configure.ac phpize && ./configure --with-php-config=$(which php-config) CFLAGS="$CFLAGS" && make popd + +if [ $(php -r "echo PHP_VERSION;" | cut -c1) != "5" ]; then + pushd ../ext/google/protobuf2 + phpize --clean + rm -f configure.in configure.ac + php make-preload.php + phpize && ./configure --with-php-config=$(which php-config) CFLAGS="$CFLAGS" && make + popd +fi diff --git a/php/tests/test.sh b/php/tests/test.sh index bb2ada36be..b1d8d5f995 100755 --- a/php/tests/test.sh +++ b/php/tests/test.sh @@ -8,12 +8,25 @@ cd $(dirname $0) ./compile_extension.sh PHP_VERSION=$(php -r "echo PHP_VERSION;") +TEST_NEW_EXTENSION=true # Each version of PHPUnit supports a fairly narrow range of PHP versions. case "$PHP_VERSION" in - 5.6.*) PHPUNIT=phpunit-5.6.8.phar;; - 7.0.*) PHPUNIT=phpunit-5.6.0.phar;; # Oddly older than for 5.6. Not sure the reason. - 7.3.*) PHPUNIT=phpunit-8.phar;; + 5.*.*) + PHPUNIT=phpunit-5.6.8.phar + TEST_NEW_EXTENSION=false + ;; + 7.0.*|7.1.*|7.2.*) + # Oddly older than for 5.6. Not sure the reason. + PHPUNIT=phpunit-5.6.0.phar + ;; + 7.3.*|7.4.*) + PHPUNIT=phpunit-8.phar + ;; + *) + echo "ERROR: Unknown PHP version $PHP_VERSION" + exit 1 + ;; esac [ -f $PHPUNIT ] || wget https://phar.phpunit.de/$PHPUNIT @@ -26,6 +39,9 @@ do echo "* $t" echo "****************************" php -dextension=../ext/google/protobuf/modules/protobuf.so $PHPUNIT --bootstrap autoload.php $t + if [ "$TEST_NEW_EXTENSION" = "true" ]; then + php -dextension=../ext/google/protobuf2/modules/protobuf.so $PHPUNIT --bootstrap autoload.php $t + fi echo "" done @@ -35,6 +51,9 @@ do echo "* $t persistent" echo "****************************" php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf/modules/protobuf.so $PHPUNIT --bootstrap autoload.php $t + if [ "$TEST_NEW_EXTENSION" = "true" ]; then + php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf2/modules/protobuf.so $PHPUNIT --bootstrap autoload.php $t + fi echo "" done @@ -45,6 +64,10 @@ export ZEND_DONT_UNLOAD_MODULES=1 export USE_ZEND_ALLOC=0 valgrind --leak-check=yes php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php valgrind --leak-check=yes php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php +if [ "$TEST_NEW_EXTENSION" = "true" ]; then + valgrind --leak-check=yes php -dextension=../ext/google/protobuf2/modules/protobuf.so memory_leak_test.php + valgrind --leak-check=yes php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf2/modules/protobuf.so memory_leak_test.php +fi # TODO(teboring): Only for debug (phpunit has memory leak which blocks this beging used by # regresssion test.) diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py index 9e84185b55..987116a106 100755 --- a/python/google/protobuf/internal/text_format_test.py +++ b/python/google/protobuf/internal/text_format_test.py @@ -142,6 +142,8 @@ class TextFormatMessageToStringTests(TextFormatBase): message.repeated_float.append(1.234e10) message.repeated_float.append(1.2345e10) message.repeated_float.append(1.23456e10) + message.repeated_float.append(float('NaN')) + message.repeated_float.append(float('inf')) message.repeated_double.append(0.0) message.repeated_double.append(0.8) message.repeated_double.append(1.0) @@ -190,6 +192,8 @@ class TextFormatMessageToStringTests(TextFormatBase): 'repeated_float: 12340000000\n' 'repeated_float: 12345000000\n' 'repeated_float: 12345600000\n' + 'repeated_float: nan\n' + 'repeated_float: inf\n' 'repeated_double: 0\n' 'repeated_double: 0.8\n' 'repeated_double: 1\n' diff --git a/python/google/protobuf/internal/type_checkers.py b/python/google/protobuf/internal/type_checkers.py index bfde1c3e36..eb66f9f6fb 100644 --- a/python/google/protobuf/internal/type_checkers.py +++ b/python/google/protobuf/internal/type_checkers.py @@ -74,11 +74,6 @@ def TruncateToFourByteFloat(original): def ToShortestFloat(original): """Returns the shortest float that has same value in wire.""" - # Return the original value if it is not truncated. This may happen - # if someone mixes this code with an old protobuf runtime. - # TODO(jieluo): Remove it after maybe 2022. - if TruncateToFourByteFloat(original) != original: - return original # All 4 byte floats have between 6 and 9 significant digits, so we # start with 6 as the lower bound. # It has to be iterative because use '.9g' directly can not get rid diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py index 8387218941..2a9a866420 100644 --- a/python/google/protobuf/text_format.py +++ b/python/google/protobuf/text_format.py @@ -46,19 +46,19 @@ __author__ = 'kenton@google.com (Kenton Varda)' import encodings.raw_unicode_escape # pylint: disable=unused-import import encodings.unicode_escape # pylint: disable=unused-import import io +import math import re - import six -if six.PY3: - long = int # pylint: disable=redefined-builtin,invalid-name - -# pylint: disable=g-import-not-at-top from google.protobuf.internal import decoder from google.protobuf.internal import type_checkers from google.protobuf import descriptor from google.protobuf import text_encoding +if six.PY3: + long = int # pylint: disable=redefined-builtin,invalid-name + +# pylint: disable=g-import-not-at-top __all__ = ['MessageToString', 'Parse', 'PrintMessage', 'PrintField', 'PrintFieldValue', 'Merge', 'MessageToBytes'] @@ -630,7 +630,10 @@ class _Printer(object): if self.float_format is not None: out.write('{1:{0}}'.format(self.float_format, value)) else: - out.write(str(type_checkers.ToShortestFloat(value))) + if math.isnan(value): + out.write(str(value)) + else: + out.write(str(type_checkers.ToShortestFloat(value))) elif (field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_DOUBLE and self.double_format is not None): out.write('{1:{0}}'.format(self.double_format, value)) diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc index 1993555f14..7eed87c5eb 100644 --- a/src/google/protobuf/any.pb.cc +++ b/src/google/protobuf/any.pb.cc @@ -91,8 +91,9 @@ bool Any::GetAnyFieldDescriptors( return ::PROTOBUF_NAMESPACE_ID::internal::GetAnyFieldDescriptors( message, type_url_field, value_field); } -bool Any::ParseAnyTypeUrl(const string& type_url, - std::string* full_type_name) { +bool Any::ParseAnyTypeUrl( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url, + std::string* full_type_name) { return ::PROTOBUF_NAMESPACE_ID::internal::ParseAnyTypeUrl(type_url, full_type_name); } diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h index 2bc234ba42..923878d73b 100644 --- a/src/google/protobuf/any.pb.h +++ b/src/google/protobuf/any.pb.h @@ -116,7 +116,7 @@ class PROTOBUF_EXPORT Any PROTOBUF_FINAL : _any_metadata_.PackFrom(message); } void PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message, - const std::string& type_url_prefix) { + ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url_prefix) { _any_metadata_.PackFrom(message, type_url_prefix); } bool UnpackTo(::PROTOBUF_NAMESPACE_ID::Message* message) const { @@ -132,7 +132,7 @@ class PROTOBUF_EXPORT Any PROTOBUF_FINAL : } template ::value>::type> void PackFrom(const T& message, - const std::string& type_url_prefix) { + ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url_prefix) { _any_metadata_.PackFrom(message, type_url_prefix);} template ::value>::type> bool UnpackTo(T* message) const { @@ -141,7 +141,7 @@ class PROTOBUF_EXPORT Any PROTOBUF_FINAL : template bool Is() const { return _any_metadata_.Is(); } - static bool ParseAnyTypeUrl(const string& type_url, + static bool ParseAnyTypeUrl(::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url, std::string* full_type_name); friend void swap(Any& a, Any& b) { a.Swap(&b); diff --git a/src/google/protobuf/any.proto b/src/google/protobuf/any.proto index 066cf60dd5..6ed8a23cf5 100644 --- a/src/google/protobuf/any.proto +++ b/src/google/protobuf/any.proto @@ -77,10 +77,13 @@ option objc_class_prefix = "GPB"; // Example 4: Pack and unpack a message in Go // // foo := &pb.Foo{...} -// any, err := ptypes.MarshalAny(foo) +// any, err := anypb.New(foo) +// if err != nil { +// ... +// } // ... // foo := &pb.Foo{} -// if err := ptypes.UnmarshalAny(any, foo); err != nil { +// if err := any.UnmarshalTo(foo); err != nil { // ... // } // diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc index 630c97e94e..39312b3adb 100644 --- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc @@ -81,13 +81,6 @@ void SetMessageVariables(const FieldDescriptor* descriptor, } else { (*variables)["lite"] = "Lite"; } - - if (!IsProto3Field(descriptor) && val->type() == FieldDescriptor::TYPE_ENUM) { - const EnumValueDescriptor* default_value = val->default_value_enum(); - (*variables)["default_enum_value"] = Int32ToString(default_value->number()); - } else { - (*variables)["default_enum_value"] = "0"; - } } MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor, @@ -105,8 +98,8 @@ void MapFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const { " $map_classname$,\n" " $key_cpp$, $val_cpp$,\n" " ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n" - " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$,\n" - " $default_enum_value$ > $name$_;\n"); + " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> " + "$name$_;\n"); } void MapFieldGenerator::GenerateAccessorDeclarations( diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index eed07dc746..7c7461fa6f 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -268,13 +268,6 @@ void CollectMapInfo(const Options& options, const Descriptor* descriptor, "TYPE_" + ToUpper(DeclaredTypeMethodName(key->type())); vars["val_wire_type"] = "TYPE_" + ToUpper(DeclaredTypeMethodName(val->type())); - if (descriptor->file()->syntax() != FileDescriptor::SYNTAX_PROTO3 && - val->type() == FieldDescriptor::TYPE_ENUM) { - const EnumValueDescriptor* default_value = val->default_value_enum(); - vars["default_enum_value"] = Int32ToString(default_value->number()); - } else { - vars["default_enum_value"] = "0"; - } } // Does the given field have a private (internal helper only) has_$name$() @@ -1017,14 +1010,13 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { "::$proto_ns$::internal::MapEntry$lite$<$classname$, \n" " $key_cpp$, $val_cpp$,\n" " ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n" - " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$,\n" - " $default_enum_value$ > {\n" + " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> {\n" "public:\n" " typedef ::$proto_ns$::internal::MapEntry$lite$<$classname$, \n" " $key_cpp$, $val_cpp$,\n" " ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n" - " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$,\n" - " $default_enum_value$ > SuperType;\n" + " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> " + "SuperType;\n" " $classname$();\n" " explicit $classname$(::$proto_ns$::Arena* arena);\n" " void MergeFrom(const $classname$& other);\n" @@ -1235,7 +1227,8 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { " _any_metadata_.PackFrom(message);\n" "}\n" "void PackFrom(const ::$proto_ns$::Message& message,\n" - " const std::string& type_url_prefix) {\n" + " ::PROTOBUF_NAMESPACE_ID::ConstStringParam " + "type_url_prefix) {\n" " _any_metadata_.PackFrom(message, type_url_prefix);\n" "}\n" "bool UnpackTo(::$proto_ns$::Message* message) const {\n" @@ -1255,7 +1248,8 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { "!std::is_convertible" "::value>::type>\n" "void PackFrom(const T& message,\n" - " const std::string& type_url_prefix) {\n" + " ::PROTOBUF_NAMESPACE_ID::ConstStringParam " + "type_url_prefix) {\n" " _any_metadata_.PackFrom(message, type_url_prefix);" "}\n" "template \n" "void PackFrom(const T& message,\n" - " const std::string& type_url_prefix) {\n" + " ::PROTOBUF_NAMESPACE_ID::ConstStringParam " + "type_url_prefix) {\n" " _any_metadata_.PackFrom(message, type_url_prefix);\n" "}\n" "template \n" @@ -1284,7 +1279,8 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { "template bool Is() const {\n" " return _any_metadata_.Is();\n" "}\n" - "static bool ParseAnyTypeUrl(const string& type_url,\n" + "static bool ParseAnyTypeUrl(::PROTOBUF_NAMESPACE_ID::ConstStringParam " + "type_url,\n" " std::string* full_type_name);\n"); } @@ -2047,8 +2043,9 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) { "}\n"); } format( - "bool $classname$::ParseAnyTypeUrl(const string& type_url,\n" - " std::string* full_type_name) {\n" + "bool $classname$::ParseAnyTypeUrl(\n" + " ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url,\n" + " std::string* full_type_name) {\n" " return ::$proto_ns$::internal::ParseAnyTypeUrl(type_url,\n" " full_type_name);\n" "}\n" diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc index 7d00402bca..b824c92f02 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -167,6 +167,12 @@ void FieldGeneratorBase::GenerateParsingCode(io::Printer* printer, bool use_pars GenerateParsingCode(printer); } +void FieldGeneratorBase::GenerateSerializationCode(io::Printer* printer, bool use_write_context) { + // for some field types the value of "use_write_context" doesn't matter, + // so we fallback to the default implementation. + GenerateSerializationCode(printer); +} + void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) { if (descriptor_->options().deprecated()) { printer->Print("[global::System.ObsoleteAttribute]\n"); diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h index 022ba21565..d22a4b6cbb 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.h +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h @@ -63,6 +63,7 @@ class FieldGeneratorBase : public SourceGeneratorBase { virtual void GenerateParsingCode(io::Printer* printer) = 0; virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context); virtual void GenerateSerializationCode(io::Printer* printer) = 0; + virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context); virtual void GenerateSerializedSizeCode(io::Printer* printer) = 0; virtual void WriteHash(io::Printer* printer) = 0; diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.cc b/src/google/protobuf/compiler/csharp/csharp_map_field.cc index 472aba63ed..44c13e2f63 100644 --- a/src/google/protobuf/compiler/csharp/csharp_map_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_map_field.cc @@ -106,9 +106,15 @@ void MapFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_parse } void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + GenerateSerializationCode(printer, true); +} + +void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) { printer->Print( variables_, - "$name$_.WriteTo(output, _map_$name$_codec);\n"); + use_write_context + ? "$name$_.WriteTo(ref output, _map_$name$_codec);\n" + : "$name$_.WriteTo(output, _map_$name$_codec);\n"); } void MapFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.h b/src/google/protobuf/compiler/csharp/csharp_map_field.h index 5054c94cc5..54156ecf54 100644 --- a/src/google/protobuf/compiler/csharp/csharp_map_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_map_field.h @@ -58,6 +58,7 @@ class MapFieldGenerator : public FieldGeneratorBase { virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context); virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context); virtual void GenerateSerializedSizeCode(io::Printer* printer); virtual void WriteHash(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index e742fc984b..d5d2b670cd 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -520,34 +520,26 @@ void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) WriteGeneratedCodeAttributes(printer); printer->Print( "public void WriteTo(pb::CodedOutputStream output) {\n"); + printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n"); printer->Indent(); + printer->Print("output.WriteRawMessage(this);\n"); + printer->Outdent(); + printer->Print("#else\n"); + printer->Indent(); + GenerateWriteToBody(printer, false); + printer->Outdent(); + printer->Print("#endif\n"); + printer->Print("}\n\n"); - // Serialize all the fields - for (int i = 0; i < fields_by_number().size(); i++) { - std::unique_ptr generator( - CreateFieldGeneratorInternal(fields_by_number()[i])); - generator->GenerateSerializationCode(printer); - } - - if (has_extension_ranges_) { - // Serialize extensions - printer->Print( - "if (_extensions != null) {\n" - " _extensions.WriteTo(output);\n" - "}\n"); - } - - // Serialize unknown fields - printer->Print( - "if (_unknownFields != null) {\n" - " _unknownFields.WriteTo(output);\n" - "}\n"); - - // TODO(jonskeet): Memoize size of frozen messages? + printer->Print("#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE\n"); + WriteGeneratedCodeAttributes(printer); + printer->Print("void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {\n"); + printer->Indent(); + GenerateWriteToBody(printer, true); printer->Outdent(); - printer->Print( - "}\n" - "\n"); + printer->Print("}\n"); + printer->Print("#endif\n\n"); + WriteGeneratedCodeAttributes(printer); printer->Print( "public int CalculateSize() {\n"); @@ -576,6 +568,39 @@ void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) printer->Print("}\n\n"); } +void MessageGenerator::GenerateWriteToBody(io::Printer* printer, bool use_write_context) { + // Serialize all the fields + for (int i = 0; i < fields_by_number().size(); i++) { + std::unique_ptr generator( + CreateFieldGeneratorInternal(fields_by_number()[i])); + generator->GenerateSerializationCode(printer, use_write_context); + } + + if (has_extension_ranges_) { + // Serialize extensions + printer->Print( + use_write_context + ? "if (_extensions != null) {\n" + " _extensions.WriteTo(ref output);\n" + "}\n" + : "if (_extensions != null) {\n" + " _extensions.WriteTo(output);\n" + "}\n"); + } + + // Serialize unknown fields + printer->Print( + use_write_context + ? "if (_unknownFields != null) {\n" + " _unknownFields.WriteTo(ref output);\n" + "}\n" + : "if (_unknownFields != null) {\n" + " _unknownFields.WriteTo(output);\n" + "}\n"); + + // TODO(jonskeet): Memoize size of frozen messages? +} + void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { // Note: These are separate from GenerateMessageSerializationMethods() // because they need to be generated even for messages that are optimized diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h index dde85e0394..d02767e44b 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.h +++ b/src/google/protobuf/compiler/csharp/csharp_message.h @@ -66,6 +66,7 @@ class MessageGenerator : public SourceGeneratorBase { bool has_extension_ranges_; void GenerateMessageSerializationMethods(io::Printer* printer); + void GenerateWriteToBody(io::Printer* printer, bool use_write_context); void GenerateMergingMethods(io::Printer* printer); void GenerateMainParseLoop(io::Printer* printer, bool use_parse_context); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc index 402e44c278..04bc7bbb1b 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc @@ -90,9 +90,15 @@ void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer, bool } void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + GenerateSerializationCode(printer, true); +} + +void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) { printer->Print( variables_, - "$name$_.WriteTo(output, _repeated_$name$_codec);\n"); + use_write_context + ? "$name$_.WriteTo(ref output, _repeated_$name$_codec);\n" + : "$name$_.WriteTo(output, _repeated_$name$_codec);\n"); } void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h index 4ce13e646d..9b9ebd48fa 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h @@ -61,6 +61,7 @@ class RepeatedEnumFieldGenerator : public FieldGeneratorBase { virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context); virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context); virtual void GenerateSerializedSizeCode(io::Printer* printer); virtual void GenerateExtensionCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc index 4483740962..8a93cd13cf 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc @@ -105,9 +105,15 @@ void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer, bo } void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + GenerateSerializationCode(printer, true); +} + +void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) { printer->Print( variables_, - "$name$_.WriteTo(output, _repeated_$name$_codec);\n"); + use_write_context + ? "$name$_.WriteTo(ref output, _repeated_$name$_codec);\n" + : "$name$_.WriteTo(output, _repeated_$name$_codec);\n"); } void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h index 2cf33a4752..90441b82ef 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h @@ -61,6 +61,7 @@ class RepeatedMessageFieldGenerator : public FieldGeneratorBase { virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context); virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context); virtual void GenerateSerializedSizeCode(io::Printer* printer); virtual void GenerateExtensionCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc index 9231210826..0eacf91ce6 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc @@ -90,9 +90,15 @@ void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer, } void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + GenerateSerializationCode(printer, true); +} + +void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) { printer->Print( variables_, - "$name$_.WriteTo(output, _repeated_$name$_codec);\n"); + use_write_context + ? "$name$_.WriteTo(ref output, _repeated_$name$_codec);\n" + : "$name$_.WriteTo(output, _repeated_$name$_codec);\n"); } void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h index 58db62d01c..23e77a9a2e 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h @@ -57,6 +57,7 @@ class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase { virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context); virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context); virtual void GenerateSerializedSizeCode(io::Printer* printer); virtual void GenerateExtensionCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc index 24381dd233..578f54ba69 100644 --- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc @@ -132,11 +132,19 @@ void WrapperFieldGenerator::GenerateParsingCode(io::Printer* printer, bool use_p } void WrapperFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + GenerateSerializationCode(printer, true); +} + +void WrapperFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) { printer->Print( variables_, - "if ($has_property_check$) {\n" - " _single_$name$_codec.WriteTagAndValue(output, $property_name$);\n" - "}\n"); + use_write_context + ? "if ($has_property_check$) {\n" + " _single_$name$_codec.WriteTagAndValue(ref output, $property_name$);\n" + "}\n" + : "if ($has_property_check$) {\n" + " _single_$name$_codec.WriteTagAndValue(output, $property_name$);\n" + "}\n"); } void WrapperFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { @@ -269,12 +277,20 @@ void WrapperOneofFieldGenerator::GenerateParsingCode(io::Printer* printer, bool } void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + GenerateSerializationCode(printer, true); +} + +void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer, bool use_write_context) { // TODO: I suspect this is wrong... printer->Print( variables_, - "if ($has_property_check$) {\n" - " _oneof_$name$_codec.WriteTagAndValue(output, ($type_name$) $oneof_name$_);\n" - "}\n"); + use_write_context + ? "if ($has_property_check$) {\n" + " _oneof_$name$_codec.WriteTagAndValue(ref output, ($type_name$) $oneof_name$_);\n" + "}\n" + : "if ($has_property_check$) {\n" + " _oneof_$name$_codec.WriteTagAndValue(output, ($type_name$) $oneof_name$_);\n" + "}\n"); } void WrapperOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h index 438080d5b9..e9bd043f22 100644 --- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h @@ -60,6 +60,7 @@ class WrapperFieldGenerator : public FieldGeneratorBase { virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context); virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context); virtual void GenerateSerializedSizeCode(io::Printer* printer); virtual void GenerateExtensionCode(io::Printer* printer); @@ -86,6 +87,7 @@ class WrapperOneofFieldGenerator : public WrapperFieldGenerator { virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer, bool use_parse_context); virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer, bool use_write_context); virtual void GenerateSerializedSizeCode(io::Printer* printer); }; diff --git a/src/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc index d5073eeb17..3e6ecefe01 100644 --- a/src/google/protobuf/extension_set_unittest.cc +++ b/src/google/protobuf/extension_set_unittest.cc @@ -1105,8 +1105,6 @@ TEST(ExtensionSetTest, RepeatedFields) { ASSERT_EQ(msg_const_iter->bb(), 1234); } - // Test range-based for as well, but only if compiled as C++11. -#if __cplusplus >= 201103L // Test one primitive field. for (auto& x : *message.MutableRepeatedExtension(unittest::repeated_int32_extension)) { @@ -1134,7 +1132,6 @@ TEST(ExtensionSetTest, RepeatedFields) { unittest::repeated_nested_message_extension)) { ASSERT_EQ(x.bb(), 4321); } -#endif } // From b/12926163 diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc index ff839467cb..6853b1ac3a 100644 --- a/src/google/protobuf/io/tokenizer.cc +++ b/src/google/protobuf/io/tokenizer.cc @@ -940,14 +940,15 @@ static void AppendUTF8(uint32 code_point, std::string* output) { tmp = 0x00e08080 | ((code_point & 0xf000) << 4) | ((code_point & 0x0fc0) << 2) | (code_point & 0x003f); len = 3; - } else if (code_point <= 0x1fffff) { + } else if (code_point <= 0x10ffff) { tmp = 0xf0808080 | ((code_point & 0x1c0000) << 6) | ((code_point & 0x03f000) << 4) | ((code_point & 0x000fc0) << 2) | (code_point & 0x003f); len = 4; } else { - // UTF-16 is only defined for code points up to 0x10FFFF, and UTF-8 is - // normally only defined up to there as well. + // Unicode code points end at 0x10FFFF, so this is out-of-range. + // ConsumeString permits hex values up to 0x1FFFFF, and FetchUnicodePoint + // doesn't perform a range check. StringAppendF(output, "\\U%08x", code_point); return; } diff --git a/src/google/protobuf/io/tokenizer_unittest.cc b/src/google/protobuf/io/tokenizer_unittest.cc index b14eddf9d8..91c440cebf 100644 --- a/src/google/protobuf/io/tokenizer_unittest.cc +++ b/src/google/protobuf/io/tokenizer_unittest.cc @@ -808,8 +808,11 @@ TEST_F(TokenizerTest, ParseString) { Tokenizer::ParseString("'\\ud852XX'", &output); EXPECT_EQ("\xed\xa1\x92XX", output); // Malformed escape: Demons may fly out of the nose. - Tokenizer::ParseString("\\u0", &output); + Tokenizer::ParseString("'\\u0'", &output); EXPECT_EQ("u0", output); + // Beyond the range of valid UTF-32 code units. + Tokenizer::ParseString("'\\U00110000\\U00200000\\UFFFFFFFF'", &output); + EXPECT_EQ("\\U00110000\\U00200000\\Uffffffff", output); // Test invalid strings that will never be tokenized as strings. #ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h index a1722db0ec..c3cfb4318a 100644 --- a/src/google/protobuf/map.h +++ b/src/google/protobuf/map.h @@ -76,12 +76,12 @@ struct is_proto_enum; namespace internal { template + WireFormatLite::FieldType value_wire_type> class MapFieldLite; template + WireFormatLite::FieldType value_wire_type> class MapField; template @@ -133,8 +133,7 @@ class MapAllocator { } } -#if __cplusplus >= 201103L && !defined(GOOGLE_PROTOBUF_OS_APPLE) && \ - !defined(GOOGLE_PROTOBUF_OS_NACL) && \ +#if !defined(GOOGLE_PROTOBUF_OS_APPLE) && !defined(GOOGLE_PROTOBUF_OS_NACL) && \ !defined(GOOGLE_PROTOBUF_OS_EMSCRIPTEN) template void construct(NodeType* p, Args&&... args) { @@ -252,6 +251,76 @@ struct TransparentSupport { }; #endif // defined(__cpp_lib_string_view) +template +using TreeForMap = + std::map, void*, typename TransparentSupport::less, + MapAllocator, void*>>>; + +inline bool TableEntryIsEmpty(void* const* table, size_t b) { + return table[b] == nullptr; +} +inline bool TableEntryIsNonEmptyList(void* const* table, size_t b) { + return table[b] != nullptr && table[b] != table[b ^ 1]; +} +inline bool TableEntryIsTree(void* const* table, size_t b) { + return !TableEntryIsEmpty(table, b) && !TableEntryIsNonEmptyList(table, b); +} +inline bool TableEntryIsList(void* const* table, size_t b) { + return !TableEntryIsTree(table, b); +} + +// This captures all numeric types. +inline size_t MapValueSpaceUsedExcludingSelfLong(bool) { return 0; } +inline size_t MapValueSpaceUsedExcludingSelfLong(const std::string& str) { + return StringSpaceUsedExcludingSelfLong(str); +} +template ().SpaceUsedLong())> +size_t MapValueSpaceUsedExcludingSelfLong(const T& message) { + return message.SpaceUsedLong() - sizeof(T); +} + +// Space used for the table, trees, and nodes. +// Does not include the indirect space used. Eg the data of a std::string. +template +PROTOBUF_NOINLINE size_t SpaceUsedInTable(void** table, size_t num_buckets, + size_t num_elements, + size_t sizeof_node) { + size_t size = 0; + // The size of the table. + size += sizeof(void*) * num_buckets; + // All the nodes. + size += sizeof_node * num_elements; + // For each tree, count the overhead of the those nodes. + // Two buckets at a time because we only care about trees. + for (size_t b = 0; b < num_buckets; b += 2) { + if (internal::TableEntryIsTree(table, b)) { + using Tree = TreeForMap; + Tree* tree = static_cast(table[b]); + // Estimated cost of the red-black tree nodes, 3 pointers plus a + // bool (plus alignment, so 4 pointers). + size += tree->size() * + (sizeof(typename Tree::value_type) + sizeof(void*) * 4); + } + } + return size; +} + +template ::value || + !std::is_scalar::value>::type> +size_t SpaceUsedInValues(const Map* map) { + size_t size = 0; + for (const auto& v : *map) { + size += internal::MapValueSpaceUsedExcludingSelfLong(v.first) + + internal::MapValueSpaceUsedExcludingSelfLong(v.second); + } + return size; +} + +inline size_t SpaceUsedInValues(const void*) { return 0; } + } // namespace internal // This is the class for Map's internal value_type. Instead of using @@ -308,11 +377,10 @@ class Map { using size_type = size_t; using hasher = typename internal::TransparentSupport::hash; - Map() : arena_(nullptr), default_enum_value_(0) { Init(); } - explicit Map(Arena* arena) : arena_(arena), default_enum_value_(0) { Init(); } + Map() : arena_(nullptr) { Init(); } + explicit Map(Arena* arena) : arena_(arena) { Init(); } - Map(const Map& other) - : arena_(nullptr), default_enum_value_(other.default_enum_value_) { + Map(const Map& other) : arena_(nullptr) { Init(); insert(other.begin(), other.end()); } @@ -336,8 +404,7 @@ class Map { } template - Map(const InputIt& first, const InputIt& last) - : arena_(nullptr), default_enum_value_(0) { + Map(const InputIt& first, const InputIt& last) : arena_(nullptr) { Init(); insert(first, last); } @@ -421,11 +488,7 @@ class Map { // The value is a void* pointing to Node. We use void* instead of Node* to // avoid code bloat. That way there is only one instantiation of the tree // class per key type. - using TreeAllocator = typename Allocator::template rebind< - std::pair, void*>>::other; - using Tree = std::map, void*, - typename internal::TransparentSupport::less, - TreeAllocator>; + using Tree = internal::TreeForMap; using TreeIterator = typename Tree::iterator; static Node* NodeFromTreeIterator(TreeIterator it) { @@ -675,6 +738,11 @@ class Map { } } + size_t SpaceUsedInternal() const { + return internal::SpaceUsedInTable(table_, num_buckets_, + num_elements_, sizeof(Node)); + } + private: const_iterator find(const Key& k, TreeIterator* it) const { return FindHelper(k, it).first; @@ -835,9 +903,9 @@ class Map { const size_type start = index_of_first_non_null_; index_of_first_non_null_ = num_buckets_; for (size_type i = start; i < old_table_size; i++) { - if (TableEntryIsNonEmptyList(old_table, i)) { + if (internal::TableEntryIsNonEmptyList(old_table, i)) { TransferList(old_table, i); - } else if (TableEntryIsTree(old_table, i)) { + } else if (internal::TableEntryIsTree(old_table, i)) { TransferTree(old_table, i++); } } @@ -873,29 +941,16 @@ class Map { } bool TableEntryIsEmpty(size_type b) const { - return TableEntryIsEmpty(table_, b); + return internal::TableEntryIsEmpty(table_, b); } bool TableEntryIsNonEmptyList(size_type b) const { - return TableEntryIsNonEmptyList(table_, b); + return internal::TableEntryIsNonEmptyList(table_, b); } bool TableEntryIsTree(size_type b) const { - return TableEntryIsTree(table_, b); + return internal::TableEntryIsTree(table_, b); } bool TableEntryIsList(size_type b) const { - return TableEntryIsList(table_, b); - } - static bool TableEntryIsEmpty(void* const* table, size_type b) { - return table[b] == nullptr; - } - static bool TableEntryIsNonEmptyList(void* const* table, size_type b) { - return table[b] != nullptr && table[b] != table[b ^ 1]; - } - static bool TableEntryIsTree(void* const* table, size_type b) { - return !TableEntryIsEmpty(table, b) && - !TableEntryIsNonEmptyList(table, b); - } - static bool TableEntryIsList(void* const* table, size_type b) { - return !TableEntryIsTree(table, b); + return internal::TableEntryIsList(table_, b); } void TreeConvert(size_type b) { @@ -1231,7 +1286,6 @@ class Map { void swap(Map& other) { if (arena_ == other.arena_) { - std::swap(default_enum_value_, other.default_enum_value_); std::swap(elements_, other.elements_); } else { // TODO(zuguang): optimize this. The temporary copy can be allocated @@ -1247,14 +1301,13 @@ class Map { // be modified to return a const reference in the future. hasher hash_function() const { return elements_->hash_function(); } - private: - // Set default enum value only for proto2 map field whose value is enum type. - void SetDefaultEnumValue(int default_enum_value) { - default_enum_value_ = default_enum_value; + size_t SpaceUsedExcludingSelfLong() const { + return sizeof(InnerMap) + elements_->SpaceUsedInternal() + + internal::SpaceUsedInValues(this); } + private: Arena* arena_; - int default_enum_value_; InnerMap* elements_; friend class Arena; @@ -1262,8 +1315,7 @@ class Map { using DestructorSkippable_ = void; template + internal::WireFormatLite::FieldType value_wire_type> friend class internal::MapFieldLite; }; diff --git a/src/google/protobuf/map_entry.h b/src/google/protobuf/map_entry.h index 4e6a3e34e7..180ff0e70a 100644 --- a/src/google/protobuf/map_entry.h +++ b/src/google/protobuf/map_entry.h @@ -51,7 +51,7 @@ class Arena; namespace internal { template + WireFormatLite::FieldType kValueFieldType> class MapField; } } // namespace protobuf @@ -86,19 +86,17 @@ namespace internal { // // The in-memory types of primitive types can be inferred from its proto type, // while we need to explicitly specify the cpp type if proto type is -// TYPE_MESSAGE to infer the in-memory type. Moreover, default_enum_value is -// used to initialize enum field in proto2. +// TYPE_MESSAGE to infer the in-memory type. template -class MapEntry - : public MapEntryImpl { + WireFormatLite::FieldType kValueFieldType> +class MapEntry : public MapEntryImpl { public: MapEntry() : _internal_metadata_(NULL) {} explicit MapEntry(Arena* arena) : MapEntryImpl(arena), + kValueFieldType>(arena), _internal_metadata_(arena) {} ~MapEntry() { Message::_internal_metadata_.Delete(); @@ -107,13 +105,11 @@ class MapEntry typedef void InternalArenaConstructable_; typedef void DestructorSkippable_; + typedef typename MapEntryImpl::KeyTypeHandler KeyTypeHandler; typedef typename MapEntryImpl::KeyTypeHandler - KeyTypeHandler; - typedef typename MapEntryImpl< - Derived, Message, Key, Value, kKeyFieldType, kValueFieldType, - default_enum_value>::ValueTypeHandler ValueTypeHandler; + kValueFieldType>::ValueTypeHandler ValueTypeHandler; size_t SpaceUsedLong() const override { size_t size = sizeof(Derived); size += KeyTypeHandler::SpaceUsedInMapEntryLong(this->key_); @@ -126,8 +122,7 @@ class MapEntry private: friend class ::PROTOBUF_NAMESPACE_ID::Arena; template + WireFormatLite::FieldType k_wire_type, WireFormatLite::FieldType> friend class internal::MapField; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry); @@ -136,26 +131,24 @@ class MapEntry // Specialization for the full runtime template -struct MapEntryHelper > - : MapEntryHelper > { + WireFormatLite::FieldType kValueFieldType> +struct MapEntryHelper< + MapEntry > + : MapEntryHelper< + MapEntryLite > { explicit MapEntryHelper(const MapPair& map_pair) - : MapEntryHelper >( + : MapEntryHelper< + MapEntryLite >( map_pair) {} }; template -struct DeconstructMapEntry > { + WireFormatLite::FieldType key, WireFormatLite::FieldType value> +struct DeconstructMapEntry > { typedef K Key; typedef V Value; static constexpr WireFormatLite::FieldType kKeyFieldType = key; static constexpr WireFormatLite::FieldType kValueFieldType = value; - static constexpr int default_enum_value = default_enum; }; } // namespace internal diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h index 161d08dbbf..6b5d4e8fdf 100644 --- a/src/google/protobuf/map_entry_lite.h +++ b/src/google/protobuf/map_entry_lite.h @@ -55,11 +55,11 @@ namespace protobuf { namespace internal { template + WireFormatLite::FieldType kValueFieldType> class MapEntry; template + WireFormatLite::FieldType kValueFieldType> class MapFieldLite; } // namespace internal } // namespace protobuf @@ -93,11 +93,7 @@ struct MoveHelper { // messages template struct MoveHelper { // strings and similar static void Move(T* src, T* dest) { -#if __cplusplus >= 201103L *dest = std::move(*src); -#else - dest->swap(*src); -#endif } }; @@ -144,7 +140,7 @@ struct MapEntryFuncs { // the eventual code to the template code. template + WireFormatLite::FieldType kValueFieldType> class MapEntryImpl : public Base { public: typedef MapEntryFuncs Funcs; @@ -185,19 +181,16 @@ class MapEntryImpl : public Base { typedef Value EntryValueType; static const WireFormatLite::FieldType kEntryKeyFieldType = kKeyFieldType; static const WireFormatLite::FieldType kEntryValueFieldType = kValueFieldType; - static const int kEntryDefaultEnumValue = default_enum_value; MapEntryImpl() { KeyTypeHandler::Initialize(&key_, NULL); - ValueTypeHandler::InitializeMaybeByDefaultEnum(&value_, default_enum_value, - NULL); + ValueTypeHandler::Initialize(&value_, NULL); _has_bits_[0] = 0; } explicit MapEntryImpl(Arena* arena) : Base(arena) { KeyTypeHandler::Initialize(&key_, arena); - ValueTypeHandler::InitializeMaybeByDefaultEnum(&value_, default_enum_value, - arena); + ValueTypeHandler::Initialize(&value_, arena); _has_bits_[0] = 0; } @@ -325,8 +318,7 @@ class MapEntryImpl : public Base { public: void Clear() override { KeyTypeHandler::Clear(&key_, Base::GetArena()); - ValueTypeHandler::ClearMaybeByDefaultEnum(&value_, Base::GetArena(), - default_enum_value); + ValueTypeHandler::Clear(&value_, Base::GetArena()); clear_has_key(); clear_has_value(); } @@ -520,10 +512,10 @@ class MapEntryImpl : public Base { typedef void InternalArenaConstructable_; typedef void DestructorSkippable_; template + WireFormatLite::FieldType> friend class internal::MapEntry; template + WireFormatLite::FieldType> friend class internal::MapFieldLite; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryImpl); @@ -531,13 +523,12 @@ class MapEntryImpl : public Base { template -class MapEntryLite - : public MapEntryImpl { + WireFormatLite::FieldType kValueFieldType> +class MapEntryLite : public MapEntryImpl { public: typedef MapEntryImpl + kValueFieldType> SuperType; MapEntryLite() {} explicit MapEntryLite(Arena* arena) : SuperType(arena) {} @@ -554,13 +545,12 @@ template struct DeconstructMapEntry; template -struct DeconstructMapEntry > { + WireFormatLite::FieldType value> +struct DeconstructMapEntry > { typedef K Key; typedef V Value; static const WireFormatLite::FieldType kKeyFieldType = key; static const WireFormatLite::FieldType kValueFieldType = value; - static const int default_enum_value = default_enum; }; // Helpers for deterministic serialization ============================= @@ -631,9 +621,9 @@ struct MapEntryHelper; template -struct MapEntryHelper > { + WireFormatLite::FieldType kValueFieldType> +struct MapEntryHelper< + MapEntryLite > { // Provide utilities to parse/serialize key/value. Provide utilities to // manipulate internal stored type. typedef MapTypeHandler KeyTypeHandler; diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h index 9ea3fad80d..efca5ee83c 100644 --- a/src/google/protobuf/map_field.h +++ b/src/google/protobuf/map_field.h @@ -425,7 +425,7 @@ class TypeDefinedMapFieldBase : public MapFieldBase { // directly. template + WireFormatLite::FieldType kValueFieldType> class MapField : public TypeDefinedMapFieldBase { // Provide utilities to parse/serialize key/value. Provide utilities to // manipulate internal stored type. @@ -436,8 +436,7 @@ class MapField : public TypeDefinedMapFieldBase { typedef Derived EntryType; // Define abbreviation for parent MapFieldLite - typedef MapFieldLite + typedef MapFieldLite MapFieldLiteType; // Enum needs to be handled differently from other types because it has @@ -522,10 +521,9 @@ class MapField : public TypeDefinedMapFieldBase { template + WireFormatLite::FieldType value_wire_type> bool AllAreInitialized( - const MapField& field) { + const MapField& field) { const auto& t = field.GetMap(); for (typename Map::const_iterator it = t.begin(); it != t.end(); ++it) { @@ -536,12 +534,10 @@ bool AllAreInitialized( template -struct MapEntryToMapField> { - typedef MapField - MapFieldType; + WireFormatLite::FieldType kValueFieldType> +struct MapEntryToMapField< + MapEntry> { + typedef MapField MapFieldType; }; class PROTOBUF_EXPORT DynamicMapField @@ -675,8 +671,7 @@ class PROTOBUF_EXPORT MapValueRef { private: template + internal::WireFormatLite::FieldType value_wire_type> friend class internal::MapField; template friend class internal::TypeDefinedMapFieldBase; @@ -778,8 +773,7 @@ class PROTOBUF_EXPORT MapIterator { friend class internal::DynamicMapField; template + internal::WireFormatLite::FieldType kValueFieldType> friend class internal::MapField; // reinterpret_cast from heap-allocated Map<...>::iterator*. MapIterator owns diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h index 7baaa5ff31..6b6a87ead2 100644 --- a/src/google/protobuf/map_field_inl.h +++ b/src/google/protobuf/map_field_inl.h @@ -164,18 +164,16 @@ void TypeDefinedMapFieldBase::CopyIterator( template -int MapField::size() const { + WireFormatLite::FieldType kValueFieldType> +int MapField::size() const { MapFieldBase::SyncMapWithRepeatedField(); return static_cast(impl_.GetMap().size()); } template -void MapField::Clear() { + WireFormatLite::FieldType kValueFieldType> +void MapField::Clear() { if (this->MapFieldBase::repeated_field_ != nullptr) { RepeatedPtrField* repeated_field = reinterpret_cast*>( @@ -192,9 +190,9 @@ void MapField -void MapField::SetMapIteratorValue(MapIterator* map_iter) + WireFormatLite::FieldType kValueFieldType> +void MapField::SetMapIteratorValue(MapIterator* map_iter) const { const Map& map = impl_.GetMap(); typename Map::const_iterator iter = @@ -206,9 +204,9 @@ void MapField -bool MapField::ContainsMapKey(const MapKey& map_key) const { + WireFormatLite::FieldType kValueFieldType> +bool MapField::ContainsMapKey( + const MapKey& map_key) const { const Map& map = impl_.GetMap(); const Key& key = UnwrapMapKey(map_key); typename Map::const_iterator iter = map.find(key); @@ -217,10 +215,10 @@ bool MapField -bool MapField::InsertOrLookupMapValue(const MapKey& map_key, - MapValueRef* val) { + WireFormatLite::FieldType kValueFieldType> +bool MapField::InsertOrLookupMapValue(const MapKey& map_key, + MapValueRef* val) { // Always use mutable map because users may change the map value by // MapValueRef. Map* map = MutableMap(); @@ -238,18 +236,18 @@ bool MapField -bool MapField::DeleteMapValue(const MapKey& map_key) { + WireFormatLite::FieldType kValueFieldType> +bool MapField::DeleteMapValue( + const MapKey& map_key) { const Key& key = UnwrapMapKey(map_key); return MutableMap()->erase(key); } template -void MapField::MergeFrom(const MapFieldBase& other) { + WireFormatLite::FieldType kValueFieldType> +void MapField::MergeFrom( + const MapFieldBase& other) { MapFieldBase::SyncMapWithRepeatedField(); const MapField& other_field = static_cast(other); other_field.SyncMapWithRepeatedField(); @@ -259,9 +257,9 @@ void MapField -void MapField::Swap(MapFieldBase* other) { + WireFormatLite::FieldType kValueFieldType> +void MapField::Swap( + MapFieldBase* other) { MapField* other_field = down_cast(other); std::swap(this->MapFieldBase::repeated_field_, other_field->repeated_field_); impl_.Swap(&other_field->impl_); @@ -274,9 +272,9 @@ void MapField -void MapField::SyncRepeatedFieldWithMapNoLock() const { + WireFormatLite::FieldType kValueFieldType> +void MapField::SyncRepeatedFieldWithMapNoLock() const { if (this->MapFieldBase::repeated_field_ == NULL) { if (this->MapFieldBase::arena_ == NULL) { this->MapFieldBase::repeated_field_ = new RepeatedPtrField(); @@ -311,9 +309,9 @@ void MapField -void MapField::SyncMapWithRepeatedFieldNoLock() const { + WireFormatLite::FieldType kValueFieldType> +void MapField::SyncMapWithRepeatedFieldNoLock() const { Map* map = const_cast(this)->impl_.MutableMap(); RepeatedPtrField* repeated_field = reinterpret_cast*>( @@ -334,20 +332,15 @@ void MapField -size_t MapField::SpaceUsedExcludingSelfNoLock() const { + WireFormatLite::FieldType kValueFieldType> +size_t MapField::SpaceUsedExcludingSelfNoLock() const { size_t size = 0; if (this->MapFieldBase::repeated_field_ != NULL) { size += this->MapFieldBase::repeated_field_->SpaceUsedExcludingSelfLong(); } - Map* map = const_cast(this)->impl_.MutableMap(); - size += sizeof(*map); - for (typename Map::iterator it = map->begin(); it != map->end(); - ++it) { - size += KeyTypeHandler::SpaceUsedInMapLong(it->first); - size += ValueTypeHandler::SpaceUsedInMapLong(it->second); - } + size += impl_.GetMap().SpaceUsedExcludingSelfLong(); + return size; } } // namespace internal diff --git a/src/google/protobuf/map_field_lite.h b/src/google/protobuf/map_field_lite.h index d641d17333..db0ddc9446 100644 --- a/src/google/protobuf/map_field_lite.h +++ b/src/google/protobuf/map_field_lite.h @@ -54,7 +54,7 @@ namespace internal { // directly. template + WireFormatLite::FieldType value_wire_type> class MapFieldLite { // Define message type for internal repeated field. typedef Derived EntryType; @@ -63,9 +63,9 @@ class MapFieldLite { typedef Map MapType; typedef EntryType EntryTypeTrait; - MapFieldLite() { SetDefaultEnumValue(); } + MapFieldLite() {} - explicit MapFieldLite(Arena* arena) : map_(arena) { SetDefaultEnumValue(); } + explicit MapFieldLite(Arena* arena) : map_(arena) {} // Accessors const Map& GetMap() const { return map_; } @@ -82,11 +82,6 @@ class MapFieldLite { } void Swap(MapFieldLite* other) { map_.swap(other->map_); } - // Set default enum value only for proto2 map field whose value is enum type. - void SetDefaultEnumValue() { - MutableMap()->SetDefaultEnumValue(default_enum_value); - } - // Used in the implementation of parsing. Caller should take the ownership iff // arena_ is NULL. EntryType* NewEntry() const { @@ -154,10 +149,9 @@ EnumParseWrapper InitEnumParseWrapper( // We want the C++ compiler to inline this or not as it sees fit. template -bool AllAreInitialized( - const MapFieldLite& field) { + WireFormatLite::FieldType value_wire_type> +bool AllAreInitialized(const MapFieldLite& field) { const auto& t = field.GetMap(); for (typename Map::const_iterator it = t.begin(); it != t.end(); ++it) { @@ -171,13 +165,12 @@ struct MapEntryToMapField : MapEntryToMapField {}; template -struct MapEntryToMapField> { - typedef MapFieldLite, - Key, Value, kKeyFieldType, kValueFieldType, - default_enum_value> + WireFormatLite::FieldType kValueFieldType> +struct MapEntryToMapField< + MapEntryLite> { + typedef MapFieldLite< + MapEntryLite, Key, Value, + kKeyFieldType, kValueFieldType> MapFieldType; }; diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc index 5ccb7b0d99..f05d68d7d0 100644 --- a/src/google/protobuf/map_field_test.cc +++ b/src/google/protobuf/map_field_test.cc @@ -99,7 +99,7 @@ class MapFieldBasePrimitiveTest : public ::testing::Test { protected: typedef unittest::TestMap_MapInt32Int32Entry_DoNotUse EntryType; typedef MapField + WireFormatLite::TYPE_INT32> MapFieldType; MapFieldBasePrimitiveTest() { @@ -203,7 +203,7 @@ class MapFieldStateTest : public testing::TestWithParam { protected: typedef unittest::TestMap_MapInt32Int32Entry_DoNotUse EntryType; typedef MapField + WireFormatLite::TYPE_INT32> MapFieldType; MapFieldStateTest() : state_(GetParam()) { // Build map field diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc index ab88dd03d7..9256f0e97f 100644 --- a/src/google/protobuf/map_test.cc +++ b/src/google/protobuf/map_test.cc @@ -980,6 +980,46 @@ TEST_F(MapImplTest, CopyAssignMapIterator) { EXPECT_EQ(it1.GetKey().GetInt32Value(), it2.GetKey().GetInt32Value()); } +TEST_F(MapImplTest, SpaceUsed) { + constexpr size_t kMinCap = 8; + constexpr size_t kInnerMapOverhead = sizeof(size_t) * 4 + sizeof(void*) * 2; + + Map m; + // To check the current overhead of an empty map. + // Ideally this should be zero. + EXPECT_EQ(m.SpaceUsedExcludingSelfLong(), + sizeof(void*) * kMinCap + kInnerMapOverhead); + + size_t capacity = kMinCap; + for (int i = 0; i < 100; ++i) { + m[i]; + static constexpr double kMaxLoadFactor = .75; + if (m.size() >= capacity * kMaxLoadFactor) { + capacity *= 2; + } + EXPECT_EQ(m.SpaceUsedExcludingSelfLong(), + sizeof(void*) * capacity + kInnerMapOverhead + + m.size() * sizeof(std::pair, void*>)); + } + + // Test string, and non-scalar keys. + Map m2; + std::string str = "Some arbitrarily large string"; + m2[str] = 1; + EXPECT_EQ(m2.SpaceUsedExcludingSelfLong(), + sizeof(void*) * kMinCap + kInnerMapOverhead + + sizeof(std::pair, void*>) + + internal::StringSpaceUsedExcludingSelfLong(str)); + + // Test messages, and non-scalar values. + Map m3; + m3[0].set_optional_string(str); + EXPECT_EQ(m3.SpaceUsedExcludingSelfLong(), + sizeof(void*) * kMinCap + kInnerMapOverhead + + sizeof(std::pair, void*>) + + m3[0].SpaceUsedLong() - sizeof(m3[0])); +} + // Attempts to verify that a map with keys a and b has a random ordering. This // function returns true if it succeeds in observing both possible orderings. bool MapOrderingIsRandom(int a, int b) { @@ -2507,6 +2547,27 @@ TEST(GeneratedMapFieldTest, IsInitialized) { EXPECT_TRUE(map_message.IsInitialized()); } +TEST(GeneratedMapFieldTest, SpaceUsed) { + unittest::TestRequiredMessageMap map_message; + const size_t initial = map_message.SpaceUsed(); + const size_t space_used_message = unittest::TestRequired().SpaceUsed(); + + auto& m = *map_message.mutable_map_field(); + constexpr int kNumValues = 100; + for (int i = 0; i < kNumValues; ++i) { + m[i]; + } + + // The exact value will depend on internal state, like collisions, + // so we can't predict it. But we can predict a lower bound. + size_t lower_bound = + initial + kNumValues * (space_used_message + sizeof(int32) + + /* Node::next */ sizeof(void*) + + /* table entry */ sizeof(void*)); + + EXPECT_LE(lower_bound, map_message.SpaceUsed()); +} + TEST(GeneratedMapFieldTest, MessagesMustMerge) { unittest::TestRequiredMessageMap map_message; diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h index d54aa226da..aba35becc7 100644 --- a/src/google/protobuf/map_type_handler.h +++ b/src/google/protobuf/map_type_handler.h @@ -59,29 +59,6 @@ struct MapIf { typedef FalseType type; }; -// In proto2 Map, enum needs to be initialized to given default value, while -// other types' default value can be inferred from the type. -template -class MapValueInitializer { - public: - static inline void Initialize(Type& type, int default_enum_value); -}; - -template -class MapValueInitializer { - public: - static inline void Initialize(Type& value, int default_enum_value) { - value = static_cast(default_enum_value); - } -}; - -template -class MapValueInitializer { - public: - static inline void Initialize(Type& /* value */, - int /* default_enum_value */) {} -}; - template class MapArenaMessageCreator { public: @@ -180,19 +157,12 @@ class MapTypeHandler { static inline void DeleteNoArena(const Type* x); static inline void Merge(const Type& from, Type** to, Arena* arena); static inline void Clear(Type** value, Arena* arena); - static inline void ClearMaybeByDefaultEnum(Type** value, Arena* arena, - int default_enum_value); static inline void Initialize(Type** x, Arena* arena); - static inline void InitializeMaybeByDefaultEnum(Type** x, - int default_enum_value, - Arena* arena); static inline Type* EnsureMutable(Type** value, Arena* arena); // SpaceUsedInMapEntry: Return bytes used by value in MapEntry, excluding // those already calculate in sizeof(MapField). static inline size_t SpaceUsedInMapEntryLong(const Type* value); - // Return bytes used by value in Map. - static inline size_t SpaceUsedInMapLong(const Type& value); // Assign default value to given instance. static inline void AssignDefaultValue(Type** value); // Return default instance if value is not initialized when calling const @@ -235,21 +205,13 @@ class MapTypeHandler { static inline void Merge(const MapEntryAccessorType& from, \ TypeOnMemory* to, Arena* arena); \ static inline void Clear(TypeOnMemory* value, Arena* arena); \ - static inline void ClearMaybeByDefaultEnum(TypeOnMemory* value, \ - Arena* arena, \ - int default_enum); \ static inline size_t SpaceUsedInMapEntryLong(const TypeOnMemory& value); \ - static inline size_t SpaceUsedInMapLong(const TypeOnMemory& value); \ - static inline size_t SpaceUsedInMapLong(ConstStringParam value); \ static inline void AssignDefaultValue(TypeOnMemory* value); \ static inline const MapEntryAccessorType& DefaultIfNotInitialized( \ const TypeOnMemory& value, const TypeOnMemory& default_value); \ static inline bool IsInitialized(const TypeOnMemory& value); \ static void DeleteNoArena(TypeOnMemory& value); \ static inline void Initialize(TypeOnMemory* value, Arena* arena); \ - static inline void InitializeMaybeByDefaultEnum(TypeOnMemory* value, \ - int default_enum_value, \ - Arena* arena); \ static inline MapEntryAccessorType* EnsureMutable(TypeOnMemory* value, \ Arena* arena); \ }; @@ -546,24 +508,12 @@ inline size_t MapTypeHandlerSpaceUsedLong(); } -template -size_t MapTypeHandler::SpaceUsedInMapLong( - const Type& value) { - return value.SpaceUsedLong(); -} - template inline void MapTypeHandler::Clear( Type** value, Arena* /* arena */) { if (*value != NULL) (*value)->Clear(); } template -inline void -MapTypeHandler::ClearMaybeByDefaultEnum( - Type** value, Arena* /* arena */, int /* default_enum_value */) { - if (*value != NULL) (*value)->Clear(); -} -template inline void MapTypeHandler::Merge( const Type& from, Type** to, Arena* /* arena */) { (*to)->MergeFrom(from); @@ -587,13 +537,6 @@ inline void MapTypeHandler::Initialize( *x = NULL; } -template -inline void MapTypeHandler:: - InitializeMaybeByDefaultEnum(Type** x, int /* default_enum_value */, - Arena* /* arena */) { - *x = NULL; -} - template inline Type* MapTypeHandler::EnsureMutable( Type** value, Arena* arena) { @@ -635,29 +578,11 @@ inline bool MapTypeHandler::IsInitialized( return sizeof(value); \ } \ template \ - inline size_t \ - MapTypeHandler::SpaceUsedInMapLong( \ - const TypeOnMemory& value) { \ - return sizeof(value); \ - } \ - template \ - inline size_t \ - MapTypeHandler::SpaceUsedInMapLong( \ - ConstStringParam value) { \ - return sizeof(std::string); \ - } \ - template \ inline void MapTypeHandler::Clear( \ TypeOnMemory* value, Arena* arena) { \ value->ClearToEmpty(&internal::GetEmptyStringAlreadyInited(), arena); \ } \ template \ - inline void MapTypeHandler:: \ - ClearMaybeByDefaultEnum(TypeOnMemory* value, Arena* arena, \ - int /* default_enum */) { \ - Clear(value, arena); \ - } \ - template \ inline void MapTypeHandler::Merge( \ const MapEntryAccessorType& from, TypeOnMemory* to, Arena* arena) { \ to->Set(&internal::GetEmptyStringAlreadyInited(), from, arena); \ @@ -678,12 +603,6 @@ inline bool MapTypeHandler::IsInitialized( value->UnsafeSetDefault(&internal::GetEmptyStringAlreadyInited()); \ } \ template \ - inline void MapTypeHandler:: \ - InitializeMaybeByDefaultEnum( \ - TypeOnMemory* value, int /* default_enum_value */, Arena* arena) { \ - Initialize(value, arena); \ - } \ - template \ inline typename MapTypeHandler::MapEntryAccessorType* \ MapTypeHandler::EnsureMutable( \ @@ -722,23 +641,11 @@ STRING_OR_BYTES_HANDLER_FUNCTIONS(BYTES) return 0; \ } \ template \ - inline size_t \ - MapTypeHandler::SpaceUsedInMapLong( \ - const TypeOnMemory& /* value */) { \ - return sizeof(Type); \ - } \ - template \ inline void MapTypeHandler::Clear( \ TypeOnMemory* value, Arena* /* arena */) { \ *value = 0; \ } \ template \ - inline void MapTypeHandler:: \ - ClearMaybeByDefaultEnum(TypeOnMemory* value, Arena* /* arena */, \ - int default_enum_value) { \ - *value = static_cast(default_enum_value); \ - } \ - template \ inline void MapTypeHandler::Merge( \ const MapEntryAccessorType& from, TypeOnMemory* to, \ Arena* /* arena */) { \ @@ -758,12 +665,6 @@ STRING_OR_BYTES_HANDLER_FUNCTIONS(BYTES) *value = 0; \ } \ template \ - inline void MapTypeHandler:: \ - InitializeMaybeByDefaultEnum( \ - TypeOnMemory* value, int default_enum_value, Arena* /* arena */) { \ - *value = static_cast(default_enum_value); \ - } \ - template \ inline typename MapTypeHandler::MapEntryAccessorType* \ MapTypeHandler::EnsureMutable( \ diff --git a/src/google/protobuf/port_def.inc b/src/google/protobuf/port_def.inc index c92a3d5045..a65a227bc2 100644 --- a/src/google/protobuf/port_def.inc +++ b/src/google/protobuf/port_def.inc @@ -444,6 +444,10 @@ #undef NO #pragma push_macro("DEBUG") #undef DEBUG +#pragma push_macro("TRUE") +#undef TRUE +#pragma push_macro("FALSE") +#undef FALSE #endif // defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER) #if defined(__clang__) diff --git a/src/google/protobuf/port_undef.inc b/src/google/protobuf/port_undef.inc index 5fea276593..6b3751055f 100644 --- a/src/google/protobuf/port_undef.inc +++ b/src/google/protobuf/port_undef.inc @@ -99,6 +99,8 @@ #pragma pop_macro("YES") #pragma pop_macro("NO") #pragma pop_macro("DEBUG") +#pragma pop_macro("TRUE") +#pragma pop_macro("FALSE") #endif // defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER) #if defined(__clang__) diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h index 0c56821659..b7aa388060 100644 --- a/src/google/protobuf/struct.pb.h +++ b/src/google/protobuf/struct.pb.h @@ -109,14 +109,12 @@ inline bool NullValue_Parse( class Struct_FieldsEntry_DoNotUse : public ::PROTOBUF_NAMESPACE_ID::internal::MapEntry { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_MESSAGE> { public: typedef ::PROTOBUF_NAMESPACE_ID::internal::MapEntry SuperType; + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_MESSAGE> SuperType; Struct_FieldsEntry_DoNotUse(); explicit Struct_FieldsEntry_DoNotUse(::PROTOBUF_NAMESPACE_ID::Arena* arena); void MergeFrom(const Struct_FieldsEntry_DoNotUse& other); @@ -282,8 +280,7 @@ class PROTOBUF_EXPORT Struct PROTOBUF_FINAL : Struct_FieldsEntry_DoNotUse, std::string, PROTOBUF_NAMESPACE_ID::Value, ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_STRING, - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_MESSAGE, - 0 > fields_; + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_MESSAGE> fields_; mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; friend struct ::TableStruct_google_2fprotobuf_2fstruct_2eproto; }; diff --git a/src/google/protobuf/util/internal/datapiece.cc b/src/google/protobuf/util/internal/datapiece.cc index 6ce7dbc1b1..e76268a9d5 100644 --- a/src/google/protobuf/util/internal/datapiece.cc +++ b/src/google/protobuf/util/internal/datapiece.cc @@ -37,6 +37,7 @@ #include #include #include +#include #include #include diff --git a/src/google/protobuf/util/internal/field_mask_utility.cc b/src/google/protobuf/util/internal/field_mask_utility.cc index 40e193e593..0beff996a6 100644 --- a/src/google/protobuf/util/internal/field_mask_utility.cc +++ b/src/google/protobuf/util/internal/field_mask_utility.cc @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -107,7 +108,7 @@ std::string ConvertFieldMaskPath(const StringPiece path, } util::Status DecodeCompactFieldMaskPaths(StringPiece paths, - PathSinkCallback path_sink) { + PathSinkCallback path_sink) { std::stack prefix; int length = paths.length(); int previous_position = 0; diff --git a/src/google/protobuf/util/internal/field_mask_utility.h b/src/google/protobuf/util/internal/field_mask_utility.h index 7335af506b..bc41321220 100644 --- a/src/google/protobuf/util/internal/field_mask_utility.h +++ b/src/google/protobuf/util/internal/field_mask_utility.h @@ -38,6 +38,7 @@ #include #include +#include #include #include @@ -63,7 +64,7 @@ std::string ConvertFieldMaskPath(const StringPiece path, // Note that we also support Apiary style FieldMask form. The above example in // the Apiary style will look like "a.b,a.c(d,e)". util::Status DecodeCompactFieldMaskPaths(StringPiece paths, - PathSinkCallback path_sink); + PathSinkCallback path_sink); } // namespace converter } // namespace util diff --git a/src/google/protobuf/util/internal/json_objectwriter.cc b/src/google/protobuf/util/internal/json_objectwriter.cc index a98e7bad5c..32ce2dcd1c 100644 --- a/src/google/protobuf/util/internal/json_objectwriter.cc +++ b/src/google/protobuf/util/internal/json_objectwriter.cc @@ -148,7 +148,7 @@ JsonObjectWriter* JsonObjectWriter::RenderBytes(StringPiece name, std::string base64; if (use_websafe_base64_for_bytes_) - WebSafeBase64EscapeWithPadding(value.ToString(), &base64); + WebSafeBase64EscapeWithPadding(std::string(value), &base64); else Base64Escape(value, &base64); diff --git a/src/google/protobuf/util/internal/protostream_objectsource_test.cc b/src/google/protobuf/util/internal/protostream_objectsource_test.cc index b2daf3af27..ab27349191 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource_test.cc +++ b/src/google/protobuf/util/internal/protostream_objectsource_test.cc @@ -49,6 +49,7 @@ #include #include #include +#include namespace google { diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc index 527d5e70da..70861634d7 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter.cc +++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include diff --git a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc index 983043fd65..564050f4f6 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc +++ b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc @@ -93,12 +93,6 @@ std::string GetTypeUrl(const Descriptor* descriptor) { } } // namespace -#if __cplusplus >= 201103L -using std::get; -#else -using std::tr1::get; -#endif - class BaseProtoStreamObjectWriterTest : public ::testing::TestWithParam { protected: @@ -171,7 +165,7 @@ class BaseProtoStreamObjectWriterTest MATCHER_P(HasObjectLocation, expected, "Verifies the expected object location") { - std::string actual = get<0>(arg).ToString(); + std::string actual = std::get<0>(arg).ToString(); if (actual == expected) return true; *result_listener << "actual location is: " << actual; return false; diff --git a/src/google/protobuf/util/internal/type_info.cc b/src/google/protobuf/util/internal/type_info.cc index e8b2103855..e91afa027e 100644 --- a/src/google/protobuf/util/internal/type_info.cc +++ b/src/google/protobuf/util/internal/type_info.cc @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc index 47ad0f1e8b..dc25608285 100644 --- a/src/google/protobuf/wire_format_lite.cc +++ b/src/google/protobuf/wire_format_lite.cc @@ -603,7 +603,6 @@ bool WireFormatLite::VerifyUtf8String(const char* data, int size, Operation op, // efficient SSE code. template static size_t VarintSize(const T* data, const int n) { -#if __cplusplus >= 201103L static_assert(sizeof(T) == 4, "This routine only works for 32 bit integers"); // is_unsigned => !ZigZag static_assert( @@ -615,7 +614,6 @@ static size_t VarintSize(const T* data, const int n) { "Cannot SignExtended unsigned types"); static_assert(!(SignExtended && ZigZag), "Cannot SignExtended and ZigZag on the same type"); -#endif uint32 sum = n; uint32 msb_sum = 0; for (int i = 0; i < n; i++) { @@ -640,12 +638,10 @@ static size_t VarintSize(const T* data, const int n) { template static size_t VarintSize64(const T* data, const int n) { -#if __cplusplus >= 201103L static_assert(sizeof(T) == 8, "This routine only works for 64 bit integers"); // is_unsigned => !ZigZag static_assert(!ZigZag || !std::is_unsigned::value, "Cannot ZigZag encode unsigned types"); -#endif uint64 sum = n; for (int i = 0; i < n; i++) { uint64 x = data[i]; diff --git a/tests.sh b/tests.sh index ca998e1e17..52b9cf127b 100755 --- a/tests.sh +++ b/tests.sh @@ -478,45 +478,6 @@ build_php5.5() { (cd conformance && make test_php) } -build_php5.5_c() { - IS_64BIT=$1 - use_php 5.5 - php/tests/test.sh - pushd conformance - if [ "$IS_64BIT" = "true" ] - then - make test_php_c - else - make test_php_c_32 - fi - popd -} - -build_php5.5_mixed() { - use_php 5.5 - pushd php - rm -rf vendor - composer update - tests/compile_extension.sh - tests/generate_protos.sh - php -dextension=./ext/google/protobuf/modules/protobuf.so ./vendor/bin/phpunit - popd -} - -build_php5.5_zts_c() { - IS_64BIT=$1 - use_php_zts 5.5 - php/tests/test.sh - pushd conformance - if [ "$IS_64BIT" = "true" ] - then - make test_php_c - else - make test_php_c_32 - fi - popd -} - build_php5.6() { use_php 5.6 pushd php @@ -527,61 +488,22 @@ build_php5.6() { (cd conformance && make test_php) } -build_php5.6_c() { - IS_64BIT=$1 - use_php 5.6 - php/tests/test.sh - pushd conformance - if [ "$IS_64BIT" = "true" ] - then - make test_php_c - else - make test_php_c_32 - fi - popd -} - -build_php5.6_mixed() { - use_php 5.6 - pushd php - rm -rf vendor - composer update - tests/compile_extension.sh - tests/generate_protos.sh - php -dextension=./ext/google/protobuf/modules/protobuf.so ./vendor/bin/phpunit - popd -} - -build_php5.6_zts_c() { - IS_64BIT=$1 - use_php_zts 5.6 - php/tests/test.sh - pushd conformance - if [ "$IS_64BIT" = "true" ] - then - make test_php_c - else - make test_php_c_32 - fi - popd -} - build_php5.6_mac() { - internal_build_cpp # Install PHP curl -s https://php-osx.liip.ch/install.sh | bash -s 5.6 PHP_FOLDER=`find /usr/local -type d -name "php5-5.6*"` # The folder name may change upon time test ! -z "$PHP_FOLDER" export PATH="$PHP_FOLDER/bin:$PATH" - # Install valgrind - echo "#! /bin/bash" > valgrind - chmod ug+x valgrind - sudo mv valgrind /usr/local/bin/valgrind + internal_build_cpp - # Test - php/tests/test.sh - (cd conformance && make test_php_c) + # Run pure-PHP tests only. + pushd php + rm -rf vendor + composer update + composer test + popd + (cd conformance && make test_php) } build_php7.0() { @@ -752,7 +674,6 @@ build_php7.4_c() { make test_php_c_32 fi popd - (cd php/ext/google/protobuf && phpize --clean) } build_php7.4_mixed() { @@ -764,7 +685,6 @@ build_php7.4_mixed() { tests/generate_protos.sh php -dextension=./ext/google/protobuf/modules/protobuf.so ./vendor/bin/phpunit popd - (cd php/ext/google/protobuf && phpize --clean) } build_php7.4_zts_c() { @@ -779,7 +699,6 @@ build_php7.4_zts_c() { make test_php_c_32 fi popd - (cd php/ext/google/protobuf && phpize --clean) } build_php_all_32() { @@ -788,18 +707,12 @@ build_php_all_32() { build_php7.0 build_php7.1 build_php7.4 - build_php5.5_c $1 - build_php5.6_c $1 build_php7.0_c $1 build_php7.1_c $1 build_php7.4_c $1 - build_php5.5_mixed - build_php5.6_mixed build_php7.0_mixed build_php7.1_mixed build_php7.4_mixed - build_php5.5_zts_c $1 - build_php5.6_zts_c $1 build_php7.0_zts_c $1 build_php7.1_zts_c $1 build_php7.4_zts_c $1 @@ -846,9 +759,7 @@ Usage: $0 { cpp | jruby | ruby_all | php5.5 | - php5.5_c | php5.6 | - php5.6_c | php7.0 | php7.0_c | php_compatibility | From 95e6c5b4746dd7474d540ce4fb375e3f79a086f8 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Mon, 17 Aug 2020 15:26:13 -0700 Subject: [PATCH 3/8] Sync from Piper @327110949 PROTOBUF_SYNC_PIPER --- .github/workflows/codespell.yml | 16 + .gitignore | 7 +- BUILD | 89 +-- CHANGES.txt | 13 +- Protobuf.podspec | 2 +- cmake/libprotobuf-lite.cmake | 1 + conformance/failure_list_php.txt | 56 -- conformance/failure_list_php_c.txt | 56 -- conformance/failure_list_php_c_32.txt | 56 -- conformance/third_party/jsoncpp/json.h | 6 +- conformance/third_party/jsoncpp/jsoncpp.cpp | 2 +- csharp/Google.Protobuf.Tools.nuspec | 2 +- csharp/generate_protos.sh | 1 + csharp/protos/unittest_issues.proto | 5 + csharp/src/AddressBook/Program.cs | 2 +- .../UnittestIssues.cs | 233 ++++++- .../Buffers/ArrayBufferWriter.cs | 2 +- csharp/src/Google.Protobuf.Test/IssuesTest.cs | 2 +- .../Proto3OptionalTest.cs | 10 + csharp/src/Google.Protobuf.Test/testprotos.pb | Bin 339004 -> 339527 bytes csharp/src/Google.Protobuf/ByteString.cs | 2 +- .../src/Google.Protobuf/CodedInputStream.cs | 2 +- .../Google.Protobuf/Google.Protobuf.csproj | 3 +- .../Reflection/OneofAccessor.cs | 2 +- .../Reflection/OneofDescriptor.cs | 2 +- .../WellKnownTypes/Timestamp.cs | 10 +- docs/csharp/proto2.md | 2 +- docs/field_presence.md | 2 +- docs/implementing_proto3_presence.md | 2 +- docs/options.md | 4 + docs/third_party.md | 12 +- java/README.md | 4 +- java/bom/pom.xml | 2 +- java/core/pom.xml | 2 +- .../com/google/protobuf/DynamicMessage.java | 31 +- .../com/google/protobuf/MessageSchema.java | 6 +- .../java/com/google/protobuf/TextFormat.java | 2 +- .../com/google/protobuf/TextFormatTest.java | 14 +- java/lite/pom.xml | 3 +- .../java/com/google/protobuf/LiteTest.java | 40 ++ java/pom.xml | 2 +- java/util/BUILD | 4 - java/util/pom.xml | 2 +- .../com/google/protobuf/util/JsonFormat.java | 11 +- js/experimental/runtime/kernel/kernel_test.js | 28 +- js/experimental/runtime/kernel/tag_test.js | 4 +- kokoro/linux/dockerfile/test/php80/Dockerfile | 96 +++ kokoro/linux/php80/build.sh | 18 + kokoro/linux/php80/continuous.cfg | 11 + kokoro/linux/php80/presubmit.cfg | 11 + kokoro/macos/prepare_build_macos_rc | 2 +- kokoro/release/collect_all_artifacts.sh | 2 +- kokoro/release/python/macos/config.sh | 19 + objectivec/BUILD | 90 +++ objectivec/DevTools/compile_testing_protos.sh | 2 +- objectivec/DevTools/full_mac_build.sh | 2 +- objectivec/DevTools/pddm.py | 2 +- objectivec/GPBExtensionInternals.m | 4 +- objectivec/GPBMessage.m | 2 +- objectivec/GPBTimestamp.pbobjc.h | 11 +- objectivec/GPBUtilities.m | 2 +- objectivec/GPBUtilities_PackagePrivate.h | 2 +- objectivec/README.md | 2 +- objectivec/Tests/CocoaPods/run_tests.sh | 2 +- objectivec/Tests/GPBCodedInputStreamTests.m | 2 +- objectivec/Tests/GPBCodedOuputStreamTests.m | 2 +- php/ext/google/protobuf/array.c | 18 +- php/ext/google/protobuf/convert.c | 61 +- php/ext/google/protobuf/def.c | 24 +- php/ext/google/protobuf/map.c | 16 +- php/ext/google/protobuf/message.c | 159 ++++- php/ext/google/protobuf/package.xml | 66 +- php/ext/google/protobuf/php-upb.c | 215 ++++--- php/ext/google/protobuf/php-upb.h | 21 +- php/ext/google/protobuf/protobuf.c | 7 + php/ext/google/protobuf/protobuf.h | 28 + php/phpunit.xml | 20 +- .../GPBMetadata/Google/Protobuf/Struct.php | 25 +- php/src/Google/Protobuf/Descriptor.php | 8 + php/src/Google/Protobuf/FieldDescriptor.php | 8 + .../Protobuf/Internal/DescriptorProto.php | 96 +-- .../DescriptorProto/ExtensionRange.php | 61 +- .../DescriptorProto/ReservedRange.php | 42 +- .../Protobuf/Internal/EnumDescriptorProto.php | 61 +- .../EnumDescriptorProto/EnumReservedRange.php | 42 +- .../Google/Protobuf/Internal/EnumOptions.php | 49 +- .../Internal/EnumValueDescriptorProto.php | 61 +- .../Protobuf/Internal/EnumValueOptions.php | 28 +- .../Internal/ExtensionRangeOptions.php | 7 - .../Protobuf/Internal/FieldDescriptor.php | 12 +- .../Internal/FieldDescriptorProto.php | 229 ++++--- .../Google/Protobuf/Internal/FieldOptions.php | 133 ++-- .../Protobuf/Internal/FileDescriptorProto.php | 150 ++--- .../Protobuf/Internal/FileDescriptorSet.php | 7 - .../Google/Protobuf/Internal/FileOptions.php | 427 +++++++------ .../Protobuf/Internal/GeneratedCodeInfo.php | 7 - .../Internal/GeneratedCodeInfo/Annotation.php | 70 ++- php/src/Google/Protobuf/Internal/Message.php | 26 +- .../Protobuf/Internal/MessageOptions.php | 91 +-- .../Internal/MethodDescriptorProto.php | 124 ++-- .../Protobuf/Internal/MethodOptions.php | 49 +- .../Internal/OneofDescriptorProto.php | 40 +- .../Google/Protobuf/Internal/OneofOptions.php | 7 - .../Internal/ServiceDescriptorProto.php | 47 +- .../Protobuf/Internal/ServiceOptions.php | 28 +- .../Protobuf/Internal/SourceCodeInfo.php | 7 - .../Internal/SourceCodeInfo/Location.php | 63 +- .../Protobuf/Internal/UninterpretedOption.php | 133 ++-- .../Internal/UninterpretedOption/NamePart.php | 42 +- php/src/Google/Protobuf/Mixin.php | 2 +- php/src/Google/Protobuf/NullValue.php | 1 + php/src/Google/Protobuf/OneofDescriptor.php | 5 + php/src/Google/Protobuf/Value.php | 30 + php/tests/{array_test.php => ArrayTest.php} | 2 +- ...scriptors_test.php => DescriptorsTest.php} | 2 +- ...e_decode_test.php => EncodeDecodeTest.php} | 36 ++ ..._class_test.php => GeneratedClassTest.php} | 22 + ...hpdoc_test.php => GeneratedPhpdocTest.php} | 0 ...vice_test.php => GeneratedServiceTest.php} | 0 .../{map_field_test.php => MapFieldTest.php} | 0 ...ion_test.php => PhpImplementationTest.php} | 2 +- ...{well_known_test.php => WellKnownTest.php} | 0 ...rs_test.php => WrapperTypeSettersTest.php} | 0 php/tests/compatibility_test.sh | 9 +- php/tests/compile_extension.sh | 16 +- php/tests/generate_protos.sh | 4 +- php/tests/proto/test.proto | 21 + php/tests/test.sh | 11 +- php/tests/test_util.php | 42 +- php/tests/valgrind.supp | 12 + protoc-artifacts/pom.xml | 2 +- python/README.md | 2 +- .../protobuf/internal/enum_type_wrapper.py | 4 +- python/release.sh | 6 +- ruby/ext/google/protobuf_c/upb.h | 4 +- ruby/google-protobuf.gemspec | 2 +- src/Makefile.am | 1 + src/google/protobuf/any.cc | 12 +- src/google/protobuf/any.pb.cc | 3 - src/google/protobuf/any.pb.h | 1 - src/google/protobuf/any_lite.cc | 32 +- src/google/protobuf/api.pb.cc | 11 - src/google/protobuf/api.pb.h | 7 +- src/google/protobuf/arena.cc | 16 +- src/google/protobuf/arena_impl.h | 1 - src/google/protobuf/arena_unittest.cc | 1 - src/google/protobuf/arenastring.h | 99 +-- .../protobuf/compiler/code_generator.cc | 6 + src/google/protobuf/compiler/code_generator.h | 10 + .../compiler/command_line_interface.cc | 203 ++++-- .../command_line_interface_unittest.cc | 39 +- src/google/protobuf/compiler/cpp/cpp_file.cc | 20 +- .../protobuf/compiler/cpp/cpp_helpers.cc | 12 +- .../protobuf/compiler/cpp/cpp_helpers.h | 26 +- .../protobuf/compiler/cpp/cpp_message.cc | 421 +++++++------ .../protobuf/compiler/cpp/cpp_message.h | 9 +- .../compiler/cpp/cpp_message_field.cc | 308 ++++------ .../protobuf/compiler/cpp/cpp_string_field.cc | 581 ++++++------------ src/google/protobuf/compiler/importer.cc | 2 +- .../protobuf/compiler/mock_code_generator.cc | 88 ++- .../protobuf/compiler/mock_code_generator.h | 4 +- .../compiler/objectivec/objectivec_file.cc | 2 +- .../objectivec/objectivec_generator.cc | 11 +- .../compiler/objectivec/objectivec_helpers.cc | 3 +- .../protobuf/compiler/php/php_generator.cc | 67 +- .../protobuf/compiler/php/php_generator.h | 5 + src/google/protobuf/compiler/plugin.cc | 10 + src/google/protobuf/compiler/plugin.pb.cc | 99 ++- src/google/protobuf/compiler/plugin.pb.h | 107 +++- src/google/protobuf/compiler/plugin.proto | 5 + .../protobuf/compiler/ruby/ruby_generator.cc | 22 +- .../protobuf/compiler/ruby/ruby_generator.h | 5 +- src/google/protobuf/descriptor.cc | 4 +- src/google/protobuf/descriptor.h | 6 +- src/google/protobuf/descriptor.pb.cc | 101 --- src/google/protobuf/descriptor.pb.h | 67 +- src/google/protobuf/descriptor_unittest.cc | 2 +- src/google/protobuf/duration.pb.cc | 3 - src/google/protobuf/duration.pb.h | 1 - src/google/protobuf/dynamic_message.cc | 7 + src/google/protobuf/empty.pb.cc | 3 - src/google/protobuf/empty.pb.h | 1 - src/google/protobuf/extension_set.cc | 30 +- src/google/protobuf/field_mask.pb.cc | 3 - src/google/protobuf/field_mask.pb.h | 1 - .../protobuf/generated_message_reflection.cc | 91 ++- .../protobuf/generated_message_reflection.h | 14 + .../generated_message_reflection_unittest.cc | 1 + .../protobuf/io/zero_copy_stream_impl.h | 1 - .../protobuf/io/zero_copy_stream_impl_lite.cc | 28 +- .../protobuf/io/zero_copy_stream_impl_lite.h | 2 +- .../protobuf/io/zero_copy_stream_unittest.cc | 15 + src/google/protobuf/map.cc | 41 ++ src/google/protobuf/map.h | 113 ++-- src/google/protobuf/map_entry_lite.h | 9 +- src/google/protobuf/map_field.h | 89 +-- src/google/protobuf/map_field_lite.h | 2 +- src/google/protobuf/map_test.cc | 13 +- src/google/protobuf/map_type_handler.h | 136 ++-- src/google/protobuf/message.cc | 4 + src/google/protobuf/message.h | 9 + src/google/protobuf/message_unittest.inc | 2 +- src/google/protobuf/repeated_field.h | 32 +- .../protobuf/repeated_field_unittest.cc | 8 + src/google/protobuf/source_context.pb.cc | 3 - src/google/protobuf/source_context.pb.h | 1 - src/google/protobuf/struct.pb.cc | 37 +- src/google/protobuf/struct.pb.h | 7 +- src/google/protobuf/text_format.cc | 30 +- src/google/protobuf/text_format.h | 4 +- src/google/protobuf/text_format_unittest.cc | 36 +- src/google/protobuf/timestamp.pb.cc | 3 - src/google/protobuf/timestamp.pb.h | 1 - src/google/protobuf/timestamp.proto | 11 +- src/google/protobuf/type.pb.cc | 21 - src/google/protobuf/type.pb.h | 17 +- src/google/protobuf/unittest_lite.proto | 5 + src/google/protobuf/util/field_comparator.h | 1 + .../protobuf/util/field_mask_util_test.cc | 4 +- .../util/internal/protostream_objectsource.cc | 4 +- .../util/internal/protostream_objectwriter.cc | 48 +- .../util/internal/protostream_objectwriter.h | 11 +- .../protobuf/util/message_differencer.cc | 90 +++ .../protobuf/util/message_differencer.h | 33 +- .../util/message_differencer_unittest.cc | 23 + src/google/protobuf/wire_format_unittest.cc | 2 +- src/google/protobuf/wrappers.pb.cc | 27 - src/google/protobuf/wrappers.pb.h | 9 - tests.sh | 49 +- 229 files changed, 4259 insertions(+), 3401 deletions(-) create mode 100644 .github/workflows/codespell.yml create mode 100644 kokoro/linux/dockerfile/test/php80/Dockerfile create mode 100755 kokoro/linux/php80/build.sh create mode 100644 kokoro/linux/php80/continuous.cfg create mode 100644 kokoro/linux/php80/presubmit.cfg create mode 100644 objectivec/BUILD rename php/tests/{array_test.php => ArrayTest.php} (99%) rename php/tests/{descriptors_test.php => DescriptorsTest.php} (99%) rename php/tests/{encode_decode_test.php => EncodeDecodeTest.php} (97%) rename php/tests/{generated_class_test.php => GeneratedClassTest.php} (98%) rename php/tests/{generated_phpdoc_test.php => GeneratedPhpdocTest.php} (100%) rename php/tests/{generated_service_test.php => GeneratedServiceTest.php} (100%) rename php/tests/{map_field_test.php => MapFieldTest.php} (100%) rename php/tests/{php_implementation_test.php => PhpImplementationTest.php} (99%) rename php/tests/{well_known_test.php => WellKnownTest.php} (100%) rename php/tests/{wrapper_type_setters_test.php => WrapperTypeSettersTest.php} (100%) create mode 100644 php/tests/valgrind.supp create mode 100644 src/google/protobuf/map.cc diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml new file mode 100644 index 0000000000..d853702a11 --- /dev/null +++ b/.github/workflows/codespell.yml @@ -0,0 +1,16 @@ +# GitHub Action to automate the identification of common misspellings in text files. +# https://github.com/codespell-project/actions-codespell +# https://github.com/codespell-project/codespell +name: codespell +on: [push, pull_request] +jobs: + codespell: + name: Check for spelling errors + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: codespell-project/actions-codespell@master + with: + check_filenames: true + skip: ./.git,./conformance/third_party,*.snk,*.pb,./src/google/protobuf/testdata,./objectivec/Tests,./python/compatibility_tests/v2.5.0/tests/google/protobuf/internal + ignore_words_list: "alow,alse,ba,cleare,copyable,cloneable,dedup,dur,errorprone,fo,fundementals,hel,importd,inout,leapyear,nd,ois,ons,parseable,process',te,testof,ue,unparseable,wasn,wee,gae,keyserver,objext,od" diff --git a/.gitignore b/.gitignore index a7349c2aa8..e06aedea6b 100644 --- a/.gitignore +++ b/.gitignore @@ -104,7 +104,7 @@ build_msvc # needed to trigger "pod install" to rerun the preinstall commands. Pods/ -# Comformance test output +# Conformance test output conformance/.libs/ conformance/com/ conformance/conformance-cpp @@ -137,19 +137,24 @@ conformance/*.class # php test output composer.lock +php/tests/.phpunit.result.cache php/tests/generated/ php/tests/old_protoc +php/tests/phpunit-9.phar php/tests/protobuf/ php/tests/core php/tests/vgcore* php/tests/multirequest.result php/tests/nohup.out +php/tests/.phpunit.result.cache +php/tests/phpunit-* php/ext/google/protobuf/.libs/ php/ext/google/protobuf/Makefile.fragments php/ext/google/protobuf/Makefile.global php/ext/google/protobuf/Makefile.objects php/ext/google/protobuf/acinclude.m4 php/ext/google/protobuf/build/ +php/ext/google/protobuf/bundled_php.c php/ext/google/protobuf/config.h php/ext/google/protobuf/config.h.in~ php/ext/google/protobuf/config.nice diff --git a/BUILD b/BUILD index 224c8fce19..f3fd3f4606 100644 --- a/BUILD +++ b/BUILD @@ -954,96 +954,13 @@ proto_lang_toolchain( alias( name = "objectivec", - actual = ":protobuf_objc", + actual = "//objectivec", visibility = ["//visibility:public"], ) -objc_library( +alias( name = "protobuf_objc", - hdrs = [ - "objectivec/GPBAny.pbobjc.h", - "objectivec/GPBApi.pbobjc.h", - "objectivec/GPBDuration.pbobjc.h", - "objectivec/GPBEmpty.pbobjc.h", - "objectivec/GPBFieldMask.pbobjc.h", - "objectivec/GPBSourceContext.pbobjc.h", - "objectivec/GPBStruct.pbobjc.h", - "objectivec/GPBTimestamp.pbobjc.h", - "objectivec/GPBType.pbobjc.h", - "objectivec/GPBWrappers.pbobjc.h", - "objectivec/GPBArray.h", - "objectivec/GPBBootstrap.h", - "objectivec/GPBCodedInputStream.h", - "objectivec/GPBCodedOutputStream.h", - "objectivec/GPBDescriptor.h", - "objectivec/GPBDictionary.h", - "objectivec/GPBExtensionInternals.h", - "objectivec/GPBExtensionRegistry.h", - "objectivec/GPBMessage.h", - "objectivec/GPBProtocolBuffers.h", - "objectivec/GPBProtocolBuffers_RuntimeSupport.h", - "objectivec/GPBRootObject.h", - "objectivec/GPBRuntimeTypes.h", - "objectivec/GPBUnknownField.h", - "objectivec/GPBUnknownFieldSet.h", - "objectivec/GPBUtilities.h", - "objectivec/GPBWellKnownTypes.h", - "objectivec/GPBWireFormat.h", - "objectivec/google/protobuf/Any.pbobjc.h", - "objectivec/google/protobuf/Api.pbobjc.h", - "objectivec/google/protobuf/Duration.pbobjc.h", - "objectivec/google/protobuf/Empty.pbobjc.h", - "objectivec/google/protobuf/FieldMask.pbobjc.h", - "objectivec/google/protobuf/SourceContext.pbobjc.h", - "objectivec/google/protobuf/Struct.pbobjc.h", - "objectivec/google/protobuf/Timestamp.pbobjc.h", - "objectivec/google/protobuf/Type.pbobjc.h", - "objectivec/google/protobuf/Wrappers.pbobjc.h", - # Package private headers, but exposed because the generated sources - # need to use them. - "objectivec/GPBArray_PackagePrivate.h", - "objectivec/GPBCodedInputStream_PackagePrivate.h", - "objectivec/GPBCodedOutputStream_PackagePrivate.h", - "objectivec/GPBDescriptor_PackagePrivate.h", - "objectivec/GPBDictionary_PackagePrivate.h", - "objectivec/GPBMessage_PackagePrivate.h", - "objectivec/GPBRootObject_PackagePrivate.h", - "objectivec/GPBUnknownFieldSet_PackagePrivate.h", - "objectivec/GPBUnknownField_PackagePrivate.h", - "objectivec/GPBUtilities_PackagePrivate.h", - ], - copts = [ - "-Wno-vla", - ], - includes = [ - "objectivec", - ], - non_arc_srcs = [ - "objectivec/GPBAny.pbobjc.m", - "objectivec/GPBApi.pbobjc.m", - "objectivec/GPBDuration.pbobjc.m", - "objectivec/GPBEmpty.pbobjc.m", - "objectivec/GPBFieldMask.pbobjc.m", - "objectivec/GPBSourceContext.pbobjc.m", - "objectivec/GPBStruct.pbobjc.m", - "objectivec/GPBTimestamp.pbobjc.m", - "objectivec/GPBType.pbobjc.m", - "objectivec/GPBWrappers.pbobjc.m", - "objectivec/GPBArray.m", - "objectivec/GPBCodedInputStream.m", - "objectivec/GPBCodedOutputStream.m", - "objectivec/GPBDescriptor.m", - "objectivec/GPBDictionary.m", - "objectivec/GPBExtensionInternals.m", - "objectivec/GPBExtensionRegistry.m", - "objectivec/GPBMessage.m", - "objectivec/GPBRootObject.m", - "objectivec/GPBUnknownField.m", - "objectivec/GPBUnknownFieldSet.m", - "objectivec/GPBUtilities.m", - "objectivec/GPBWellKnownTypes.m", - "objectivec/GPBWireFormat.m", - ], + actual = "//objectivec", visibility = ["//visibility:public"], ) diff --git a/CHANGES.txt b/CHANGES.txt index 6d77428d7d..76910c4d0c 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,4 @@ -Unreleased Changes +2020-07-14 version 3.13.0-rc1 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) C++: * Removed deprecated unsafe arena string accessors @@ -37,10 +37,19 @@ Unreleased Changes type internally. (#7351) * Add `ParseFrom(ReadOnlySequence)` method to enable GC friendly parsing with reduced allocations and buffer copies. (#7351) + * Add support for serialization directly to a `IBufferWriter` or + to a `Span` to enable GC friendly serialization. + The new API is available as extension methods on the `IMessage` type. (#7576) * Add `GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE` define to make generated code compatible with old C# compilers (pre-roslyn compilers from .NET framework and old versions of mono) that do not support - ref structs. (#7490) + ref structs. Users that are still on a legacy stack that does + not support C# 7.2 compiler might need to use the new define + in their projects to be able to build the newly generated code. (#7490) + * Due to the major overhaul of parsing and serialization internals (#7351 and #7576), + it is recommended to regenerate your generated code to achieve the best + performance (the legacy generated code will still work, but might incur + a slight performance penalty). 2020-06-01 version 3.12.3 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) diff --git a/Protobuf.podspec b/Protobuf.podspec index 3b7a716761..22e7ce3003 100644 --- a/Protobuf.podspec +++ b/Protobuf.podspec @@ -5,7 +5,7 @@ # dependent projects use the :git notation to refer to the library. Pod::Spec.new do |s| s.name = 'Protobuf' - s.version = '3.12.3' + s.version = '3.13.0' s.summary = 'Protocol Buffers v.3 runtime library for Objective-C.' s.homepage = 'https://github.com/protocolbuffers/protobuf' s.license = '3-Clause BSD License' diff --git a/cmake/libprotobuf-lite.cmake b/cmake/libprotobuf-lite.cmake index 6bf86a2770..bbba6071f7 100644 --- a/cmake/libprotobuf-lite.cmake +++ b/cmake/libprotobuf-lite.cmake @@ -12,6 +12,7 @@ set(libprotobuf_lite_files ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream.cc ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl.cc ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl_lite.cc + ${protobuf_source_dir}/src/google/protobuf/map.cc ${protobuf_source_dir}/src/google/protobuf/message_lite.cc ${protobuf_source_dir}/src/google/protobuf/parse_context.cc ${protobuf_source_dir}/src/google/protobuf/repeated_field.cc diff --git a/conformance/failure_list_php.txt b/conformance/failure_list_php.txt index 1c7f92bc92..d51a75dc36 100644 --- a/conformance/failure_list_php.txt +++ b/conformance/failure_list_php.txt @@ -6,62 +6,6 @@ Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput -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.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput -Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.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 Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator Required.Proto3.JsonInput.DoubleFieldTooSmall Required.Proto3.JsonInput.FloatFieldTooLarge diff --git a/conformance/failure_list_php_c.txt b/conformance/failure_list_php_c.txt index cfed9f6d4d..63c7e8a024 100644 --- a/conformance/failure_list_php_c.txt +++ b/conformance/failure_list_php_c.txt @@ -1,58 +1,2 @@ Recommended.Proto2.JsonInput.FieldNameExtension.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.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput -Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.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 Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator diff --git a/conformance/failure_list_php_c_32.txt b/conformance/failure_list_php_c_32.txt index cfed9f6d4d..63c7e8a024 100644 --- a/conformance/failure_list_php_c_32.txt +++ b/conformance/failure_list_php_c_32.txt @@ -1,58 +1,2 @@ Recommended.Proto2.JsonInput.FieldNameExtension.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.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput -Recommended.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.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 Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator diff --git a/conformance/third_party/jsoncpp/json.h b/conformance/third_party/jsoncpp/json.h index 5639c92451..373ec98bde 100644 --- a/conformance/third_party/jsoncpp/json.h +++ b/conformance/third_party/jsoncpp/json.h @@ -1371,7 +1371,7 @@ public: */ std::string getFormattedErrorMessages() const; - /** \brief Returns a vector of structured errors encounted while parsing. + /** \brief Returns a vector of structured errors encountered while parsing. * \return A (possibly empty) vector of StructuredError objects. Currently * only one error can be returned, but the caller should tolerate * multiple @@ -1867,7 +1867,7 @@ private: * - otherwise, it the values do not fit on one line, or the array contains * object or non empty array, then print one value per line. * - * If the Value have comments then they are outputed according to their + * If the Value have comments then they are outputted according to their *#CommentPlacement. * * \sa Reader, Value, Value::setComment() @@ -1928,7 +1928,7 @@ private: * - otherwise, it the values do not fit on one line, or the array contains * object or non empty array, then print one value per line. * - * If the Value have comments then they are outputed according to their + * If the Value have comments then they are outputted according to their #CommentPlacement. * * \param indentation Each level will be indented by this amount extra. diff --git a/conformance/third_party/jsoncpp/jsoncpp.cpp b/conformance/third_party/jsoncpp/jsoncpp.cpp index d313d0563c..78919eac0f 100644 --- a/conformance/third_party/jsoncpp/jsoncpp.cpp +++ b/conformance/third_party/jsoncpp/jsoncpp.cpp @@ -142,7 +142,7 @@ enum { typedef char UIntToStringBuffer[uintToStringBufferSize]; /** Converts an unsigned integer to string. - * @param value Unsigned interger to convert to string + * @param value Unsigned integer to convert to string * @param current Input/Output string buffer. * Must have at least uintToStringBufferSize chars free. */ diff --git a/csharp/Google.Protobuf.Tools.nuspec b/csharp/Google.Protobuf.Tools.nuspec index d0c088f2a1..019f054472 100644 --- a/csharp/Google.Protobuf.Tools.nuspec +++ b/csharp/Google.Protobuf.Tools.nuspec @@ -5,7 +5,7 @@ Google Protocol Buffers tools Tools for Protocol Buffers - Google's data interchange format. See project site for more info. - 3.12.3 + 3.13.0 Google Inc. protobuf-packages https://github.com/protocolbuffers/protobuf/blob/master/LICENSE diff --git a/csharp/generate_protos.sh b/csharp/generate_protos.sh index 49a5a42665..b663138d10 100755 --- a/csharp/generate_protos.sh +++ b/csharp/generate_protos.sh @@ -45,6 +45,7 @@ $PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf \ # and old_extensions2.proto, which are generated with an older version # of protoc. $PROTOC -Isrc -Icsharp/protos \ + --experimental_allow_proto3_optional \ --csharp_out=csharp/src/Google.Protobuf.Test.TestProtos \ --descriptor_set_out=csharp/src/Google.Protobuf.Test/testprotos.pb \ --include_source_info \ diff --git a/csharp/protos/unittest_issues.proto b/csharp/protos/unittest_issues.proto index ef40d75fce..388998f0a0 100644 --- a/csharp/protos/unittest_issues.proto +++ b/csharp/protos/unittest_issues.proto @@ -151,3 +151,8 @@ message NullValueOutsideStruct { message NullValueNotInOneof { google.protobuf.NullValue null_value = 2; } + +message MixedRegularAndOptional { + string regular_field = 1; + optional string optional_field = 2; +} diff --git a/csharp/src/AddressBook/Program.cs b/csharp/src/AddressBook/Program.cs index ff7b9c085e..de4867a0ce 100644 --- a/csharp/src/AddressBook/Program.cs +++ b/csharp/src/AddressBook/Program.cs @@ -37,7 +37,7 @@ namespace Google.Protobuf.Examples.AddressBook /// /// Entry point. Repeatedly prompts user for an action to take, delegating actual behaviour /// to individual actions. Each action has its own Main method, so that it can be used as an - /// invidual complete program. + /// individual complete program. /// internal class Program { diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs index e09191a65c..4377cf3a19 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs @@ -52,11 +52,13 @@ namespace UnitTest.Issues.TestProtos { "bmdfdmFsdWUYASABKAlIABIwCgpudWxsX3ZhbHVlGAIgASgOMhouZ29vZ2xl", "LnByb3RvYnVmLk51bGxWYWx1ZUgAQgcKBXZhbHVlIkUKE051bGxWYWx1ZU5v", "dEluT25lb2YSLgoKbnVsbF92YWx1ZRgCIAEoDjIaLmdvb2dsZS5wcm90b2J1", - "Zi5OdWxsVmFsdWUqVQoMTmVnYXRpdmVFbnVtEhYKEk5FR0FUSVZFX0VOVU1f", - "WkVSTxAAEhYKCUZpdmVCZWxvdxD7//////////8BEhUKCE1pbnVzT25lEP//", - "/////////wEqLgoORGVwcmVjYXRlZEVudW0SEwoPREVQUkVDQVRFRF9aRVJP", - "EAASBwoDb25lEAFCHaoCGlVuaXRUZXN0Lklzc3Vlcy5UZXN0UHJvdG9zYgZw", - "cm90bzM=")); + "Zi5OdWxsVmFsdWUiYAoXTWl4ZWRSZWd1bGFyQW5kT3B0aW9uYWwSFQoNcmVn", + "dWxhcl9maWVsZBgBIAEoCRIbCg5vcHRpb25hbF9maWVsZBgCIAEoCUgAiAEB", + "QhEKD19vcHRpb25hbF9maWVsZCpVCgxOZWdhdGl2ZUVudW0SFgoSTkVHQVRJ", + "VkVfRU5VTV9aRVJPEAASFgoJRml2ZUJlbG93EPv//////////wESFQoITWlu", + "dXNPbmUQ////////////ASouCg5EZXByZWNhdGVkRW51bRITCg9ERVBSRUNB", + "VEVEX1pFUk8QABIHCgNvbmUQAUIdqgIaVW5pdFRlc3QuSXNzdWVzLlRlc3RQ", + "cm90b3NiBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::UnitTest.Issues.TestProtos.NegativeEnum), typeof(global::UnitTest.Issues.TestProtos.DeprecatedEnum), }, null, new pbr::GeneratedClrTypeInfo[] { @@ -70,7 +72,8 @@ namespace UnitTest.Issues.TestProtos { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.TestJsonName), global::UnitTest.Issues.TestProtos.TestJsonName.Parser, new[]{ "Name", "Description", "Guid" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.OneofMerging), global::UnitTest.Issues.TestProtos.OneofMerging.Parser, new[]{ "Text", "Nested" }, new[]{ "Value" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested), global::UnitTest.Issues.TestProtos.OneofMerging.Types.Nested.Parser, new[]{ "X", "Y" }, null, null, null, null)}), new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NullValueOutsideStruct), global::UnitTest.Issues.TestProtos.NullValueOutsideStruct.Parser, new[]{ "StringValue", "NullValue" }, new[]{ "Value" }, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NullValueNotInOneof), global::UnitTest.Issues.TestProtos.NullValueNotInOneof.Parser, new[]{ "NullValue" }, null, null, null, null) + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NullValueNotInOneof), global::UnitTest.Issues.TestProtos.NullValueNotInOneof.Parser, new[]{ "NullValue" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.MixedRegularAndOptional), global::UnitTest.Issues.TestProtos.MixedRegularAndOptional.Parser, new[]{ "RegularField", "OptionalField" }, new[]{ "OptionalField" }, null, null, null) })); } #endregion @@ -3304,6 +3307,224 @@ namespace UnitTest.Issues.TestProtos { } + public sealed partial class MixedRegularAndOptional : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MixedRegularAndOptional()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestIssuesReflection.Descriptor.MessageTypes[11]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MixedRegularAndOptional() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MixedRegularAndOptional(MixedRegularAndOptional other) : this() { + regularField_ = other.regularField_; + optionalField_ = other.optionalField_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public MixedRegularAndOptional Clone() { + return new MixedRegularAndOptional(this); + } + + /// Field number for the "regular_field" field. + public const int RegularFieldFieldNumber = 1; + private string regularField_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string RegularField { + get { return regularField_; } + set { + regularField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "optional_field" field. + public const int OptionalFieldFieldNumber = 2; + private string optionalField_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string OptionalField { + get { return optionalField_ ?? ""; } + set { + optionalField_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + /// Gets whether the "optional_field" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasOptionalField { + get { return optionalField_ != null; } + } + /// Clears the value of the "optional_field" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearOptionalField() { + optionalField_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as MixedRegularAndOptional); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(MixedRegularAndOptional other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (RegularField != other.RegularField) return false; + if (OptionalField != other.OptionalField) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (RegularField.Length != 0) hash ^= RegularField.GetHashCode(); + if (HasOptionalField) hash ^= OptionalField.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (RegularField.Length != 0) { + output.WriteRawTag(10); + output.WriteString(RegularField); + } + if (HasOptionalField) { + output.WriteRawTag(18); + output.WriteString(OptionalField); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (RegularField.Length != 0) { + output.WriteRawTag(10); + output.WriteString(RegularField); + } + if (HasOptionalField) { + output.WriteRawTag(18); + output.WriteString(OptionalField); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (RegularField.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(RegularField); + } + if (HasOptionalField) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(OptionalField); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(MixedRegularAndOptional other) { + if (other == null) { + return; + } + if (other.RegularField.Length != 0) { + RegularField = other.RegularField; + } + if (other.HasOptionalField) { + OptionalField = other.OptionalField; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + RegularField = input.ReadString(); + break; + } + case 18: { + OptionalField = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + RegularField = input.ReadString(); + break; + } + case 18: { + OptionalField = input.ReadString(); + break; + } + } + } + } + #endif + + } + #endregion } diff --git a/csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs b/csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs index 8e42d13dab..5b9913b290 100644 --- a/csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs +++ b/csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs @@ -60,7 +60,7 @@ namespace Google.Protobuf.Buffers } /// - /// Userful for testing writing to buffer writer with a lot of small segments. + /// Useful for testing writing to buffer writer with a lot of small segments. /// If set, it limits the max number of bytes by which the buffer grows by at once. /// public int? MaxGrowBy { get; set; } diff --git a/csharp/src/Google.Protobuf.Test/IssuesTest.cs b/csharp/src/Google.Protobuf.Test/IssuesTest.cs index 941bce0160..2904c461df 100644 --- a/csharp/src/Google.Protobuf.Test/IssuesTest.cs +++ b/csharp/src/Google.Protobuf.Test/IssuesTest.cs @@ -108,7 +108,7 @@ namespace Google.Protobuf // we still must read the tag correctly, even though the tag is at the very end of our limited input // (which is a corner case and will most likely result in an error when trying to read value of the field - // decribed by this tag, but it would be a logical error not to read the tag that's actually present). + // described by this tag, but it would be a logical error not to read the tag that's actually present). // See https://github.com/protocolbuffers/protobuf/pull/7289 cis.AssertNextTag(WireFormat.MakeTag(11, WireFormat.WireType.Varint)); } diff --git a/csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs b/csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs index 20c1846da4..46a8c57a78 100644 --- a/csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs +++ b/csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs @@ -34,6 +34,7 @@ using NUnit.Framework; using ProtobufUnittest; using System; using System.IO; +using UnitTest.Issues.TestProtos; namespace Google.Protobuf.Test { @@ -139,5 +140,14 @@ namespace Google.Protobuf.Test Assert.IsTrue(message1.Equals(message2)); message1.ClearOptionalInt32(); } + + [Test] + public void MixedFields() + { + var descriptor = MixedRegularAndOptional.Descriptor; + Assert.AreEqual(1, descriptor.Oneofs.Count); + Assert.AreEqual(0, descriptor.RealOneofCount); + Assert.True(descriptor.Oneofs[0].IsSynthetic); + } } } diff --git a/csharp/src/Google.Protobuf.Test/testprotos.pb b/csharp/src/Google.Protobuf.Test/testprotos.pb index bde0dae5040dff3e1cf7e8eef6495e5142d7242f..bae05e08fbd2a3c3931f4ec077a417dcb495bfc0 100644 GIT binary patch delta 693 zcmYL`v2W8r6o>uJXU9G_R52B_MJ0x`Qc?*Aq>2SGfK&uSiwJ)}F^y@X8arxS(WT1J zAxIHJU@+7Pu(5PNWU!Een4*q|1sD(;Vq;;fsQS*a!IFpX_rCW|_ipfQ;^6zl+YkF> zccK4r|F6_Mzr#*1)wb*E_d9LN?1(w|$r7I6=wo{!11Bz;8ED3M$ zOrK{byrdzq2)Awum28^F;$wj8IX1qMh9mje;N2Vb%N)z-k|6Z@PQR=-*%%{K)8#!7 zdH_sgBGo{rd!Xd8M5#suorXZpuq=}}NiixZq8oyGDn*gw)O6B{#V(M!qzE)dmLg8- zo&znHa%}5Hia4qZh1uP3*b0Y$KZ(MjcyvKLxWs~;WoiV2KjK$5Ec5%E6`n%$`@Q%? z4(1Od_aWy6G z1WiKo>PSK_cu8pC4(8^X?Jw57)%Cmfs^?aVrP4nq9%wdff7x=qMlq2&pk?0QsyV1% zVR-W5w)L>?*v94H^^rIgEr@hUp5(6};5u5M9jU98f|FOXX6+ONTDMD delta 235 zcmX?pM`X_pkqvv-Fg-EcynoGK*2&hJmve4Y;bIqJWnh@G`SoUfq2^u3+IJme1Y)M` zyN)sc(`CA?KYiC1<{w-)bwTRn7&;lZ^X_KuWt;B#hdEK;voseI3xg1A9Z;N6>Z$bh z-G7*8vTwIzW$|Sb=i*{!VPF(uuHz8on#;(=!otABAjHx%eK9x7e7z<{CU!1fE>@5r zBT$r)gCE9a262Uixt>Dw0A)L-7x1t=m+wI6VFZaXa_~a+Faq^-w3qR+Y%k+wy{G^H DXfQjl diff --git a/csharp/src/Google.Protobuf/ByteString.cs b/csharp/src/Google.Protobuf/ByteString.cs index 74dc865e9d..2a52ae58be 100644 --- a/csharp/src/Google.Protobuf/ByteString.cs +++ b/csharp/src/Google.Protobuf/ByteString.cs @@ -269,7 +269,7 @@ namespace Google.Protobuf } /// - /// Retuns the byte at the given index. + /// Returns the byte at the given index. /// public byte this[int index] { diff --git a/csharp/src/Google.Protobuf/CodedInputStream.cs b/csharp/src/Google.Protobuf/CodedInputStream.cs index 4050cbec8c..b09f96ce28 100644 --- a/csharp/src/Google.Protobuf/CodedInputStream.cs +++ b/csharp/src/Google.Protobuf/CodedInputStream.cs @@ -652,7 +652,7 @@ namespace Google.Protobuf /// /// Called when buffer is empty to read more bytes from the - /// input. If is true, RefillBuffer() gurantees that + /// input. If is true, RefillBuffer() guarantees that /// either there will be at least one byte in the buffer when it returns /// or it will throw an exception. If is false, /// RefillBuffer() returns false if no more bytes were available. diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.csproj b/csharp/src/Google.Protobuf/Google.Protobuf.csproj index db86da520e..082a398bfe 100644 --- a/csharp/src/Google.Protobuf/Google.Protobuf.csproj +++ b/csharp/src/Google.Protobuf/Google.Protobuf.csproj @@ -4,8 +4,7 @@ C# runtime library for Protocol Buffers - Google's data interchange format. Copyright 2015, Google Inc. Google Protocol Buffers - 3.12.2 - 3.12.3 + 3.13.0 7.2 Google Inc. diff --git a/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs b/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs index 4e040c17ea..7523426dc5 100644 --- a/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs +++ b/csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs @@ -63,7 +63,7 @@ namespace Google.Protobuf.Reflection internal static OneofAccessor ForSyntheticOneof(OneofDescriptor descriptor) { // Note: descriptor.Fields will be null when this method is called, because we haven't - // cross-linked yet. But by the time the delgates are called by user code, all will be + // cross-linked yet. But by the time the delegates are called by user code, all will be // well. (That's why we capture the descriptor itself rather than a field.) return new OneofAccessor(descriptor, message => descriptor.Fields[0].Accessor.HasValue(message) ? descriptor.Fields[0].FieldNumber : 0, diff --git a/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs index 0df4f534b2..b41d520515 100644 --- a/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs @@ -59,7 +59,7 @@ namespace Google.Protobuf.Reflection // It's useful to determine whether or not this is a synthetic oneof before cross-linking. That means // diving into the proto directly rather than using FieldDescriptor, but that's okay. - var firstFieldInOneof = parent.Proto.Field.FirstOrDefault(fieldProto => fieldProto.OneofIndex == index); + var firstFieldInOneof = parent.Proto.Field.FirstOrDefault(fieldProto => fieldProto.HasOneofIndex && fieldProto.OneofIndex == index); IsSynthetic = firstFieldInOneof?.Proto3Optional ?? false; accessor = CreateAccessor(clrName); diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs index c75ef0f9a1..2fb1b4d164 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs @@ -91,7 +91,15 @@ namespace Google.Protobuf.WellKnownTypes { /// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) /// .setNanos((int) ((millis % 1000) * 1000000)).build(); /// - /// Example 5: Compute Timestamp from current time in Python. + /// Example 5: Compute Timestamp from Java `Instant.now()`. + /// + /// Instant now = Instant.now(); + /// + /// Timestamp timestamp = + /// Timestamp.newBuilder().setSeconds(now.getEpochSecond()) + /// .setNanos(now.getNano()).build(); + /// + /// Example 6: Compute Timestamp from current time in Python. /// /// timestamp = Timestamp() /// timestamp.GetCurrentTime() diff --git a/docs/csharp/proto2.md b/docs/csharp/proto2.md index 0d9159de73..53fc43c7eb 100644 --- a/docs/csharp/proto2.md +++ b/docs/csharp/proto2.md @@ -97,7 +97,7 @@ foo.GetOrInitializeExtension(RepeatedFooExt).Add(new Baz()); ### Message initialization -Initialization refers to checking the status of required fields in a proto2 message. If a message is uninitialized, not all required fields are set in either the message itself or any of its submessages. In other languages, missing required fields throw errors depending on the merge method used. This could cause unforseen errors at runtime if the incorrect method is used. +Initialization refers to checking the status of required fields in a proto2 message. If a message is uninitialized, not all required fields are set in either the message itself or any of its submessages. In other languages, missing required fields throw errors depending on the merge method used. This could cause unforeseen errors at runtime if the incorrect method is used. However, in this implementation, parsers and input streams don't check messages for initialization on their own and throw errors. Instead it's up to you to handle messages with missing required fields in whatever way you see fit. Checking message initialization can be done manually via the `IsInitialized` extension method in `MessageExtensions`. diff --git a/docs/field_presence.md b/docs/field_presence.md index 4ce778552b..dc16292c85 100644 --- a/docs/field_presence.md +++ b/docs/field_presence.md @@ -127,7 +127,7 @@ The _no presence_ serialization discipline results in visible differences from t ### Considerations for merging -Under the _no presence_ rules, it is effectively impossible for a target field to merge-from its default value (using the protobuf's API merging functions). This is because default values are skipped, simliar to the _no presence_ serialization discipline. Merging only updates the target (merged-to) message using the non-skipped values from the update (merged-from) message. +Under the _no presence_ rules, it is effectively impossible for a target field to merge-from its default value (using the protobuf's API merging functions). This is because default values are skipped, similar to the _no presence_ serialization discipline. Merging only updates the target (merged-to) message using the non-skipped values from the update (merged-from) message. The difference in merging behavior has further implications for protocols which rely on partial "patch" updates. If field presence is not tracked, then an update patch alone cannot represent an update to the default value, because only non-default values are merged-from. diff --git a/docs/implementing_proto3_presence.md b/docs/implementing_proto3_presence.md index fae2eb589a..73f21a3829 100644 --- a/docs/implementing_proto3_presence.md +++ b/docs/implementing_proto3_presence.md @@ -13,7 +13,7 @@ optional fields. First-party code generators developed by Google are being updated already. However third-party code generators will need to be updated independently by their authors. This includes: -- implementations of Protocol Buffers for other languges. +- implementations of Protocol Buffers for other languages. - alternate implementations of Protocol Buffers that target specialized use cases. - RPC code generators that create generated APIs for service calls. diff --git a/docs/options.md b/docs/options.md index df6b88c033..fd1e813797 100644 --- a/docs/options.md +++ b/docs/options.md @@ -244,3 +244,7 @@ with info about your project (name and website) so we can add an entry for you. 1. ADLINK EdgeSDK * Website: https://www.adlinktech.com/en/Edge-SDK-IoT * Extensions: 1086 + +1. Wire wire_package + * Website: https://square.github.io/wire/ + * Extensions: 1087 diff --git a/docs/third_party.md b/docs/third_party.md index c1726a0f17..b9c66c02f1 100644 --- a/docs/third_party.md +++ b/docs/third_party.md @@ -26,8 +26,8 @@ These are projects we know about implementing Protocol Buffers for other program * Clojure: http://github.com/ninjudd/clojure-protobuf * Clojure: https://github.com/clojusc/protobuf * Clojure: https://protojure.github.io -* Common Lisp: http://github.com/ndantam/s-protobuf * Common Lisp: http://github.com/brown/protobuf +* Common Lisp: http://github.com/qitab/cl-protobuf * D: https://github.com/dcarp/protobuf-d * D: https://github.com/msoucy/dproto * D: https://github.com/opticron/ProtocolBuffer @@ -62,6 +62,8 @@ These are projects we know about implementing Protocol Buffers for other program * Javascript: https://github.com/dcodeIO/ProtoBuf.js * Javascript: http://code.google.com/p/protobuf-for-node/ * Javascript: http://code.google.com/p/protostuff/ +* Javascript: https://github.com/seishun/node-protoc-plugin (Node.js port of plugin.h) +* Javascript: https://github.com/seishun/node-protoc-gen-javascript (Node.js port of the Google-official implementation) * Julia: https://github.com/tanmaykm/ProtoBuf.jl * Kotlin: https://github.com/marcoferrer/kroto-plus * Kotlin: https://github.com/Kotlin/kotlinx.serialization @@ -154,7 +156,7 @@ There are miscellaneous other things you may find useful as a Protocol Buffers d * [Alternate encodings (JSON, XML, HTML) for Java protobufs](http://code.google.com/p/protobuf-java-format/) * [Another JSON encoder/decoder for Java](https://github.com/sijuv/protobuf-codec) * [Editor for serialized protobufs](http://code.google.com/p/protobufeditor/) -* [Intellij IDEA plugin](http://github.com/nnmatveev/idea-plugin-protobuf) +* [IntelliJ IDEA plugin](http://github.com/jvolkman/intellij-protobuf-editor) * [TextMate syntax highlighting](http://github.com/michaeledgar/protobuf-tmbundle) * [Oracle PL SQL plugin](http://code.google.com/p/protocol-buffer-plsql/) * [Eclipse editor for protobuf (from Google)](http://code.google.com/p/protobuf-dt/) @@ -184,3 +186,9 @@ There are miscellaneous other things you may find useful as a Protocol Buffers d * [Protocol Buffer property-based testing utility and example message generator (Python / Hypothesis)](https://github.com/CurataEng/hypothesis-protobuf) * [Protolock - CLI utility to prevent backward-incompatible changes to .proto files](https://github.com/nilslice/protolock) * [Optional GRPC - GRPC for testable microservices (Python)](https://github.com/mattpaletta/optional-grpc.git) +* [Protobuf Parser - Yet another Go package which parses a Protocol Buffer file (proto2+proto3)](https://github.com/yoheimuta/go-protoparser) +* [Protolint - A tool to enforce Protocol Buffer style and conventions.](https://github.com/yoheimuta/protolint) + * [vscode-protolint: A protobuf linter for visual studio code](https://github.com/plexsystems/vscode-protolint) + * [intellij-protolint: A protobuf linter for JetBrains IDEs](https://github.com/yoheimuta/intellij-protolint) + * [vim-protolint: A protobuf linter for Vim](https://github.com/yoheimuta/vim-protolint) +* [super-linter: Protocol Buffer lint as GitHub Action](https://github.com/github/super-linter) diff --git a/java/README.md b/java/README.md index c4e8e20de5..dea9e763f2 100644 --- a/java/README.md +++ b/java/README.md @@ -47,7 +47,7 @@ If you are using Gradle, add the following to your `build.gradle` file's depende ``` compile 'com.google.protobuf:protobuf-java:3.11.0' ``` -Again, be sure to check that the version number maches (or is newer than) the version number of protoc that you are using. +Again, be sure to check that the version number matches (or is newer than) the version number of protoc that you are using. ### Use Java Protocol Buffers on Android @@ -68,7 +68,7 @@ how to use them. Most users should follow the instructions above to use protobuf Java runtime. If you are contributing code to protobuf or want to use a protobuf version -that hasn't been officially released yet, you can folllow the instructions +that hasn't been officially released yet, you can follow the instructions below to build protobuf from source code. ### Build from Source - With Maven diff --git a/java/bom/pom.xml b/java/bom/pom.xml index ff2d106764..3642783f6a 100644 --- a/java/bom/pom.xml +++ b/java/bom/pom.xml @@ -4,7 +4,7 @@ com.google.protobuf protobuf-bom - 3.12.3 + 3.13.0 pom Protocol Buffers [BOM] diff --git a/java/core/pom.xml b/java/core/pom.xml index b2b0b0386e..3509163b08 100644 --- a/java/core/pom.xml +++ b/java/core/pom.xml @@ -4,7 +4,7 @@ com.google.protobuf protobuf-parent - 3.12.3 + 3.13.0 protobuf-java diff --git a/java/core/src/main/java/com/google/protobuf/DynamicMessage.java b/java/core/src/main/java/com/google/protobuf/DynamicMessage.java index 63dda6b9f2..8beebba24d 100644 --- a/java/core/src/main/java/com/google/protobuf/DynamicMessage.java +++ b/java/core/src/main/java/com/google/protobuf/DynamicMessage.java @@ -328,20 +328,6 @@ public final class DynamicMessage extends AbstractMessage { this.fields = FieldSet.newFieldSet(); this.unknownFields = UnknownFieldSet.getDefaultInstance(); this.oneofCases = new FieldDescriptor[type.toProto().getOneofDeclCount()]; - // A MapEntry has all of its fields present at all times. - if (type.getOptions().getMapEntry()) { - populateMapEntry(); - } - } - - private void populateMapEntry() { - for (FieldDescriptor field : type.getFields()) { - if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - fields.setField(field, getDefaultInstance(field.getMessageType())); - } else { - fields.setField(field, field.getDefaultValue()); - } - } } // --------------------------------------------------------------- @@ -354,10 +340,6 @@ public final class DynamicMessage extends AbstractMessage { } else { fields.clear(); } - // A MapEntry has all of its fields present at all times. - if (type.getOptions().getMapEntry()) { - populateMapEntry(); - } unknownFields = UnknownFieldSet.getDefaultInstance(); return this; } @@ -423,6 +405,19 @@ public final class DynamicMessage extends AbstractMessage { @Override public DynamicMessage buildPartial() { + // Set default values for all fields in a MapEntry. + if (type.getOptions().getMapEntry()) { + for (FieldDescriptor field : type.getFields()) { + if (field.isOptional() && !fields.hasField(field)) { + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + fields.setField(field, getDefaultInstance(field.getMessageType())); + } else { + fields.setField(field, field.getDefaultValue()); + } + } + } + } + fields.makeImmutable(); DynamicMessage result = new DynamicMessage( diff --git a/java/core/src/main/java/com/google/protobuf/MessageSchema.java b/java/core/src/main/java/com/google/protobuf/MessageSchema.java index 139e55a971..28879d7785 100644 --- a/java/core/src/main/java/com/google/protobuf/MessageSchema.java +++ b/java/core/src/main/java/com/google/protobuf/MessageSchema.java @@ -1402,8 +1402,10 @@ final class MessageSchema implements Schema { if (!isOneofPresent(other, number, pos)) { return; } - - Object mine = UnsafeUtil.getObject(message, offset); + Object mine = null; + if (isOneofPresent(message, number, pos)) { + mine = UnsafeUtil.getObject(message, offset); + } Object theirs = UnsafeUtil.getObject(other, offset); if (mine != null && theirs != null) { Object merged = Internal.mergeMessage(mine, theirs); diff --git a/java/core/src/main/java/com/google/protobuf/TextFormat.java b/java/core/src/main/java/com/google/protobuf/TextFormat.java index bec9623fe8..7f744ddba7 100644 --- a/java/core/src/main/java/com/google/protobuf/TextFormat.java +++ b/java/core/src/main/java/com/google/protobuf/TextFormat.java @@ -1661,7 +1661,7 @@ public final class TextFormat { throws IOException { // Read the entire input to a String then parse that. - // If StreamTokenizer were not quite so crippled, or if there were a kind + // If StreamTokenizer was not so limited, or if there were a kind // of Reader that could read in chunks that match some particular regex, // or if we wanted to write a custom Reader to tokenize our stream, then // we would not have to read to one big String. Alas, none of these is 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 a9a884e196..e229facace 100644 --- a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java +++ b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java @@ -1478,11 +1478,23 @@ public class TextFormatTest extends TestCase { // With overwrite forbidden, same behavior. // TODO(b/29122459): Expect parse exception here. TestMap.Builder builder = TestMap.newBuilder(); - defaultParser.merge(text, builder); + parserWithOverwriteForbidden.merge(text, builder); TestMap map = builder.build(); assertEquals(2, map.getInt32ToInt32Field().size()); assertEquals(30, map.getInt32ToInt32Field().get(1).intValue()); } + + { + // With overwrite forbidden and a dynamic message, same behavior. + // TODO(b/29122459): Expect parse exception here. + Message.Builder builder = DynamicMessage.newBuilder(TestMap.getDescriptor()); + parserWithOverwriteForbidden.merge(text, builder); + TestMap map = + TestMap.parseFrom( + builder.build().toByteString(), ExtensionRegistryLite.getEmptyRegistry()); + assertEquals(2, map.getInt32ToInt32Field().size()); + assertEquals(30, map.getInt32ToInt32Field().get(1).intValue()); + } } // ======================================================================= diff --git a/java/lite/pom.xml b/java/lite/pom.xml index 49686cd7ad..779eacc637 100644 --- a/java/lite/pom.xml +++ b/java/lite/pom.xml @@ -4,7 +4,7 @@ com.google.protobuf protobuf-parent - 3.12.3 + 3.13.0 protobuf-javalite @@ -52,6 +52,7 @@ google/protobuf/any.proto google/protobuf/api.proto + google/protobuf/duration.proto google/protobuf/empty.proto google/protobuf/field_mask.proto google/protobuf/source_context.proto diff --git a/java/lite/src/test/java/com/google/protobuf/LiteTest.java b/java/lite/src/test/java/com/google/protobuf/LiteTest.java index 3e39bc7c8b..140df7270f 100644 --- a/java/lite/src/test/java/com/google/protobuf/LiteTest.java +++ b/java/lite/src/test/java/com/google/protobuf/LiteTest.java @@ -42,6 +42,7 @@ import com.google.protobuf.UnittestLite.TestAllExtensionsLite; import com.google.protobuf.UnittestLite.TestAllTypesLite; import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedEnum; import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedMessage; +import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedMessage2; import com.google.protobuf.UnittestLite.TestAllTypesLite.OneofFieldCase; import com.google.protobuf.UnittestLite.TestAllTypesLite.OptionalGroup; import com.google.protobuf.UnittestLite.TestAllTypesLite.RepeatedGroup; @@ -1354,6 +1355,45 @@ public class LiteTest extends TestCase { assertEquals(message.getSerializedSize() * 2, result.getSerializedSize()); } + public void testMergeFrom_differentFieldsSetWithinOneField() throws Exception { + TestAllTypesLite result = + TestAllTypesLite.newBuilder() + .setOneofNestedMessage(NestedMessage.newBuilder().setBb(2)) + .mergeFrom( + TestAllTypesLite.newBuilder() + .setOneofNestedMessage2(NestedMessage2.newBuilder().setDd(3)) + .build()) + .build(); + + assertToStringEquals("oneof_nested_message2 {\n dd: 3\n}", result); + } + + public void testMergeFrom_differentFieldsOfSameTypeSetWithinOneField() throws Exception { + TestAllTypesLite result = + TestAllTypesLite.newBuilder() + .setOneofNestedMessage(NestedMessage.newBuilder().setBb(2)) + .mergeFrom( + TestAllTypesLite.newBuilder() + .setOneofLazyNestedMessage(NestedMessage.newBuilder().setCc(3)) + .build()) + .build(); + + assertToStringEquals("oneof_lazy_nested_message {\n cc: 3\n}", result); + } + + public void testMergeFrom_sameFieldSetWithinOneofField() throws Exception { + TestAllTypesLite result = + TestAllTypesLite.newBuilder() + .setOneofNestedMessage(NestedMessage.newBuilder().setBb(2)) + .mergeFrom( + TestAllTypesLite.newBuilder() + .setOneofNestedMessage(NestedMessage.newBuilder().setCc(4)) + .build()) + .build(); + + assertToStringEquals("oneof_nested_message {\n bb: 2\n cc: 4\n}", result); + } + public void testToStringDefaultInstance() throws Exception { assertToStringEquals("", TestAllTypesLite.getDefaultInstance()); } diff --git a/java/pom.xml b/java/pom.xml index 0a813e02dc..bb91146fd2 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -4,7 +4,7 @@ com.google.protobuf protobuf-parent - 3.12.3 + 3.13.0 pom Protocol Buffers [Parent] diff --git a/java/util/BUILD b/java/util/BUILD index cfdb28e2e1..71f73bab10 100644 --- a/java/util/BUILD +++ b/java/util/BUILD @@ -5,10 +5,6 @@ java_library( srcs = glob([ "src/main/java/com/google/protobuf/util/*.java", ]), - javacopts = [ - "-source 7", - "-target 7", - ], visibility = ["//visibility:public"], deps = [ "//external:error_prone_annotations", diff --git a/java/util/pom.xml b/java/util/pom.xml index daa123a944..54dcc86907 100644 --- a/java/util/pom.xml +++ b/java/util/pom.xml @@ -4,7 +4,7 @@ com.google.protobuf protobuf-parent - 3.12.3 + 3.13.0 protobuf-java-util diff --git a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java index 67981435d1..cc3f5f658f 100644 --- a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java +++ b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java @@ -328,14 +328,13 @@ public class JsonFormat { /** * Create a new {@link Printer} that will sort the map keys in the JSON output. * - * Use of this modifier is discouraged, the generated JSON messages are equivalent - * with and without this option set, but there are some corner caseuse cases that - * demand a stable output, while order of map keys is otherwise arbitrary. + *

Use of this modifier is discouraged, the generated JSON messages are equivalent with and + * without this option set, but there are some corner use cases that demand a stable output, + * while order of map keys is otherwise arbitrary. * - * The generated order is not well-defined and should not be depended on, but - * it's stable. + *

The generated order is not well-defined and should not be depended on, but it's stable. * - * This new Printer clones all other configurations from the current {@link Printer}. + *

This new Printer clones all other configurations from the current {@link Printer}. */ public Printer sortingMapKeys() { return new Printer( diff --git a/js/experimental/runtime/kernel/kernel_test.js b/js/experimental/runtime/kernel/kernel_test.js index e72be4f3b6..eba7c4a55a 100644 --- a/js/experimental/runtime/kernel/kernel_test.js +++ b/js/experimental/runtime/kernel/kernel_test.js @@ -699,7 +699,7 @@ describe('Bytes access', () => { expect(accessor.getBytesWithDefault(1)).toEqual(simpleByteString); }); - it('decodes value from wire with multple values being present', () => { + it('decodes value from wire with multiple values being present', () => { const accessor = Kernel.fromArrayBuffer( createArrayBuffer(0x0A, 0x01, 0x00, 0x0A, 0x01, 0x01)); expect(accessor.getBytesWithDefault(1)).toEqual(simpleByteString); @@ -801,7 +801,7 @@ describe('Fixed32 access', () => { expect(accessor.getFixed32WithDefault(1)).toEqual(1); }); - it('decodes value from wire with multple values being present', () => { + it('decodes value from wire with multiple values being present', () => { const accessor = Kernel.fromArrayBuffer(createArrayBuffer( 0x0D, 0x01, 0x00, 0x80, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00)); expect(accessor.getFixed32WithDefault(1)).toEqual(2); @@ -909,7 +909,7 @@ describe('Fixed64 access', () => { expect(accessor.getFixed64WithDefault(1)).toEqual(Int64.fromInt(1)); }); - it('decodes value from wire with multple values being present', () => { + it('decodes value from wire with multiple values being present', () => { const accessor = Kernel.fromArrayBuffer(createArrayBuffer( 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); @@ -1008,7 +1008,7 @@ describe('Float access', () => { expect(accessor.getFloatWithDefault(1)).toEqual(1); }); - it('decodes value from wire with multple values being present', () => { + it('decodes value from wire with multiple values being present', () => { const accessor = Kernel.fromArrayBuffer(createArrayBuffer( 0x0D, 0x00, 0x00, 0x80, 0x3F, 0x0D, 0x00, 0x00, 0x80, 0xBF)); expect(accessor.getFloatWithDefault(1)).toEqual(-1); @@ -1110,7 +1110,7 @@ describe('Int32 access', () => { expect(accessor.getInt32WithDefault(1)).toEqual(1); }); - it('decodes value from wire with multple values being present', () => { + it('decodes value from wire with multiple values being present', () => { const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01, 0x08, 0x02)); expect(accessor.getInt32WithDefault(1)).toEqual(2); @@ -1207,7 +1207,7 @@ describe('Int64 access', () => { expect(accessor.getInt64WithDefault(1)).toEqual(Int64.fromInt(1)); }); - it('decodes value from wire with multple values being present', () => { + it('decodes value from wire with multiple values being present', () => { const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01, 0x08, 0x02)); expect(accessor.getInt64WithDefault(1)).toEqual(Int64.fromInt(2)); @@ -1306,7 +1306,7 @@ describe('Sfixed32 access', () => { expect(accessor.getSfixed32WithDefault(1)).toEqual(1); }); - it('decodes value from wire with multple values being present', () => { + it('decodes value from wire with multiple values being present', () => { const accessor = Kernel.fromArrayBuffer(createArrayBuffer( 0x0D, 0x01, 0x00, 0x80, 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00)); expect(accessor.getSfixed32WithDefault(1)).toEqual(2); @@ -1404,7 +1404,7 @@ describe('Sfixed64 access', () => { expect(accessor.getSfixed64WithDefault(1)).toEqual(Int64.fromInt(1)); }); - it('decodes value from wire with multple values being present', () => { + it('decodes value from wire with multiple values being present', () => { const accessor = Kernel.fromArrayBuffer(createArrayBuffer( 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); @@ -1502,7 +1502,7 @@ describe('Sint32 access', () => { expect(accessor.getSint32WithDefault(1)).toEqual(1); }); - it('decodes value from wire with multple values being present', () => { + it('decodes value from wire with multiple values being present', () => { const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x03, 0x08, 0x02)); expect(accessor.getSint32WithDefault(1)).toEqual(1); @@ -1599,7 +1599,7 @@ describe('SInt64 access', () => { expect(accessor.getSint64WithDefault(1)).toEqual(Int64.fromInt(1)); }); - it('decodes value from wire with multple values being present', () => { + it('decodes value from wire with multiple values being present', () => { const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01, 0x08, 0x02)); expect(accessor.getSint64WithDefault(1)).toEqual(Int64.fromInt(1)); @@ -1698,7 +1698,7 @@ describe('String access', () => { expect(accessor.getStringWithDefault(1)).toEqual('a'); }); - it('decodes value from wire with multple values being present', () => { + it('decodes value from wire with multiple values being present', () => { const accessor = Kernel.fromArrayBuffer( createArrayBuffer(0x0A, 0x01, 0x60, 0x0A, 0x01, 0x61)); expect(accessor.getStringWithDefault(1)).toEqual('a'); @@ -1789,7 +1789,7 @@ describe('Uint32 access', () => { expect(accessor.getUint32WithDefault(1)).toEqual(1); }); - it('decodes value from wire with multple values being present', () => { + it('decodes value from wire with multiple values being present', () => { const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01, 0x08, 0x02)); expect(accessor.getUint32WithDefault(1)).toEqual(2); @@ -1896,7 +1896,7 @@ describe('Uint64 access', () => { expect(accessor.getUint64WithDefault(1)).toEqual(Int64.fromInt(1)); }); - it('decodes value from wire with multple values being present', () => { + it('decodes value from wire with multiple values being present', () => { const accessor = Kernel.fromArrayBuffer(createArrayBuffer(0x08, 0x01, 0x08, 0x02)); expect(accessor.getUint64WithDefault(1)).toEqual(Int64.fromInt(2)); @@ -1996,7 +1996,7 @@ describe('Double access', () => { }); - it('decodes value from wire with multple values being present', () => { + it('decodes value from wire with multiple values being present', () => { const accessor = Kernel.fromArrayBuffer(createArrayBuffer( 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xBF)); diff --git a/js/experimental/runtime/kernel/tag_test.js b/js/experimental/runtime/kernel/tag_test.js index 04a6cb6668..35137bb247 100644 --- a/js/experimental/runtime/kernel/tag_test.js +++ b/js/experimental/runtime/kernel/tag_test.js @@ -95,12 +95,12 @@ describe('skipField', () => { it('skips group in group', () => { const buffer = createArrayBuffer( - 0x0B, // start outter + 0x0B, // start outer 0x10, 0x01, // field: 2, value: 1 0x0B, // start inner group 0x10, 0x01, // payload inner group 0x0C, // stop inner group - 0x0C // end outter + 0x0C // end outer ); const bufferDecoder = BufferDecoder.fromArrayBuffer(buffer); bufferDecoder.setCursor(1); diff --git a/kokoro/linux/dockerfile/test/php80/Dockerfile b/kokoro/linux/dockerfile/test/php80/Dockerfile new file mode 100644 index 0000000000..d6c9b4d273 --- /dev/null +++ b/kokoro/linux/dockerfile/test/php80/Dockerfile @@ -0,0 +1,96 @@ +FROM debian:jessie + +# Install dependencies. We start with the basic ones require to build protoc +# and the C++ build +RUN apt-get update && apt-get install -y \ + autoconf \ + autotools-dev \ + build-essential \ + bzip2 \ + ccache \ + curl \ + gcc \ + git \ + libc6 \ + libc6-dbg \ + libc6-dev \ + libgtest-dev \ + libtool \ + make \ + parallel \ + time \ + wget \ + re2c \ + sqlite3 \ + vim \ + libonig-dev \ + libsqlite3-dev \ + && apt-get clean + +# Install php dependencies +RUN apt-get clean && apt-get update && apt-get install -y --force-yes \ + php5 \ + libcurl4-openssl-dev \ + libgmp-dev \ + libgmp3-dev \ + libssl-dev \ + libxml2-dev \ + unzip \ + zlib1g-dev \ + pkg-config \ + && apt-get clean + +# Install other dependencies +RUN ln -sf /usr/include/x86_64-linux-gnu/gmp.h /usr/include/gmp.h +RUN wget https://ftp.gnu.org/gnu/bison/bison-3.0.1.tar.gz -O /var/local/bison-3.0.1.tar.gz +RUN cd /var/local \ + && tar -zxvf bison-3.0.1.tar.gz \ + && cd /var/local/bison-3.0.1 \ + && ./configure \ + && make \ + && make install + +# Install composer +RUN curl -sS https://getcomposer.org/installer | php +RUN mv composer.phar /usr/local/bin/composer + +# Download php source code +RUN git clone https://github.com/php/php-src + +# php 8.0 +RUN cd php-src \ + && git checkout php-8.0.0alpha3 \ + && ./buildconf --force +RUN cd php-src \ + && ./configure \ + --enable-bcmath \ + --enable-mbstring \ + --with-gmp \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-8.0 \ + && make \ + && make install \ + && make clean +RUN cd php-src \ + && ./configure \ + --enable-bcmath \ + --enable-mbstring \ + --enable-maintainer-zts \ + --with-gmp \ + --with-openssl \ + --with-zlib \ + --prefix=/usr/local/php-8.0-zts \ + && make \ + && make install \ + && make clean + +RUN wget -O phpunit https://phar.phpunit.de/phpunit-9.phar \ + && chmod +x phpunit \ + && cp phpunit /usr/local/php-8.0/bin \ + && mv phpunit /usr/local/php-8.0-zts/bin + +# Install php dependencies +RUN apt-get clean && apt-get update && apt-get install -y --force-yes \ + valgrind \ + && apt-get clean diff --git a/kokoro/linux/php80/build.sh b/kokoro/linux/php80/build.sh new file mode 100755 index 0000000000..6499b39af8 --- /dev/null +++ b/kokoro/linux/php80/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/php +export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh +export OUTPUT_DIR=testoutput +export TEST_SET="php8.0_all" +./kokoro/linux/build_and_run_docker.sh diff --git a/kokoro/linux/php80/continuous.cfg b/kokoro/linux/php80/continuous.cfg new file mode 100644 index 0000000000..8426318bbe --- /dev/null +++ b/kokoro/linux/php80/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/php80/build.sh" +timeout_mins: 120 + +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/kokoro/linux/php80/presubmit.cfg b/kokoro/linux/php80/presubmit.cfg new file mode 100644 index 0000000000..8426318bbe --- /dev/null +++ b/kokoro/linux/php80/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/php80/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 18ce60b17f..830e7eee67 100755 --- a/kokoro/macos/prepare_build_macos_rc +++ b/kokoro/macos/prepare_build_macos_rc @@ -66,7 +66,7 @@ fi # Install Tox if [[ "${KOKORO_INSTALL_TOX:-}" == "yes" ]] ; then - sudo pip install tox==2.4.1 + sudo python3 -m pip install --upgrade pip tox fi ## diff --git a/kokoro/release/collect_all_artifacts.sh b/kokoro/release/collect_all_artifacts.sh index 3b7d7d4066..8f6e9db9a0 100755 --- a/kokoro/release/collect_all_artifacts.sh +++ b/kokoro/release/collect_all_artifacts.sh @@ -39,7 +39,7 @@ cp ${INPUT_ARTIFACTS_DIR}/build64/Release/protoc.exe protoc/windows_x64/protoc.e mkdir -p protoc/linux_x86 mkdir -p protoc/linux_x64 # Because of maven unrelated reasonse the linux protoc binaries have a dummy .exe extension. -# For the Google.Protobuf.Tools nuget, we don't want that expection, so we just remove it. +# For the Google.Protobuf.Tools nuget, we don't want that exception, so we just remove it. cp ${INPUT_ARTIFACTS_DIR}/protoc-artifacts/target/linux/x86_32/protoc.exe protoc/linux_x86/protoc cp ${INPUT_ARTIFACTS_DIR}/protoc-artifacts/target/linux/x86_64/protoc.exe protoc/linux_x64/protoc diff --git a/kokoro/release/python/macos/config.sh b/kokoro/release/python/macos/config.sh index 741988a6b5..1b0a302e4c 100644 --- a/kokoro/release/python/macos/config.sh +++ b/kokoro/release/python/macos/config.sh @@ -1,6 +1,25 @@ # Define custom utilities # Test for OSX with [ -n "$IS_OSX" ] +function remove_travis_ve_pip { + # Removing the system virtualenv or pip can be very problematic for + # macOS on Kokoro, so just leave them be. + :; +} + +function install_pip { + check_python + PIP_CMD="sudo $PYTHON_EXE -m pip${pip_args:+ $pip_args}" + $PIP_CMD install --upgrade pip +} + +function install_virtualenv { + check_python + check_pip + $PIP_CMD install --upgrade virtualenv + VIRTUALENV_CMD="$PYTHON_EXE -m virtualenv" +} + function pre_build { # Any stuff that you need to do before you start building the wheels # Runs in the root directory of this repository. diff --git a/objectivec/BUILD b/objectivec/BUILD new file mode 100644 index 0000000000..9f702ec95f --- /dev/null +++ b/objectivec/BUILD @@ -0,0 +1,90 @@ +load("@rules_cc//cc:defs.bzl", "objc_library") + +objc_library( + name = "objectivec", + hdrs = [ + "GPBAny.pbobjc.h", + "GPBApi.pbobjc.h", + "GPBDuration.pbobjc.h", + "GPBEmpty.pbobjc.h", + "GPBFieldMask.pbobjc.h", + "GPBSourceContext.pbobjc.h", + "GPBStruct.pbobjc.h", + "GPBTimestamp.pbobjc.h", + "GPBType.pbobjc.h", + "GPBWrappers.pbobjc.h", + "GPBArray.h", + "GPBBootstrap.h", + "GPBCodedInputStream.h", + "GPBCodedOutputStream.h", + "GPBDescriptor.h", + "GPBDictionary.h", + "GPBExtensionInternals.h", + "GPBExtensionRegistry.h", + "GPBMessage.h", + "GPBProtocolBuffers.h", + "GPBProtocolBuffers_RuntimeSupport.h", + "GPBRootObject.h", + "GPBRuntimeTypes.h", + "GPBUnknownField.h", + "GPBUnknownFieldSet.h", + "GPBUtilities.h", + "GPBWellKnownTypes.h", + "GPBWireFormat.h", + "google/protobuf/Any.pbobjc.h", + "google/protobuf/Api.pbobjc.h", + "google/protobuf/Duration.pbobjc.h", + "google/protobuf/Empty.pbobjc.h", + "google/protobuf/FieldMask.pbobjc.h", + "google/protobuf/SourceContext.pbobjc.h", + "google/protobuf/Struct.pbobjc.h", + "google/protobuf/Timestamp.pbobjc.h", + "google/protobuf/Type.pbobjc.h", + "google/protobuf/Wrappers.pbobjc.h", + # Package private headers, but exposed because the generated sources + # need to use them. + "GPBArray_PackagePrivate.h", + "GPBCodedInputStream_PackagePrivate.h", + "GPBCodedOutputStream_PackagePrivate.h", + "GPBDescriptor_PackagePrivate.h", + "GPBDictionary_PackagePrivate.h", + "GPBMessage_PackagePrivate.h", + "GPBRootObject_PackagePrivate.h", + "GPBUnknownFieldSet_PackagePrivate.h", + "GPBUnknownField_PackagePrivate.h", + "GPBUtilities_PackagePrivate.h", + ], + copts = [ + "-Wno-vla", + ], + includes = [ + ".", + ], + non_arc_srcs = [ + "GPBAny.pbobjc.m", + "GPBApi.pbobjc.m", + "GPBDuration.pbobjc.m", + "GPBEmpty.pbobjc.m", + "GPBFieldMask.pbobjc.m", + "GPBSourceContext.pbobjc.m", + "GPBStruct.pbobjc.m", + "GPBTimestamp.pbobjc.m", + "GPBType.pbobjc.m", + "GPBWrappers.pbobjc.m", + "GPBArray.m", + "GPBCodedInputStream.m", + "GPBCodedOutputStream.m", + "GPBDescriptor.m", + "GPBDictionary.m", + "GPBExtensionInternals.m", + "GPBExtensionRegistry.m", + "GPBMessage.m", + "GPBRootObject.m", + "GPBUnknownField.m", + "GPBUnknownFieldSet.m", + "GPBUtilities.m", + "GPBWellKnownTypes.m", + "GPBWireFormat.m", + ], + visibility = ["//visibility:public"], +) diff --git a/objectivec/DevTools/compile_testing_protos.sh b/objectivec/DevTools/compile_testing_protos.sh index 021e03d0ed..69c32f920b 100755 --- a/objectivec/DevTools/compile_testing_protos.sh +++ b/objectivec/DevTools/compile_testing_protos.sh @@ -95,7 +95,7 @@ cd "${SRCROOT}/.." # ----------------------------------------------------------------------------- RUN_PROTOC=no -# Check to if all the output files exist (incase a new one got added). +# Check to if all the output files exist (in case a new one got added). for PROTO_FILE in "${CORE_PROTO_FILES[@]}" "${OBJC_TEST_PROTO_FILES[@]}"; do DIR=${PROTO_FILE%/*} diff --git a/objectivec/DevTools/full_mac_build.sh b/objectivec/DevTools/full_mac_build.sh index 84ed8e9914..4df131408e 100755 --- a/objectivec/DevTools/full_mac_build.sh +++ b/objectivec/DevTools/full_mac_build.sh @@ -285,7 +285,7 @@ if [[ "${DO_XCODE_IOS_TESTS}" == "yes" ]] ; then -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit -destination "platform=iOS Simulator,name=iPhone 7,OS=latest" # 64bit # 10.x also seems to often fail running destinations in parallel (with - # 32bit one include atleast) + # 32bit one include at least) -disable-concurrent-destination-testing ) ;; diff --git a/objectivec/DevTools/pddm.py b/objectivec/DevTools/pddm.py index dacf7bba00..b572cc75b6 100755 --- a/objectivec/DevTools/pddm.py +++ b/objectivec/DevTools/pddm.py @@ -645,7 +645,7 @@ def main(args): opts, extra_args = parser.parse_args(args) if not extra_args: - parser.error('Need atleast one file to process') + parser.error('Need at least one file to process') result = 0 for a_path in extra_args: diff --git a/objectivec/GPBExtensionInternals.m b/objectivec/GPBExtensionInternals.m index 290c82a1bb..bacec5740a 100644 --- a/objectivec/GPBExtensionInternals.m +++ b/objectivec/GPBExtensionInternals.m @@ -361,8 +361,8 @@ static id NewSingleValueFromInputStream(GPBExtensionDescriptor *extension, if (existingValue) { message = [existingValue retain]; } else { - GPBDescriptor *decriptor = [extension.msgClass descriptor]; - message = [[decriptor.messageClass alloc] init]; + GPBDescriptor *descriptor = [extension.msgClass descriptor]; + message = [[descriptor.messageClass alloc] init]; } if (description->dataType == GPBDataTypeGroup) { diff --git a/objectivec/GPBMessage.m b/objectivec/GPBMessage.m index 8e6aaf16e9..7b1263fde9 100644 --- a/objectivec/GPBMessage.m +++ b/objectivec/GPBMessage.m @@ -3286,7 +3286,7 @@ static void ResolveIvarSet(__unsafe_unretained GPBFieldDescriptor *field, // if a sub message in a field has extensions, the issue still exists. A // recursive check could be done here (like the work in // GPBMessageDropUnknownFieldsRecursively()), but that has the potential to - // be expensive and could slow down serialization in DEBUG enought to cause + // be expensive and could slow down serialization in DEBUG enough to cause // developers other problems. NSLog(@"Warning: writing out a GPBMessage (%@) via NSCoding and it" @" has %ld extensions; when read back in, those fields will be" diff --git a/objectivec/GPBTimestamp.pbobjc.h b/objectivec/GPBTimestamp.pbobjc.h index 92f0bac886..a328afc7c9 100644 --- a/objectivec/GPBTimestamp.pbobjc.h +++ b/objectivec/GPBTimestamp.pbobjc.h @@ -107,7 +107,16 @@ typedef GPB_ENUM(GPBTimestamp_FieldNumber) { * .setNanos((int) ((millis % 1000) * 1000000)).build(); * * - * Example 5: Compute Timestamp from current time in Python. + * Example 5: Compute Timestamp from Java `Instant.now()`. + * + * Instant now = Instant.now(); + * + * Timestamp timestamp = + * Timestamp.newBuilder().setSeconds(now.getEpochSecond()) + * .setNanos(now.getNano()).build(); + * + * + * Example 6: Compute Timestamp from current time in Python. * * timestamp = Timestamp() * timestamp.GetCurrentTime() diff --git a/objectivec/GPBUtilities.m b/objectivec/GPBUtilities.m index ee79d00192..e13210210d 100644 --- a/objectivec/GPBUtilities.m +++ b/objectivec/GPBUtilities.m @@ -219,7 +219,7 @@ void GPBCheckRuntimeVersionSupport(int32_t objcRuntimeVersion) { // Library is too old for headers. [NSException raise:NSInternalInconsistencyException format:@"Linked to ProtocolBuffer runtime version %d," - @" but code compiled needing atleast %d!", + @" but code compiled needing at least %d!", GOOGLE_PROTOBUF_OBJC_VERSION, objcRuntimeVersion]; } if (objcRuntimeVersion < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION) { diff --git a/objectivec/GPBUtilities_PackagePrivate.h b/objectivec/GPBUtilities_PackagePrivate.h index 9c29c39c0b..a620288267 100644 --- a/objectivec/GPBUtilities_PackagePrivate.h +++ b/objectivec/GPBUtilities_PackagePrivate.h @@ -304,7 +304,7 @@ void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self, const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel); // Helper for text format name encoding. -// decodeData is the data describing the sepecial decodes. +// decodeData is the data describing the special decodes. // key and inputString are the input that needs decoding. NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key, NSString *inputString); diff --git a/objectivec/README.md b/objectivec/README.md index 5982939290..2583779d38 100644 --- a/objectivec/README.md +++ b/objectivec/README.md @@ -168,7 +168,7 @@ supported keys are: Any number of files can be listed for a framework, just separate them with commas. - There can be multiple lines listing the same frameworkName incase it has a + There can be multiple lines listing the same frameworkName in case it has a lot of proto files included in it; and having multiple lines makes things easier to read. diff --git a/objectivec/Tests/CocoaPods/run_tests.sh b/objectivec/Tests/CocoaPods/run_tests.sh index 6d3e12be30..35bcc18df7 100755 --- a/objectivec/Tests/CocoaPods/run_tests.sh +++ b/objectivec/Tests/CocoaPods/run_tests.sh @@ -90,7 +90,7 @@ cleanup() { echo "Cleaning up..." # Generally don't let things fail, and eat common stdout, but let stderr show - # incase something does hiccup. + # in case something does hiccup. xcodebuild -workspace "${TEST_NAME}.xcworkspace" -scheme "${TEST_NAME}" clean > /dev/null || true pod deintegrate > /dev/null || true # Flush the cache so nothing is left behind. diff --git a/objectivec/Tests/GPBCodedInputStreamTests.m b/objectivec/Tests/GPBCodedInputStreamTests.m index f5aa69038f..6cd5a1ffd7 100644 --- a/objectivec/Tests/GPBCodedInputStreamTests.m +++ b/objectivec/Tests/GPBCodedInputStreamTests.m @@ -422,7 +422,7 @@ - (void)testBOMWithinStrings { // We've seen servers that end up with BOMs within strings (not always at the // start, and sometimes in multiple places), make sure they always parse - // correctly. (Again, this is inpart incase a custom string class is ever + // correctly. (Again, this is inpart in case a custom string class is ever // used again.) const char* strs[] = { "\xEF\xBB\xBF String with BOM", diff --git a/objectivec/Tests/GPBCodedOuputStreamTests.m b/objectivec/Tests/GPBCodedOuputStreamTests.m index 6c9144fb57..a9934acdac 100644 --- a/objectivec/Tests/GPBCodedOuputStreamTests.m +++ b/objectivec/Tests/GPBCodedOuputStreamTests.m @@ -400,7 +400,7 @@ - (void)testWriteStringsWithZeroChar { // Unicode allows `\0` as a character, and NSString is a class cluster, so - // there are a few different classes that could end up beind a given string. + // there are a few different classes that could end up behind a given string. // Historically, we've seen differences based on constant strings in code and // strings built via the NSString apis. So this round trips them to ensure // they are acting as expected. diff --git a/php/ext/google/protobuf/array.c b/php/ext/google/protobuf/array.c index 571d3e41cd..4615ed31aa 100644 --- a/php/ext/google/protobuf/array.c +++ b/php/ext/google/protobuf/array.c @@ -94,11 +94,12 @@ static void RepeatedField_destructor(zend_object* obj) { zend_object_std_dtor(&intern->std); } -static HashTable *RepeatedField_GetProperties(zval *object TSRMLS_DC) { +static HashTable *RepeatedField_GetProperties(PROTO_VAL *object) { return NULL; // We do not have a properties table. } -static zval *RepeatedField_GetPropertyPtrPtr(zval *object, zval *member, +static zval *RepeatedField_GetPropertyPtrPtr(PROTO_VAL *object, + PROTO_STR *member, int type, void **cache_slot) { return NULL; // We don't offer direct references to our properties. } @@ -392,6 +393,15 @@ PHP_METHOD(RepeatedField, getIterator) { RETURN_ZVAL(&ret, 0, 1); } +ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 1) + ZEND_ARG_INFO(0, type) + ZEND_ARG_INFO(0, class) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_append, 0, 0, 1) + ZEND_ARG_INFO(0, newval) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() @@ -405,8 +415,8 @@ ZEND_BEGIN_ARG_INFO(arginfo_void, 0) ZEND_END_ARG_INFO() static zend_function_entry repeated_field_methods[] = { - PHP_ME(RepeatedField, __construct, NULL, ZEND_ACC_PUBLIC) - PHP_ME(RepeatedField, append, NULL, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedField, __construct, arginfo_construct, ZEND_ACC_PUBLIC) + PHP_ME(RepeatedField, append, arginfo_append, ZEND_ACC_PUBLIC) PHP_ME(RepeatedField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC) PHP_ME(RepeatedField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC) PHP_ME(RepeatedField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC) diff --git a/php/ext/google/protobuf/convert.c b/php/ext/google/protobuf/convert.c index dd076c5f1a..1c2f6288b5 100644 --- a/php/ext/google/protobuf/convert.c +++ b/php/ext/google/protobuf/convert.c @@ -92,20 +92,55 @@ PHP_METHOD(Util, checkRepeatedField) { RETURN_ZVAL(val, 1, 0); } +ZEND_BEGIN_ARG_INFO_EX(arginfo_checkPrimitive, 0, 0, 1) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_checkMessage, 0, 0, 2) + ZEND_ARG_INFO(0, value) + ZEND_ARG_INFO(0, class) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_checkMapField, 0, 0, 3) + ZEND_ARG_INFO(0, value) + ZEND_ARG_INFO(0, key_type) + ZEND_ARG_INFO(0, value_type) + ZEND_ARG_INFO(0, value_class) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_checkRepeatedField, 0, 0, 2) + ZEND_ARG_INFO(0, value) + ZEND_ARG_INFO(0, type) + ZEND_ARG_INFO(0, class) +ZEND_END_ARG_INFO() + static zend_function_entry util_methods[] = { - PHP_ME(Util, checkInt32, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkUint32, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkInt64, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkUint64, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkEnum, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkFloat, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkDouble, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkBool, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkString, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkBytes, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkMessage, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkMapField, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) - PHP_ME(Util, checkRepeatedField, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkInt32, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkUint32, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkInt64, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkUint64, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkEnum, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkFloat, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkDouble, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkBool, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkString, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkBytes, arginfo_checkPrimitive, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkMessage, arginfo_checkMessage, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkMapField, arginfo_checkMapField, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + PHP_ME(Util, checkRepeatedField, arginfo_checkRepeatedField, + ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_FE_END }; diff --git a/php/ext/google/protobuf/def.c b/php/ext/google/protobuf/def.c index c76134d86b..37dd50c182 100644 --- a/php/ext/google/protobuf/def.c +++ b/php/ext/google/protobuf/def.c @@ -180,8 +180,7 @@ PHP_METHOD(EnumDescriptor, getValue) { zend_long index; zval ret; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == - FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) { zend_error(E_USER_ERROR, "Expect integer for index.\n"); return; } @@ -284,8 +283,7 @@ PHP_METHOD(OneofDescriptor, getField) { zend_long index; zval ret; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == - FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) { zend_error(E_USER_ERROR, "Expect integer for index.\n"); return; } @@ -615,8 +613,7 @@ PHP_METHOD(Descriptor, getField) { zval ret; zend_long index; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == - FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) { zend_error(E_USER_ERROR, "Expect integer for index.\n"); return; } @@ -658,8 +655,7 @@ PHP_METHOD(Descriptor, getOneofDecl) { zend_long index; zval ret; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == - FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) { zend_error(E_USER_ERROR, "Expect integer for index.\n"); return; } @@ -799,8 +795,8 @@ PHP_METHOD(DescriptorPool, getDescriptorByClassName) { zend_string *str; zval ret; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &classname, - &classname_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &classname, &classname_len) == + FAILURE) { return; } @@ -828,8 +824,8 @@ PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName) { zend_string *str; zval ret; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &classname, - &classname_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &classname, &classname_len) == + FAILURE) { return; } @@ -856,8 +852,8 @@ PHP_METHOD(DescriptorPool, getDescriptorByProtoName) { zend_long protoname_len; const upb_msgdef *m; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &protoname, - &protoname_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &protoname, &protoname_len) == + FAILURE) { return; } diff --git a/php/ext/google/protobuf/map.c b/php/ext/google/protobuf/map.c index 0217c6491e..f29c18c9bd 100644 --- a/php/ext/google/protobuf/map.c +++ b/php/ext/google/protobuf/map.c @@ -90,12 +90,12 @@ static void MapField_destructor(zend_object* obj) { zend_object_std_dtor(&intern->std); } -static zval *Map_GetPropertyPtrPtr(zval *object, zval *member, int type, - void **cache_slot) { +static zval *Map_GetPropertyPtrPtr(PROTO_VAL *object, PROTO_STR *member, + int type, void **cache_slot) { return NULL; // We don't offer direct references to our properties. } -static HashTable *map_get_properties(zval *object TSRMLS_DC) { +static HashTable *Map_GetProperties(PROTO_VAL *object) { return NULL; // We do not have a properties table. } @@ -378,6 +378,12 @@ PHP_METHOD(MapField, getIterator) { RETURN_ZVAL(&ret, 0, 1); } +ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 2) + ZEND_ARG_INFO(0, key_type) + ZEND_ARG_INFO(0, value_type) + ZEND_ARG_INFO(0, value_class) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_offsetGet, 0, 0, 1) ZEND_ARG_INFO(0, index) ZEND_END_ARG_INFO() @@ -391,7 +397,7 @@ ZEND_BEGIN_ARG_INFO(arginfo_void, 0) ZEND_END_ARG_INFO() static zend_function_entry MapField_methods[] = { - PHP_ME(MapField, __construct, NULL, ZEND_ACC_PUBLIC) + PHP_ME(MapField, __construct, arginfo_construct, ZEND_ACC_PUBLIC) PHP_ME(MapField, offsetExists, arginfo_offsetGet, ZEND_ACC_PUBLIC) PHP_ME(MapField, offsetGet, arginfo_offsetGet, ZEND_ACC_PUBLIC) PHP_ME(MapField, offsetSet, arginfo_offsetSet, ZEND_ACC_PUBLIC) @@ -572,7 +578,7 @@ void Map_ModuleInit() { h = &MapField_object_handlers; memcpy(h, &std_object_handlers, sizeof(zend_object_handlers)); h->dtor_obj = MapField_destructor; - h->get_properties = map_get_properties; + h->get_properties = Map_GetProperties; h->get_property_ptr_ptr = Map_GetPropertyPtrPtr; INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\MapFieldIter", diff --git a/php/ext/google/protobuf/message.c b/php/ext/google/protobuf/message.c index 20dd37a76e..63d2b084aa 100644 --- a/php/ext/google/protobuf/message.c +++ b/php/ext/google/protobuf/message.c @@ -95,10 +95,10 @@ static void Message_dtor(zend_object* obj) { * * Helper function to look up a field given a member name (as a string). */ -static const upb_fielddef *get_field(Message *msg, zval *member) { +static const upb_fielddef *get_field(Message *msg, PROTO_STR *member) { const upb_msgdef *m = msg->desc->msgdef; const upb_fielddef *f = - upb_msgdef_ntof(m, Z_STRVAL_P(member), Z_STRLEN_P(member)); + upb_msgdef_ntof(m, PROTO_STRVAL_P(member), PROTO_STRLEN_P(member)); if (!f) { zend_throw_exception_ex(NULL, 0, "No such property %s.", @@ -108,6 +108,78 @@ static const upb_fielddef *get_field(Message *msg, zval *member) { return f; } +/** + * Message_has_property() + * + * Object handler for testing whether a property exists. Called when PHP code + * does any of: + * + * isset($message->foobar); + * property_exists($message->foobar); + * + * Note that all properties of generated messages are private, so this should + * only be possible to invoke from generated code, which has accessors like this + * (if the field has presence): + * + * public function hasOptionalInt32() + * { + * return isset($this->optional_int32); + * } + */ +static int Message_has_property(PROTO_VAL *obj, PROTO_STR *member, + int has_set_exists, + void **cache_slot) { + Message* intern = PROTO_MSG_P(obj); + const upb_fielddef *f = get_field(intern, member); + + if (!f) return 0; + + if (!upb_fielddef_haspresence(f)) { + zend_throw_exception_ex( + NULL, 0, + "Cannot call isset() on field %s which does not have presence.", + ZSTR_VAL(intern->desc->class_entry->name)); + return 0; + } + + return upb_msg_has(intern->msg, f); +} + +/** + * Message_unset_property() + * + * Object handler for unsetting a property. Called when PHP code calls: + * does any of: + * + * unset($message->foobar); + * + * Note that all properties of generated messages are private, so this should + * only be possible to invoke from generated code, which has accessors like this + * (if the field has presence): + * + * public function clearOptionalInt32() + * { + * unset($this->optional_int32); + * } + */ +static void Message_unset_property(PROTO_VAL *obj, PROTO_STR *member, + void **cache_slot) { + Message* intern = PROTO_MSG_P(obj); + const upb_fielddef *f = get_field(intern, member); + + if (!f) return; + + if (!upb_fielddef_haspresence(f)) { + zend_throw_exception_ex( + NULL, 0, + "Cannot call unset() on field %s which does not have presence.", + ZSTR_VAL(intern->desc->class_entry->name)); + return; + } + + upb_msg_clearfield(intern->msg, f); +} + /** * Message_read_property() * @@ -126,9 +198,9 @@ static const upb_fielddef *get_field(Message *msg, zval *member) { * We lookup the field and return the scalar, RepeatedField, or MapField for * this field. */ -static zval *Message_read_property(zval *obj, zval *member, int type, - void **cache_slot, zval *rv) { - Message* intern = (Message*)Z_OBJ_P(obj); +static zval *Message_read_property(PROTO_VAL *obj, PROTO_STR *member, + int type, void **cache_slot, zval *rv) { + Message* intern = PROTO_MSG_P(obj); const upb_fielddef *f = get_field(intern, member); upb_arena *arena = Arena_Get(&intern->arena); @@ -170,29 +242,41 @@ static zval *Message_read_property(zval *obj, zval *member, int type, * The C extension version of checkInt32() doesn't actually check anything, so * we perform all checking and conversion in this function. */ -static void Message_write_property(zval *obj, zval *member, zval *val, - void **cache_slot) { - Message* intern = (Message*)Z_OBJ_P(obj); +static PROTO_RETURN_VAL Message_write_property( + PROTO_VAL *obj, PROTO_STR *member, zval *val, void **cache_slot) { + Message* intern = PROTO_MSG_P(obj); const upb_fielddef *f = get_field(intern, member); upb_arena *arena = Arena_Get(&intern->arena); upb_msgval msgval; - if (!f) return; + if (!f) goto error; if (upb_fielddef_ismap(f)) { msgval.map_val = MapField_GetUpbMap(val, f, arena); - if (!msgval.map_val) return; + if (!msgval.map_val) goto error; } else if (upb_fielddef_isseq(f)) { msgval.array_val = RepeatedField_GetUpbArray(val, f, arena); - if (!msgval.array_val) return; + if (!msgval.array_val) goto error; } else { upb_fieldtype_t type = upb_fielddef_type(f); const Descriptor *subdesc = Descriptor_GetFromFieldDef(f); bool ok = Convert_PhpToUpb(val, &msgval, type, subdesc, arena); - if (!ok) return; + if (!ok) goto error; } upb_msg_set(intern->msg, f, msgval, arena); +#if PHP_VERSION_ID < 704000 + return; +#else + return val; +#endif + +error: +#if PHP_VERSION_ID < 704000 + return; +#else + return &EG(error_zval); +#endif } /** @@ -202,7 +286,8 @@ static void Message_write_property(zval *obj, zval *member, zval *val, * reference to our internal properties. We don't support this, so we return * NULL. */ -static zval *Message_get_property_ptr_ptr(zval *object, zval *member, int type, +static zval *Message_get_property_ptr_ptr(PROTO_VAL *object, PROTO_STR *member, + int type, void **cache_slot) { return NULL; // We do not have a properties table. } @@ -213,7 +298,7 @@ static zval *Message_get_property_ptr_ptr(zval *object, zval *member, int type, * Object handler for the get_properties event in PHP. This returns a HashTable * of our internal properties. We don't support this, so we return NULL. */ -static HashTable* Message_get_properties(zval* object TSRMLS_DC) { +static HashTable *Message_get_properties(PROTO_VAL *object) { return NULL; // We don't offer direct references to our properties. } @@ -549,7 +634,7 @@ PHP_METHOD(Message, serializeToJsonString) { zend_bool preserve_proto_fieldnames = false; upb_status status; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &preserve_proto_fieldnames) == FAILURE) { return; } @@ -800,20 +885,36 @@ PHP_METHOD(Message, writeOneof) { upb_msg_set(intern->msg, f, msgval, arena); } +ZEND_BEGIN_ARG_INFO_EX(arginfo_void, 0, 0, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_mergeFrom, 0, 0, 1) + ZEND_ARG_INFO(0, data) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_read, 0, 0, 1) + ZEND_ARG_INFO(0, field) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_write, 0, 0, 2) + ZEND_ARG_INFO(0, field) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + static zend_function_entry Message_methods[] = { - PHP_ME(Message, clear, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Message, discardUnknownFields, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Message, serializeToString, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Message, mergeFromString, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Message, serializeToJsonString, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Message, mergeFromJsonString, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Message, mergeFrom, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Message, readWrapperValue, NULL, ZEND_ACC_PROTECTED) - PHP_ME(Message, writeWrapperValue, NULL, ZEND_ACC_PROTECTED) - PHP_ME(Message, readOneof, NULL, ZEND_ACC_PROTECTED) - PHP_ME(Message, writeOneof, NULL, ZEND_ACC_PROTECTED) - PHP_ME(Message, whichOneof, NULL, ZEND_ACC_PROTECTED) - PHP_ME(Message, __construct, NULL, ZEND_ACC_PROTECTED) + PHP_ME(Message, clear, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(Message, discardUnknownFields, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(Message, serializeToString, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(Message, mergeFromString, arginfo_mergeFrom, ZEND_ACC_PUBLIC) + PHP_ME(Message, serializeToJsonString, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(Message, mergeFromJsonString, arginfo_mergeFrom, ZEND_ACC_PUBLIC) + PHP_ME(Message, mergeFrom, arginfo_mergeFrom, ZEND_ACC_PUBLIC) + PHP_ME(Message, readWrapperValue, arginfo_read, ZEND_ACC_PROTECTED) + PHP_ME(Message, writeWrapperValue, arginfo_write, ZEND_ACC_PROTECTED) + PHP_ME(Message, readOneof, arginfo_read, ZEND_ACC_PROTECTED) + PHP_ME(Message, writeOneof, arginfo_write, ZEND_ACC_PROTECTED) + PHP_ME(Message, whichOneof, arginfo_read, ZEND_ACC_PROTECTED) + PHP_ME(Message, __construct, arginfo_void, ZEND_ACC_PROTECTED) ZEND_FE_END }; @@ -836,6 +937,8 @@ void Message_ModuleInit() { h->dtor_obj = Message_dtor; h->read_property = Message_read_property; h->write_property = Message_write_property; + h->has_property = Message_has_property; + h->unset_property = Message_unset_property; h->get_properties = Message_get_properties; h->get_property_ptr_ptr = Message_get_property_ptr_ptr; } diff --git a/php/ext/google/protobuf/package.xml b/php/ext/google/protobuf/package.xml index b8ae8bae71..037fa90d93 100644 --- a/php/ext/google/protobuf/package.xml +++ b/php/ext/google/protobuf/package.xml @@ -10,11 +10,11 @@ protobuf-opensource@google.com yes - 2020-06-01 - + 2020-08-14 + - 3.12.3 - 3.12.3 + 3.13.0 + 3.13.0 stable @@ -51,7 +51,7 @@ - 5.5.9 + 7.0.0 1.4.0 @@ -619,5 +619,61 @@ G A release. 3-Clause BSD License GA release. + + + 3.13.0RC1 + 3.13.0 + + + beta + beta + + 2020-08-05 + + 3-Clause BSD License + GA release. + + + + 3.13.0RC2 + 3.13.0 + + + beta + beta + + 2020-08-05 + + 3-Clause BSD License + GA release. + + + + 3.13.0RC3 + 3.13.0 + + + beta + beta + + 2020-08-12 + + 3-Clause BSD License + GA release. + + + + 3.13.0 + 3.13.0 + + + stable + stable + + 2020-08-14 + + 3-Clause BSD License + GA release. + diff --git a/php/ext/google/protobuf/php-upb.c b/php/ext/google/protobuf/php-upb.c index f5ea2ef20a..6ce85f1e6a 100644 --- a/php/ext/google/protobuf/php-upb.c +++ b/php/ext/google/protobuf/php-upb.c @@ -174,6 +174,11 @@ int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg); #else #define UPB_INFINITY (1.0 / 0.0) #endif +#ifdef NAN +#define UPB_NAN NAN +#else +#define UPB_NAN (0.0 / 0.0) +#endif #include #include @@ -235,11 +240,13 @@ static const unsigned fixed64_ok = (1 << UPB_DTYPE_DOUBLE) | (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_SCALAR_LG2(n) (n) /* n in [0, 2, 3] => op in [0, 2, 3] */ #define OP_STRING 4 -#define OP_SUBMSG 5 +#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 */ @@ -277,7 +284,7 @@ static const int8_t delim_ops[37] = { OP_STRING, /* STRING */ -1, /* GROUP */ OP_SUBMSG, /* MESSAGE */ - OP_STRING, /* BYTES */ + OP_BYTES, /* BYTES */ -1, /* UINT32 */ -1, /* ENUM */ -1, /* SFIXED32 */ @@ -296,7 +303,7 @@ static const int8_t delim_ops[37] = { OP_STRING, /* REPEATED STRING */ OP_SUBMSG, /* REPEATED GROUP */ OP_SUBMSG, /* REPEATED MESSAGE */ - OP_STRING, /* REPEATED BYTES */ + OP_BYTES, /* REPEATED BYTES */ OP_VARPCK_LG2(2), /* REPEATED UINT32 */ OP_VARPCK_LG2(2), /* REPEATED ENUM */ OP_FIXPCK_LG2(2), /* REPEATED SFIXED32 */ @@ -328,6 +335,40 @@ static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg, UPB_NORETURN static void decode_err(upb_decstate *d) { longjmp(d->err, 1); } +void decode_verifyutf8(upb_decstate *d, const char *buf, int len) { + static const uint8_t utf8_offset[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 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, + }; + + int i, j; + uint8_t offset; + + i = 0; + while (i < len) { + offset = utf8_offset[(uint8_t)buf[i]]; + if (offset == 0 || i + offset > len) { + decode_err(d); + } + for (j = i + 1; j < i + offset; j++) { + if ((buf[j] & 0xc0) != 0x80) { + decode_err(d); + } + } + i += offset; + } + if (i != 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)) { @@ -395,7 +436,7 @@ static void decode_munge(int type, wireval *val) { static const upb_msglayout_field *upb_find_field(const upb_msglayout *l, uint32_t field_number) { - static upb_msglayout_field none = {0}; + static upb_msglayout_field none = {0, 0, 0, 0, 0, 0}; /* Lots of optimization opportunities here. */ int i; @@ -473,7 +514,10 @@ static const char *decode_toarray(upb_decstate *d, const char *ptr, memcpy(mem, &val, 1 << op); return ptr; case OP_STRING: - /* Append string. */ + decode_verifyutf8(d, val.str_val.data, val.str_val.size); + /* Fallthrough. */ + case OP_BYTES: + /* Append bytes. */ mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(upb_strview), void); arr->len++; @@ -607,6 +651,9 @@ static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg, break; } case OP_STRING: + decode_verifyutf8(d, val.str_val.data, val.str_val.size); + /* Fallthrough. */ + case OP_BYTES: memcpy(mem, &val, sizeof(upb_strview)); break; case OP_SCALAR_LG2(3): @@ -1892,17 +1939,6 @@ bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) { 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); @@ -2328,15 +2364,28 @@ struct upb_arena { 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, void *ptr, size_t size) { mem_block *block = ptr; + upb_arena *root = arena_findroot(a); - block->next = a->freelist; + /* 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; - a->freelist = block; + root->freelist = block; a->last_size = block->size; - if (!a->freelist_tail) a->freelist_tail = block; + 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); @@ -2371,17 +2420,6 @@ static void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize, return upb_arena_realloc(a, ptr, oldsize, size); } -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; -} - /* Public Arena API ***********************************************************/ upb_arena *arena_initslow(void *mem, size_t n, upb_alloc *alloc) { @@ -2540,9 +2578,9 @@ static const upb_msglayout *const google_protobuf_FileDescriptorProto_submsgs[6] }; 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}, + {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}, @@ -2551,7 +2589,7 @@ static const upb_msglayout_field google_protobuf_FileDescriptorProto__fields[12] {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}, + {12, UPB_SIZE(20, 40), 3, 0, 12, 1}, }; const upb_msglayout google_protobuf_FileDescriptorProto_msginit = { @@ -2571,7 +2609,7 @@ static const upb_msglayout *const google_protobuf_DescriptorProto_submsgs[8] = { }; static const upb_msglayout_field google_protobuf_DescriptorProto__fields[10] = { - {1, UPB_SIZE(4, 8), 1, 0, 9, 1}, + {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}, @@ -2580,7 +2618,7 @@ static const upb_msglayout_field google_protobuf_DescriptorProto__fields[10] = { {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}, + {10, UPB_SIZE(44, 88), 0, 0, 12, 3}, }; const upb_msglayout google_protobuf_DescriptorProto_msginit = { @@ -2635,16 +2673,16 @@ static const upb_msglayout *const google_protobuf_FieldDescriptorProto_submsgs[1 }; 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}, + {1, UPB_SIZE(36, 40), 6, 0, 12, 1}, + {2, UPB_SIZE(44, 56), 7, 0, 12, 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}, + {6, UPB_SIZE(52, 72), 8, 0, 12, 1}, + {7, UPB_SIZE(60, 88), 9, 0, 12, 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}, + {10, UPB_SIZE(68, 104), 10, 0, 12, 1}, {17, UPB_SIZE(32, 32), 5, 0, 8, 1}, }; @@ -2659,7 +2697,7 @@ static const upb_msglayout *const google_protobuf_OneofDescriptorProto_submsgs[1 }; static const upb_msglayout_field google_protobuf_OneofDescriptorProto__fields[2] = { - {1, UPB_SIZE(4, 8), 1, 0, 9, 1}, + {1, UPB_SIZE(4, 8), 1, 0, 12, 1}, {2, UPB_SIZE(12, 24), 2, 0, 11, 1}, }; @@ -2676,11 +2714,11 @@ static const upb_msglayout *const google_protobuf_EnumDescriptorProto_submsgs[3] }; static const upb_msglayout_field google_protobuf_EnumDescriptorProto__fields[5] = { - {1, UPB_SIZE(4, 8), 1, 0, 9, 1}, + {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, 9, 3}, + {5, UPB_SIZE(24, 48), 0, 0, 12, 3}, }; const upb_msglayout google_protobuf_EnumDescriptorProto_msginit = { @@ -2705,7 +2743,7 @@ static const upb_msglayout *const google_protobuf_EnumValueDescriptorProto_subms }; static const upb_msglayout_field google_protobuf_EnumValueDescriptorProto__fields[3] = { - {1, UPB_SIZE(8, 8), 2, 0, 9, 1}, + {1, UPB_SIZE(8, 8), 2, 0, 12, 1}, {2, UPB_SIZE(4, 4), 1, 0, 5, 1}, {3, UPB_SIZE(16, 24), 3, 0, 11, 1}, }; @@ -2722,7 +2760,7 @@ static const upb_msglayout *const google_protobuf_ServiceDescriptorProto_submsgs }; static const upb_msglayout_field google_protobuf_ServiceDescriptorProto__fields[3] = { - {1, UPB_SIZE(4, 8), 1, 0, 9, 1}, + {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}, }; @@ -2738,9 +2776,9 @@ static const upb_msglayout *const google_protobuf_MethodDescriptorProto_submsgs[ }; 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}, + {1, UPB_SIZE(4, 8), 3, 0, 12, 1}, + {2, UPB_SIZE(12, 24), 4, 0, 12, 1}, + {3, UPB_SIZE(20, 40), 5, 0, 12, 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}, @@ -2757,11 +2795,11 @@ static const upb_msglayout *const google_protobuf_FileOptions_submsgs[1] = { }; 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}, + {1, UPB_SIZE(28, 32), 11, 0, 12, 1}, + {8, UPB_SIZE(36, 48), 12, 0, 12, 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}, + {11, UPB_SIZE(44, 64), 13, 0, 12, 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}, @@ -2769,14 +2807,14 @@ static const upb_msglayout_field google_protobuf_FileOptions__fields[21] = { {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}, + {36, UPB_SIZE(52, 80), 14, 0, 12, 1}, + {37, UPB_SIZE(60, 96), 15, 0, 12, 1}, + {39, UPB_SIZE(68, 112), 16, 0, 12, 1}, + {40, UPB_SIZE(76, 128), 17, 0, 12, 1}, + {41, UPB_SIZE(84, 144), 18, 0, 12, 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}, + {44, UPB_SIZE(92, 160), 19, 0, 12, 1}, + {45, UPB_SIZE(100, 176), 20, 0, 12, 1}, {999, UPB_SIZE(108, 192), 0, 0, 11, 3}, }; @@ -2906,12 +2944,12 @@ static const upb_msglayout *const google_protobuf_UninterpretedOption_submsgs[1] 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}, + {3, UPB_SIZE(32, 32), 4, 0, 12, 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}, + {8, UPB_SIZE(48, 64), 6, 0, 12, 1}, }; const upb_msglayout google_protobuf_UninterpretedOption_msginit = { @@ -2921,7 +2959,7 @@ const upb_msglayout google_protobuf_UninterpretedOption_msginit = { }; static const upb_msglayout_field google_protobuf_UninterpretedOption_NamePart__fields[2] = { - {1, UPB_SIZE(4, 8), 2, 0, 9, 2}, + {1, UPB_SIZE(4, 8), 2, 0, 12, 2}, {2, UPB_SIZE(1, 1), 1, 0, 8, 2}, }; @@ -2948,9 +2986,9 @@ const upb_msglayout google_protobuf_SourceCodeInfo_msginit = { 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}, + {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 = { @@ -2975,7 +3013,7 @@ const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit = { 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}, + {2, UPB_SIZE(12, 16), 3, 0, 12, 1}, {3, UPB_SIZE(4, 4), 1, 0, 5, 1}, {4, UPB_SIZE(8, 8), 2, 0, 5, 1}, }; @@ -4383,6 +4421,13 @@ static bool make_layout(const upb_symtab *symtab, const upb_msgdef *m) { 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)) { @@ -4918,13 +4963,21 @@ static bool create_fielddef( 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); + 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; - f->packed_ = false; } return true; @@ -5188,7 +5241,7 @@ static bool build_filedef( const google_protobuf_FieldDescriptorProto *const *exts; const upb_strview* strs; size_t i, n; - decl_counts counts = {0}; + decl_counts counts = {0, 0, 0}; count_types_in_file(file_proto, &counts); @@ -5612,7 +5665,11 @@ const upb_fielddef *upb_msg_whichoneof(const upb_msg *msg, if (upb_oneof_done(&i)) return false; f = upb_oneof_iter_field(&i); field = upb_fielddef_layout(f); - oneof_case = _upb_getoneofcase_field(msg, field); + if (in_oneof(field)) { + oneof_case = _upb_getoneofcase_field(msg, field); + } else { + return _upb_hasbit_field(msg, field) ? f : NULL; + } return oneof_case ? upb_msgdef_itof(m, oneof_case) : NULL; } @@ -6341,6 +6398,7 @@ static upb_strview jsondec_string(jsondec *d) { upb_strview ret; ret.data = buf; ret.size = end - buf; + *end = '\0'; /* Needed for possible strtod(). */ return ret; } case '\\': @@ -6665,7 +6723,7 @@ static upb_msgval jsondec_double(jsondec *d, const upb_fielddef *f) { case JD_STRING: str = jsondec_string(d); if (jsondec_streql(str, "NaN")) { - val.double_val = 0.0 / 0.0; + val.double_val = UPB_NAN; } else if (jsondec_streql(str, "Infinity")) { val.double_val = UPB_INFINITY; } else if (jsondec_streql(str, "-Infinity")) { @@ -6822,7 +6880,7 @@ static void jsondec_field(jsondec *d, upb_msg *msg, const upb_msgdef *m) { return; } - if (upb_fielddef_containingoneof(f) && + if (upb_fielddef_realcontainingoneof(f) && upb_msg_whichoneof(msg, upb_fielddef_containingoneof(f))) { jsondec_err(d, "More than one field for this oneof."); } @@ -7655,7 +7713,7 @@ static const upb_msgdef *jsonenc_getanymsg(jsonenc *e, upb_strview type_url) { ret = upb_symtab_lookupmsg2(e->ext_pool, ptr, end - ptr); if (!ret) { - jsonenc_errf(e, "Couldn't find Any type: %.*s (full URL: " UPB_STRVIEW_FORMAT ")", (int)(end - ptr), ptr, UPB_STRVIEW_ARGS(type_url)); + jsonenc_errf(e, "Couldn't find Any type: %.*s", (int)(end - ptr), ptr); } return ret; @@ -8071,6 +8129,7 @@ size_t upb_json_encode(const upb_msg *msg, const upb_msgdef *m, #undef UPB_ASSERT_DEBUGVAR #undef UPB_UNREACHABLE #undef UPB_INFINITY +#undef UPB_NAN #undef UPB_MSVC_VSNPRINTF #undef _upb_snprintf #undef _upb_vsnprintf diff --git a/php/ext/google/protobuf/php-upb.h b/php/ext/google/protobuf/php-upb.h index a07885ff9c..666ec76d05 100644 --- a/php/ext/google/protobuf/php-upb.h +++ b/php/ext/google/protobuf/php-upb.h @@ -173,6 +173,11 @@ int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg); #else #define UPB_INFINITY (1.0 / 0.0) #endif +#ifdef NAN +#define UPB_NAN NAN +#else +#define UPB_NAN (0.0 / 0.0) +#endif /* ** upb_decode: parsing into a upb_msg using a upb_msglayout. */ @@ -208,7 +213,7 @@ int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg); ** store pointers or integers of at least 32 bits (upb isn't really useful on ** systems where sizeof(void*) < 4). ** -** The table must be homogenous (all values of the same type). In debug +** The table must be homogeneous (all values of the same type). In debug ** mode, we check this on insert and lookup. */ @@ -799,15 +804,6 @@ UPB_INLINE bool upb_strtable_remove(upb_strtable *t, const char *key, * 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); @@ -1072,7 +1068,7 @@ UPB_INLINE uint32_t _upb_getoneofcase(const void *msg, size_t case_ofs) { UPB_INLINE size_t _upb_oneofcase_ofs(const upb_msglayout_field *f) { UPB_ASSERT(f->presence < 0); - return ~(int64_t)f->presence; + return ~(ptrdiff_t)f->presence; } UPB_INLINE uint32_t *_upb_oneofcase_field(upb_msg *msg, @@ -3831,7 +3827,7 @@ extern "C" { #endif enum { - /* When set, emits 0/default values. TOOD(haberman): proto3 only? */ + /* 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) @@ -3879,6 +3875,7 @@ size_t upb_json_encode(const upb_msg *msg, const upb_msgdef *m, #undef UPB_ASSERT_DEBUGVAR #undef UPB_UNREACHABLE #undef UPB_INFINITY +#undef UPB_NAN #undef UPB_MSVC_VSNPRINTF #undef _upb_snprintf #undef _upb_vsnprintf diff --git a/php/ext/google/protobuf/protobuf.c b/php/ext/google/protobuf/protobuf.c index 15c8f9bd72..fa1cc114b1 100644 --- a/php/ext/google/protobuf/protobuf.c +++ b/php/ext/google/protobuf/protobuf.c @@ -273,11 +273,18 @@ const upb_msgdef *NameMap_GetMessage(zend_class_entry *ce) { zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name); if (!ret && ce->create_object) { +#if PHP_VERSION_ID < 80000 zval tmp; zval zv; ZVAL_OBJ(&tmp, ce->create_object(ce)); zend_call_method_with_0_params(&tmp, ce, NULL, "__construct", &zv); zval_ptr_dtor(&tmp); +#else + zval zv; + zend_object *tmp = ce->create_object(ce); + zend_call_method_with_0_params(tmp, ce, NULL, "__construct", &zv); + OBJ_RELEASE(tmp); +#endif zval_ptr_dtor(&zv); ret = zend_hash_find_ptr(&PROTOBUF_G(name_msg_cache), ce->name); } diff --git a/php/ext/google/protobuf/protobuf.h b/php/ext/google/protobuf/protobuf.h index 6a7afae061..3188fe7dcb 100644 --- a/php/ext/google/protobuf/protobuf.h +++ b/php/ext/google/protobuf/protobuf.h @@ -43,6 +43,34 @@ const zval *get_generated_pool(); #define GC_DELREF(h) --GC_REFCOUNT(h) #endif +// Since php 7.4, the write_property() object handler now returns the assigned +// value (after possible type coercions) rather than void. +// https://github.com/php/php-src/blob/PHP-7.4.0/UPGRADING.INTERNALS#L171-L173 +#if PHP_VERSION_ID < 70400 +#define PROTO_RETURN_VAL void +#else +#define PROTO_RETURN_VAL zval* +#endif + +// Sine php 8.0, the Object Handlers API was changed to receive zend_object* +// instead of zval* and zend_string* instead of zval* for property names. +// https://github.com/php/php-src/blob/php-8.0.0beta1/UPGRADING.INTERNALS#L37-L39 +#if PHP_VERSION_ID < 80000 +#define PROTO_VAL zval +#define PROTO_STR zval +#define PROTO_MSG_P(obj) (Message*)Z_OBJ_P(obj) +#define PROTO_STRVAL_P(obj) Z_STRVAL_P(obj) +#define PROTO_STRLEN_P(obj) Z_STRLEN_P(obj) +#else +#define PROTO_VAL zend_object +#define PROTO_STR zend_string +#define PROTO_MSG_P(obj) (Message*)(obj) +#define PROTO_STRVAL_P(obj) ZSTR_VAL(obj) +#define PROTO_STRLEN_P(obj) ZSTR_LEN(obj) +#endif + +#define PHP_PROTOBUF_VERSION "3.13.0" + // ptr -> PHP object cache. This is a weak map that caches lazily-created // wrapper objects around upb types: // * upb_msg* -> Message diff --git a/php/phpunit.xml b/php/phpunit.xml index 769037cf9a..8e7583596b 100644 --- a/php/phpunit.xml +++ b/php/phpunit.xml @@ -3,16 +3,16 @@ colors="true"> - tests/php_implementation_test.php - tests/array_test.php - tests/encode_decode_test.php - tests/generated_class_test.php - tests/generated_phpdoc_test.php - tests/map_field_test.php - tests/well_known_test.php - tests/descriptors_test.php - tests/generated_service_test.php - tests/wrapper_type_setters_test.php + tests/PhpImplementationTest.php + tests/ArrayTest.php + tests/EncodeDecodeTest.php + tests/GeneratedClassTest.php + tests/GeneratedPhpdocTest.php + tests/MapFieldTest.php + tests/WellKnownTest.php + tests/DescriptorsTest.php + tests/GeneratedServiceTest.php + tests/WrapperTypeSettersTest.php diff --git a/php/src/GPBMetadata/Google/Protobuf/Struct.php b/php/src/GPBMetadata/Google/Protobuf/Struct.php index 96b42af41d..8e6191dc7a 100644 --- a/php/src/GPBMetadata/Google/Protobuf/Struct.php +++ b/php/src/GPBMetadata/Google/Protobuf/Struct.php @@ -15,29 +15,8 @@ class Struct return; } $pool->internalAddGeneratedFile(hex2bin( - "0a81050a1c676f6f676c652f70726f746f6275662f7374727563742e7072" . - "6f746f120f676f6f676c652e70726f746f6275662284010a065374727563" . - "7412330a066669656c647318012003280b32232e676f6f676c652e70726f" . - "746f6275662e5374727563742e4669656c6473456e7472791a450a0b4669" . - "656c6473456e747279120b0a036b657918012001280912250a0576616c75" . - "6518022001280b32162e676f6f676c652e70726f746f6275662e56616c75" . - "653a02380122ea010a0556616c756512300a0a6e756c6c5f76616c756518" . - "012001280e321a2e676f6f676c652e70726f746f6275662e4e756c6c5661" . - "6c7565480012160a0c6e756d6265725f76616c7565180220012801480012" . - "160a0c737472696e675f76616c7565180320012809480012140a0a626f6f" . - "6c5f76616c75651804200128084800122f0a0c7374727563745f76616c75" . - "6518052001280b32172e676f6f676c652e70726f746f6275662e53747275" . - "6374480012300a0a6c6973745f76616c756518062001280b321a2e676f6f" . - "676c652e70726f746f6275662e4c69737456616c7565480042060a046b69" . - "6e6422330a094c69737456616c756512260a0676616c7565731801200328" . - "0b32162e676f6f676c652e70726f746f6275662e56616c75652a1b0a094e" . - "756c6c56616c7565120e0a0a4e554c4c5f56414c554510004281010a1363" . - "6f6d2e676f6f676c652e70726f746f627566420b53747275637450726f74" . - "6f50015a316769746875622e636f6d2f676f6c616e672f70726f746f6275" . - "662f7074797065732f7374727563743b7374727563747062f80101a20203" . - "475042aa021e476f6f676c652e50726f746f6275662e57656c6c4b6e6f77" . - "6e5479706573620670726f746f33" - )); + "0a81050a1c676f6f676c652f70726f746f6275662f7374727563742e70726f746f120f676f6f676c652e70726f746f6275662284010a0653747275637412330a066669656c647318012003280b32232e676f6f676c652e70726f746f6275662e5374727563742e4669656c6473456e7472791a450a0b4669656c6473456e747279120b0a036b657918012001280912250a0576616c756518022001280b32162e676f6f676c652e70726f746f6275662e56616c75653a02380122ea010a0556616c756512300a0a6e756c6c5f76616c756518012001280e321a2e676f6f676c652e70726f746f6275662e4e756c6c56616c7565480012160a0c6e756d6265725f76616c7565180220012801480012160a0c737472696e675f76616c7565180320012809480012140a0a626f6f6c5f76616c75651804200128084800122f0a0c7374727563745f76616c756518052001280b32172e676f6f676c652e70726f746f6275662e537472756374480012300a0a6c6973745f76616c756518062001280b321a2e676f6f676c652e70726f746f6275662e4c69737456616c7565480042060a046b696e6422330a094c69737456616c756512260a0676616c75657318012003280b32162e676f6f676c652e70726f746f6275662e56616c75652a1b0a094e756c6c56616c7565120e0a0a4e554c4c5f56414c554510004281010a13636f6d2e676f6f676c652e70726f746f627566420b53747275637450726f746f50015a316769746875622e636f6d2f676f6c616e672f70726f746f6275662f7074797065732f7374727563743b7374727563747062f80101a20203475042aa021e476f6f676c652e50726f746f6275662e57656c6c4b6e6f776e5479706573620670726f746f33" + ), true); static::$is_initialized = true; } diff --git a/php/src/Google/Protobuf/Descriptor.php b/php/src/Google/Protobuf/Descriptor.php index 986b81e12d..36436e2b70 100644 --- a/php/src/Google/Protobuf/Descriptor.php +++ b/php/src/Google/Protobuf/Descriptor.php @@ -97,4 +97,12 @@ class Descriptor { return count($this->internal_desc->getOneofDecl()); } + + /** + * @return int Number of real oneofs in message + */ + public function getRealOneofDeclCount() + { + return $this->internal_desc->getRealOneofDeclCount(); + } } diff --git a/php/src/Google/Protobuf/FieldDescriptor.php b/php/src/Google/Protobuf/FieldDescriptor.php index ac9271f98b..6d08cea9da 100644 --- a/php/src/Google/Protobuf/FieldDescriptor.php +++ b/php/src/Google/Protobuf/FieldDescriptor.php @@ -114,4 +114,12 @@ class FieldDescriptor { return $this->internal_desc->isMap(); } + + /** + * @return boolean + */ + public function hasOptionalKeyword() + { + return $this->internal_desc->hasOptionalKeyword(); + } } diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto.php b/php/src/Google/Protobuf/Internal/DescriptorProto.php index 7cc689d028..e0822d779b 100644 --- a/php/src/Google/Protobuf/Internal/DescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/DescriptorProto.php @@ -20,48 +20,39 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message /** * Generated from protobuf field optional string name = 1; */ - protected $name = ''; - private $has_name = false; + protected $name = null; /** * Generated from protobuf field repeated .google.protobuf.FieldDescriptorProto field = 2; */ private $field; - private $has_field = false; /** * Generated from protobuf field repeated .google.protobuf.FieldDescriptorProto extension = 6; */ private $extension; - private $has_extension = false; /** * Generated from protobuf field repeated .google.protobuf.DescriptorProto nested_type = 3; */ private $nested_type; - private $has_nested_type = false; /** * Generated from protobuf field repeated .google.protobuf.EnumDescriptorProto enum_type = 4; */ private $enum_type; - private $has_enum_type = false; /** * Generated from protobuf field repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; */ private $extension_range; - private $has_extension_range = false; /** * Generated from protobuf field repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; */ private $oneof_decl; - private $has_oneof_decl = false; /** * Generated from protobuf field optional .google.protobuf.MessageOptions options = 7; */ protected $options = null; - private $has_options = false; /** * Generated from protobuf field repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; */ private $reserved_range; - private $has_reserved_range = false; /** * Reserved field names, which may not be used by fields in the same message. * A given name may only be reserved once. @@ -69,7 +60,6 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message * Generated from protobuf field repeated string reserved_name = 10; */ private $reserved_name; - private $has_reserved_name = false; /** * Constructor. @@ -102,7 +92,17 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message */ public function getName() { - return $this->name; + return isset($this->name) ? $this->name : ''; + } + + public function hasName() + { + return isset($this->name); + } + + public function clearName() + { + unset($this->name); } /** @@ -114,16 +114,10 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->name = $var; - $this->has_name = true; return $this; } - public function hasName() - { - return $this->has_name; - } - /** * Generated from protobuf field repeated .google.protobuf.FieldDescriptorProto field = 2; * @return \Google\Protobuf\Internal\RepeatedField @@ -142,16 +136,10 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FieldDescriptorProto::class); $this->field = $arr; - $this->has_field = true; return $this; } - public function hasField() - { - return $this->has_field; - } - /** * Generated from protobuf field repeated .google.protobuf.FieldDescriptorProto extension = 6; * @return \Google\Protobuf\Internal\RepeatedField @@ -170,16 +158,10 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FieldDescriptorProto::class); $this->extension = $arr; - $this->has_extension = true; return $this; } - public function hasExtension() - { - return $this->has_extension; - } - /** * Generated from protobuf field repeated .google.protobuf.DescriptorProto nested_type = 3; * @return \Google\Protobuf\Internal\RepeatedField @@ -198,16 +180,10 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto::class); $this->nested_type = $arr; - $this->has_nested_type = true; return $this; } - public function hasNestedType() - { - return $this->has_nested_type; - } - /** * Generated from protobuf field repeated .google.protobuf.EnumDescriptorProto enum_type = 4; * @return \Google\Protobuf\Internal\RepeatedField @@ -226,16 +202,10 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumDescriptorProto::class); $this->enum_type = $arr; - $this->has_enum_type = true; return $this; } - public function hasEnumType() - { - return $this->has_enum_type; - } - /** * Generated from protobuf field repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; * @return \Google\Protobuf\Internal\RepeatedField @@ -254,16 +224,10 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto\ExtensionRange::class); $this->extension_range = $arr; - $this->has_extension_range = true; return $this; } - public function hasExtensionRange() - { - return $this->has_extension_range; - } - /** * Generated from protobuf field repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; * @return \Google\Protobuf\Internal\RepeatedField @@ -282,23 +246,27 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\OneofDescriptorProto::class); $this->oneof_decl = $arr; - $this->has_oneof_decl = true; return $this; } - public function hasOneofDecl() - { - return $this->has_oneof_decl; - } - /** * Generated from protobuf field optional .google.protobuf.MessageOptions options = 7; * @return \Google\Protobuf\Internal\MessageOptions */ public function getOptions() { - return $this->options; + return isset($this->options) ? $this->options : null; + } + + public function hasOptions() + { + return isset($this->options); + } + + public function clearOptions() + { + unset($this->options); } /** @@ -310,16 +278,10 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkMessage($var, \Google\Protobuf\Internal\MessageOptions::class); $this->options = $var; - $this->has_options = true; return $this; } - public function hasOptions() - { - return $this->has_options; - } - /** * Generated from protobuf field repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; * @return \Google\Protobuf\Internal\RepeatedField @@ -338,16 +300,10 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto\ReservedRange::class); $this->reserved_range = $arr; - $this->has_reserved_range = true; return $this; } - public function hasReservedRange() - { - return $this->has_reserved_range; - } - /** * Reserved field names, which may not be used by fields in the same message. * A given name may only be reserved once. @@ -372,15 +328,9 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING); $this->reserved_name = $arr; - $this->has_reserved_name = true; return $this; } - public function hasReservedName() - { - return $this->has_reserved_name; - } - } diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php b/php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php index 82b5695efe..1594913996 100644 --- a/php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php +++ b/php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php @@ -20,20 +20,17 @@ class ExtensionRange extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional int32 start = 1; */ - protected $start = 0; - private $has_start = false; + protected $start = null; /** * Exclusive. * * Generated from protobuf field optional int32 end = 2; */ - protected $end = 0; - private $has_end = false; + protected $end = null; /** * Generated from protobuf field optional .google.protobuf.ExtensionRangeOptions options = 3; */ protected $options = null; - private $has_options = false; /** * Constructor. @@ -61,7 +58,17 @@ class ExtensionRange extends \Google\Protobuf\Internal\Message */ public function getStart() { - return $this->start; + return isset($this->start) ? $this->start : 0; + } + + public function hasStart() + { + return isset($this->start); + } + + public function clearStart() + { + unset($this->start); } /** @@ -75,16 +82,10 @@ class ExtensionRange extends \Google\Protobuf\Internal\Message { GPBUtil::checkInt32($var); $this->start = $var; - $this->has_start = true; return $this; } - public function hasStart() - { - return $this->has_start; - } - /** * Exclusive. * @@ -93,7 +94,17 @@ class ExtensionRange extends \Google\Protobuf\Internal\Message */ public function getEnd() { - return $this->end; + return isset($this->end) ? $this->end : 0; + } + + public function hasEnd() + { + return isset($this->end); + } + + public function clearEnd() + { + unset($this->end); } /** @@ -107,23 +118,27 @@ class ExtensionRange extends \Google\Protobuf\Internal\Message { GPBUtil::checkInt32($var); $this->end = $var; - $this->has_end = true; return $this; } - public function hasEnd() - { - return $this->has_end; - } - /** * Generated from protobuf field optional .google.protobuf.ExtensionRangeOptions options = 3; * @return \Google\Protobuf\Internal\ExtensionRangeOptions */ public function getOptions() { - return $this->options; + return isset($this->options) ? $this->options : null; + } + + public function hasOptions() + { + return isset($this->options); + } + + public function clearOptions() + { + unset($this->options); } /** @@ -135,16 +150,10 @@ class ExtensionRange extends \Google\Protobuf\Internal\Message { GPBUtil::checkMessage($var, \Google\Protobuf\Internal\ExtensionRangeOptions::class); $this->options = $var; - $this->has_options = true; return $this; } - public function hasOptions() - { - return $this->has_options; - } - } // Adding a class alias for backwards compatibility with the previous class name. diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php b/php/src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php index 8022151abf..f099cc345a 100644 --- a/php/src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php +++ b/php/src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php @@ -24,15 +24,13 @@ class ReservedRange extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional int32 start = 1; */ - protected $start = 0; - private $has_start = false; + protected $start = null; /** * Exclusive. * * Generated from protobuf field optional int32 end = 2; */ - protected $end = 0; - private $has_end = false; + protected $end = null; /** * Constructor. @@ -59,7 +57,17 @@ class ReservedRange extends \Google\Protobuf\Internal\Message */ public function getStart() { - return $this->start; + return isset($this->start) ? $this->start : 0; + } + + public function hasStart() + { + return isset($this->start); + } + + public function clearStart() + { + unset($this->start); } /** @@ -73,16 +81,10 @@ class ReservedRange extends \Google\Protobuf\Internal\Message { GPBUtil::checkInt32($var); $this->start = $var; - $this->has_start = true; return $this; } - public function hasStart() - { - return $this->has_start; - } - /** * Exclusive. * @@ -91,7 +93,17 @@ class ReservedRange extends \Google\Protobuf\Internal\Message */ public function getEnd() { - return $this->end; + return isset($this->end) ? $this->end : 0; + } + + public function hasEnd() + { + return isset($this->end); + } + + public function clearEnd() + { + unset($this->end); } /** @@ -105,16 +117,10 @@ class ReservedRange extends \Google\Protobuf\Internal\Message { GPBUtil::checkInt32($var); $this->end = $var; - $this->has_end = true; return $this; } - public function hasEnd() - { - return $this->has_end; - } - } // Adding a class alias for backwards compatibility with the previous class name. diff --git a/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php b/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php index f5c7fe1482..85dc246634 100644 --- a/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php @@ -20,18 +20,15 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message /** * Generated from protobuf field optional string name = 1; */ - protected $name = ''; - private $has_name = false; + protected $name = null; /** * Generated from protobuf field repeated .google.protobuf.EnumValueDescriptorProto value = 2; */ private $value; - private $has_value = false; /** * Generated from protobuf field optional .google.protobuf.EnumOptions options = 3; */ protected $options = null; - private $has_options = false; /** * Range of reserved numeric values. Reserved numeric values may not be used * by enum values in the same enum declaration. Reserved ranges may not @@ -40,7 +37,6 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message * Generated from protobuf field repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4; */ private $reserved_range; - private $has_reserved_range = false; /** * Reserved enum value names, which may not be reused. A given name may only * be reserved once. @@ -48,7 +44,6 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message * Generated from protobuf field repeated string reserved_name = 5; */ private $reserved_name; - private $has_reserved_name = false; /** * Constructor. @@ -79,7 +74,17 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message */ public function getName() { - return $this->name; + return isset($this->name) ? $this->name : ''; + } + + public function hasName() + { + return isset($this->name); + } + + public function clearName() + { + unset($this->name); } /** @@ -91,16 +96,10 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->name = $var; - $this->has_name = true; return $this; } - public function hasName() - { - return $this->has_name; - } - /** * Generated from protobuf field repeated .google.protobuf.EnumValueDescriptorProto value = 2; * @return \Google\Protobuf\Internal\RepeatedField @@ -119,23 +118,27 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumValueDescriptorProto::class); $this->value = $arr; - $this->has_value = true; return $this; } - public function hasValue() - { - return $this->has_value; - } - /** * Generated from protobuf field optional .google.protobuf.EnumOptions options = 3; * @return \Google\Protobuf\Internal\EnumOptions */ public function getOptions() { - return $this->options; + return isset($this->options) ? $this->options : null; + } + + public function hasOptions() + { + return isset($this->options); + } + + public function clearOptions() + { + unset($this->options); } /** @@ -147,16 +150,10 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkMessage($var, \Google\Protobuf\Internal\EnumOptions::class); $this->options = $var; - $this->has_options = true; return $this; } - public function hasOptions() - { - return $this->has_options; - } - /** * Range of reserved numeric values. Reserved numeric values may not be used * by enum values in the same enum declaration. Reserved ranges may not @@ -183,16 +180,10 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumDescriptorProto\EnumReservedRange::class); $this->reserved_range = $arr; - $this->has_reserved_range = true; return $this; } - public function hasReservedRange() - { - return $this->has_reserved_range; - } - /** * Reserved enum value names, which may not be reused. A given name may only * be reserved once. @@ -217,15 +208,9 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING); $this->reserved_name = $arr; - $this->has_reserved_name = true; return $this; } - public function hasReservedName() - { - return $this->has_reserved_name; - } - } diff --git a/php/src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php b/php/src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php index 949dd89107..7282fccb07 100644 --- a/php/src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php +++ b/php/src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php @@ -26,15 +26,13 @@ class EnumReservedRange extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional int32 start = 1; */ - protected $start = 0; - private $has_start = false; + protected $start = null; /** * Inclusive. * * Generated from protobuf field optional int32 end = 2; */ - protected $end = 0; - private $has_end = false; + protected $end = null; /** * Constructor. @@ -61,7 +59,17 @@ class EnumReservedRange extends \Google\Protobuf\Internal\Message */ public function getStart() { - return $this->start; + return isset($this->start) ? $this->start : 0; + } + + public function hasStart() + { + return isset($this->start); + } + + public function clearStart() + { + unset($this->start); } /** @@ -75,16 +83,10 @@ class EnumReservedRange extends \Google\Protobuf\Internal\Message { GPBUtil::checkInt32($var); $this->start = $var; - $this->has_start = true; return $this; } - public function hasStart() - { - return $this->has_start; - } - /** * Inclusive. * @@ -93,7 +95,17 @@ class EnumReservedRange extends \Google\Protobuf\Internal\Message */ public function getEnd() { - return $this->end; + return isset($this->end) ? $this->end : 0; + } + + public function hasEnd() + { + return isset($this->end); + } + + public function clearEnd() + { + unset($this->end); } /** @@ -107,16 +119,10 @@ class EnumReservedRange extends \Google\Protobuf\Internal\Message { GPBUtil::checkInt32($var); $this->end = $var; - $this->has_end = true; return $this; } - public function hasEnd() - { - return $this->has_end; - } - } // Adding a class alias for backwards compatibility with the previous class name. diff --git a/php/src/Google/Protobuf/Internal/EnumOptions.php b/php/src/Google/Protobuf/Internal/EnumOptions.php index e6500423b1..7a69676059 100644 --- a/php/src/Google/Protobuf/Internal/EnumOptions.php +++ b/php/src/Google/Protobuf/Internal/EnumOptions.php @@ -21,8 +21,7 @@ class EnumOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool allow_alias = 2; */ - protected $allow_alias = false; - private $has_allow_alias = false; + protected $allow_alias = null; /** * Is this enum deprecated? * Depending on the target platform, this can emit Deprecated annotations @@ -31,15 +30,13 @@ class EnumOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool deprecated = 3 [default = false]; */ - protected $deprecated = false; - private $has_deprecated = false; + protected $deprecated = null; /** * The parser stores options it doesn't recognize here. See above. * * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; */ private $uninterpreted_option; - private $has_uninterpreted_option = false; /** * Constructor. @@ -73,7 +70,17 @@ class EnumOptions extends \Google\Protobuf\Internal\Message */ public function getAllowAlias() { - return $this->allow_alias; + return isset($this->allow_alias) ? $this->allow_alias : false; + } + + public function hasAllowAlias() + { + return isset($this->allow_alias); + } + + public function clearAllowAlias() + { + unset($this->allow_alias); } /** @@ -88,16 +95,10 @@ class EnumOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->allow_alias = $var; - $this->has_allow_alias = true; return $this; } - public function hasAllowAlias() - { - return $this->has_allow_alias; - } - /** * Is this enum deprecated? * Depending on the target platform, this can emit Deprecated annotations @@ -109,7 +110,17 @@ class EnumOptions extends \Google\Protobuf\Internal\Message */ public function getDeprecated() { - return $this->deprecated; + return isset($this->deprecated) ? $this->deprecated : false; + } + + public function hasDeprecated() + { + return isset($this->deprecated); + } + + public function clearDeprecated() + { + unset($this->deprecated); } /** @@ -126,16 +137,10 @@ class EnumOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->deprecated = $var; - $this->has_deprecated = true; return $this; } - public function hasDeprecated() - { - return $this->has_deprecated; - } - /** * The parser stores options it doesn't recognize here. See above. * @@ -158,15 +163,9 @@ class EnumOptions extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class); $this->uninterpreted_option = $arr; - $this->has_uninterpreted_option = true; return $this; } - public function hasUninterpretedOption() - { - return $this->has_uninterpreted_option; - } - } diff --git a/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php b/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php index 3dd95583ac..01097b669d 100644 --- a/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php @@ -20,18 +20,15 @@ class EnumValueDescriptorProto extends \Google\Protobuf\Internal\Message /** * Generated from protobuf field optional string name = 1; */ - protected $name = ''; - private $has_name = false; + protected $name = null; /** * Generated from protobuf field optional int32 number = 2; */ - protected $number = 0; - private $has_number = false; + protected $number = null; /** * Generated from protobuf field optional .google.protobuf.EnumValueOptions options = 3; */ protected $options = null; - private $has_options = false; /** * Constructor. @@ -55,7 +52,17 @@ class EnumValueDescriptorProto extends \Google\Protobuf\Internal\Message */ public function getName() { - return $this->name; + return isset($this->name) ? $this->name : ''; + } + + public function hasName() + { + return isset($this->name); + } + + public function clearName() + { + unset($this->name); } /** @@ -67,23 +74,27 @@ class EnumValueDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->name = $var; - $this->has_name = true; return $this; } - public function hasName() - { - return $this->has_name; - } - /** * Generated from protobuf field optional int32 number = 2; * @return int */ public function getNumber() { - return $this->number; + return isset($this->number) ? $this->number : 0; + } + + public function hasNumber() + { + return isset($this->number); + } + + public function clearNumber() + { + unset($this->number); } /** @@ -95,23 +106,27 @@ class EnumValueDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkInt32($var); $this->number = $var; - $this->has_number = true; return $this; } - public function hasNumber() - { - return $this->has_number; - } - /** * Generated from protobuf field optional .google.protobuf.EnumValueOptions options = 3; * @return \Google\Protobuf\Internal\EnumValueOptions */ public function getOptions() { - return $this->options; + return isset($this->options) ? $this->options : null; + } + + public function hasOptions() + { + return isset($this->options); + } + + public function clearOptions() + { + unset($this->options); } /** @@ -123,15 +138,9 @@ class EnumValueDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkMessage($var, \Google\Protobuf\Internal\EnumValueOptions::class); $this->options = $var; - $this->has_options = true; return $this; } - public function hasOptions() - { - return $this->has_options; - } - } diff --git a/php/src/Google/Protobuf/Internal/EnumValueOptions.php b/php/src/Google/Protobuf/Internal/EnumValueOptions.php index 9f9fb3bec1..84ba7bc85b 100644 --- a/php/src/Google/Protobuf/Internal/EnumValueOptions.php +++ b/php/src/Google/Protobuf/Internal/EnumValueOptions.php @@ -23,15 +23,13 @@ class EnumValueOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool deprecated = 1 [default = false]; */ - protected $deprecated = false; - private $has_deprecated = false; + protected $deprecated = null; /** * The parser stores options it doesn't recognize here. See above. * * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; */ private $uninterpreted_option; - private $has_uninterpreted_option = false; /** * Constructor. @@ -64,7 +62,17 @@ class EnumValueOptions extends \Google\Protobuf\Internal\Message */ public function getDeprecated() { - return $this->deprecated; + return isset($this->deprecated) ? $this->deprecated : false; + } + + public function hasDeprecated() + { + return isset($this->deprecated); + } + + public function clearDeprecated() + { + unset($this->deprecated); } /** @@ -81,16 +89,10 @@ class EnumValueOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->deprecated = $var; - $this->has_deprecated = true; return $this; } - public function hasDeprecated() - { - return $this->has_deprecated; - } - /** * The parser stores options it doesn't recognize here. See above. * @@ -113,15 +115,9 @@ class EnumValueOptions extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class); $this->uninterpreted_option = $arr; - $this->has_uninterpreted_option = true; return $this; } - public function hasUninterpretedOption() - { - return $this->has_uninterpreted_option; - } - } diff --git a/php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php b/php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php index 00fbebecaf..b5e27c3e27 100644 --- a/php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php +++ b/php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php @@ -21,7 +21,6 @@ class ExtensionRangeOptions extends \Google\Protobuf\Internal\Message * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; */ private $uninterpreted_option; - private $has_uninterpreted_option = false; /** * Constructor. @@ -60,15 +59,9 @@ class ExtensionRangeOptions extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class); $this->uninterpreted_option = $arr; - $this->has_uninterpreted_option = true; return $this; } - public function hasUninterpretedOption() - { - return $this->has_uninterpreted_option; - } - } diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptor.php b/php/src/Google/Protobuf/Internal/FieldDescriptor.php index 98b516fecc..ce83f63a2b 100644 --- a/php/src/Google/Protobuf/Internal/FieldDescriptor.php +++ b/php/src/Google/Protobuf/Internal/FieldDescriptor.php @@ -229,7 +229,17 @@ class FieldDescriptor } $oneof_index = $proto->hasOneofIndex() ? $proto->getOneofIndex() : -1; - $packed = false; + // TODO: once proto2 is supported, this default should be false + // for proto2. + if ($proto->getLabel() === GPBLabel::REPEATED && + $proto->getType() !== GPBType::MESSAGE && + $proto->getType() !== GPBType::GROUP && + $proto->getType() !== GPBType::STRING && + $proto->getType() !== GPBType::BYTES) { + $packed = true; + } else { + $packed = false; + } $options = $proto->getOptions(); if ($options !== null) { $packed = $options->getPacked(); diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php b/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php index a65ce707ec..5c8823f8dc 100644 --- a/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php @@ -20,26 +20,22 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message /** * Generated from protobuf field optional string name = 1; */ - protected $name = ''; - private $has_name = false; + protected $name = null; /** * Generated from protobuf field optional int32 number = 3; */ - protected $number = 0; - private $has_number = false; + protected $number = null; /** * Generated from protobuf field optional .google.protobuf.FieldDescriptorProto.Label label = 4; */ - protected $label = 0; - private $has_label = false; + protected $label = null; /** * If type_name is set, this need not be set. If both this and type_name * are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. * * Generated from protobuf field optional .google.protobuf.FieldDescriptorProto.Type type = 5; */ - protected $type = 0; - private $has_type = false; + protected $type = null; /** * For message and enum types, this is the name of the type. If the name * starts with a '.', it is fully-qualified. Otherwise, C++-like scoping @@ -49,16 +45,14 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional string type_name = 6; */ - protected $type_name = ''; - private $has_type_name = false; + protected $type_name = null; /** * For extensions, this is the name of the type being extended. It is * resolved in the same manner as type_name. * * Generated from protobuf field optional string extendee = 2; */ - protected $extendee = ''; - private $has_extendee = false; + protected $extendee = null; /** * For numeric types, contains the original text representation of the value. * For booleans, "true" or "false". @@ -68,16 +62,14 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional string default_value = 7; */ - protected $default_value = ''; - private $has_default_value = false; + protected $default_value = null; /** * If set, gives the index of a oneof in the containing type's oneof_decl * list. This field is a member of that oneof. * * Generated from protobuf field optional int32 oneof_index = 9; */ - protected $oneof_index = 0; - private $has_oneof_index = false; + protected $oneof_index = null; /** * JSON name of this field. The value is set by protocol compiler. If the * user has set a "json_name" option on this field, that option's value @@ -86,13 +78,11 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional string json_name = 10; */ - protected $json_name = ''; - private $has_json_name = false; + protected $json_name = null; /** * Generated from protobuf field optional .google.protobuf.FieldOptions options = 8; */ protected $options = null; - private $has_options = false; /** * If true, this is a proto3 "optional". When a proto3 field is optional, it * tracks presence regardless of field type. @@ -115,8 +105,7 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool proto3_optional = 17; */ - protected $proto3_optional = false; - private $has_proto3_optional = false; + protected $proto3_optional = null; /** * Constructor. @@ -186,7 +175,17 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message */ public function getName() { - return $this->name; + return isset($this->name) ? $this->name : ''; + } + + public function hasName() + { + return isset($this->name); + } + + public function clearName() + { + unset($this->name); } /** @@ -198,23 +197,27 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->name = $var; - $this->has_name = true; return $this; } - public function hasName() - { - return $this->has_name; - } - /** * Generated from protobuf field optional int32 number = 3; * @return int */ public function getNumber() { - return $this->number; + return isset($this->number) ? $this->number : 0; + } + + public function hasNumber() + { + return isset($this->number); + } + + public function clearNumber() + { + unset($this->number); } /** @@ -226,23 +229,27 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkInt32($var); $this->number = $var; - $this->has_number = true; return $this; } - public function hasNumber() - { - return $this->has_number; - } - /** * Generated from protobuf field optional .google.protobuf.FieldDescriptorProto.Label label = 4; * @return int */ public function getLabel() { - return $this->label; + return isset($this->label) ? $this->label : 0; + } + + public function hasLabel() + { + return isset($this->label); + } + + public function clearLabel() + { + unset($this->label); } /** @@ -254,16 +261,10 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldDescriptorProto\Label::class); $this->label = $var; - $this->has_label = true; return $this; } - public function hasLabel() - { - return $this->has_label; - } - /** * If type_name is set, this need not be set. If both this and type_name * are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. @@ -273,7 +274,17 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message */ public function getType() { - return $this->type; + return isset($this->type) ? $this->type : 0; + } + + public function hasType() + { + return isset($this->type); + } + + public function clearType() + { + unset($this->type); } /** @@ -288,16 +299,10 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldDescriptorProto\Type::class); $this->type = $var; - $this->has_type = true; return $this; } - public function hasType() - { - return $this->has_type; - } - /** * For message and enum types, this is the name of the type. If the name * starts with a '.', it is fully-qualified. Otherwise, C++-like scoping @@ -310,7 +315,17 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message */ public function getTypeName() { - return $this->type_name; + return isset($this->type_name) ? $this->type_name : ''; + } + + public function hasTypeName() + { + return isset($this->type_name); + } + + public function clearTypeName() + { + unset($this->type_name); } /** @@ -328,16 +343,10 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->type_name = $var; - $this->has_type_name = true; return $this; } - public function hasTypeName() - { - return $this->has_type_name; - } - /** * For extensions, this is the name of the type being extended. It is * resolved in the same manner as type_name. @@ -347,7 +356,17 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message */ public function getExtendee() { - return $this->extendee; + return isset($this->extendee) ? $this->extendee : ''; + } + + public function hasExtendee() + { + return isset($this->extendee); + } + + public function clearExtendee() + { + unset($this->extendee); } /** @@ -362,16 +381,10 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->extendee = $var; - $this->has_extendee = true; return $this; } - public function hasExtendee() - { - return $this->has_extendee; - } - /** * For numeric types, contains the original text representation of the value. * For booleans, "true" or "false". @@ -384,7 +397,17 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message */ public function getDefaultValue() { - return $this->default_value; + return isset($this->default_value) ? $this->default_value : ''; + } + + public function hasDefaultValue() + { + return isset($this->default_value); + } + + public function clearDefaultValue() + { + unset($this->default_value); } /** @@ -402,16 +425,10 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->default_value = $var; - $this->has_default_value = true; return $this; } - public function hasDefaultValue() - { - return $this->has_default_value; - } - /** * If set, gives the index of a oneof in the containing type's oneof_decl * list. This field is a member of that oneof. @@ -421,7 +438,17 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message */ public function getOneofIndex() { - return $this->oneof_index; + return isset($this->oneof_index) ? $this->oneof_index : 0; + } + + public function hasOneofIndex() + { + return isset($this->oneof_index); + } + + public function clearOneofIndex() + { + unset($this->oneof_index); } /** @@ -436,16 +463,10 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkInt32($var); $this->oneof_index = $var; - $this->has_oneof_index = true; return $this; } - public function hasOneofIndex() - { - return $this->has_oneof_index; - } - /** * JSON name of this field. The value is set by protocol compiler. If the * user has set a "json_name" option on this field, that option's value @@ -457,7 +478,17 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message */ public function getJsonName() { - return $this->json_name; + return isset($this->json_name) ? $this->json_name : ''; + } + + public function hasJsonName() + { + return isset($this->json_name); + } + + public function clearJsonName() + { + unset($this->json_name); } /** @@ -474,23 +505,27 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->json_name = $var; - $this->has_json_name = true; return $this; } - public function hasJsonName() - { - return $this->has_json_name; - } - /** * Generated from protobuf field optional .google.protobuf.FieldOptions options = 8; * @return \Google\Protobuf\Internal\FieldOptions */ public function getOptions() { - return $this->options; + return isset($this->options) ? $this->options : null; + } + + public function hasOptions() + { + return isset($this->options); + } + + public function clearOptions() + { + unset($this->options); } /** @@ -502,16 +537,10 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FieldOptions::class); $this->options = $var; - $this->has_options = true; return $this; } - public function hasOptions() - { - return $this->has_options; - } - /** * If true, this is a proto3 "optional". When a proto3 field is optional, it * tracks presence regardless of field type. @@ -537,7 +566,17 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message */ public function getProto3Optional() { - return $this->proto3_optional; + return isset($this->proto3_optional) ? $this->proto3_optional : false; + } + + public function hasProto3Optional() + { + return isset($this->proto3_optional); + } + + public function clearProto3Optional() + { + unset($this->proto3_optional); } /** @@ -568,15 +607,9 @@ class FieldDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->proto3_optional = $var; - $this->has_proto3_optional = true; return $this; } - public function hasProto3Optional() - { - return $this->has_proto3_optional; - } - } diff --git a/php/src/Google/Protobuf/Internal/FieldOptions.php b/php/src/Google/Protobuf/Internal/FieldOptions.php index c57077d858..c6c63a9665 100644 --- a/php/src/Google/Protobuf/Internal/FieldOptions.php +++ b/php/src/Google/Protobuf/Internal/FieldOptions.php @@ -23,8 +23,7 @@ class FieldOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; */ - protected $ctype = 0; - private $has_ctype = false; + protected $ctype = null; /** * The packed option can be enabled for repeated primitive fields to enable * a more efficient representation on the wire. Rather than repeatedly @@ -34,8 +33,7 @@ class FieldOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool packed = 2; */ - protected $packed = false; - private $has_packed = false; + protected $packed = null; /** * The jstype option determines the JavaScript type used for values of the * field. The option is permitted only for 64 bit integral and fixed types @@ -50,8 +48,7 @@ class FieldOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; */ - protected $jstype = 0; - private $has_jstype = false; + protected $jstype = null; /** * Should this field be parsed lazily? Lazy applies only to message-type * fields. It means that when the outer message is initially parsed, the @@ -80,8 +77,7 @@ class FieldOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool lazy = 5 [default = false]; */ - protected $lazy = false; - private $has_lazy = false; + protected $lazy = null; /** * Is this field deprecated? * Depending on the target platform, this can emit Deprecated annotations @@ -90,22 +86,19 @@ class FieldOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool deprecated = 3 [default = false]; */ - protected $deprecated = false; - private $has_deprecated = false; + protected $deprecated = null; /** * For Google-internal migration only. Do not use. * * Generated from protobuf field optional bool weak = 10 [default = false]; */ - protected $weak = false; - private $has_weak = false; + protected $weak = null; /** * The parser stores options it doesn't recognize here. See above. * * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; */ private $uninterpreted_option; - private $has_uninterpreted_option = false; /** * Constructor. @@ -187,7 +180,17 @@ class FieldOptions extends \Google\Protobuf\Internal\Message */ public function getCtype() { - return $this->ctype; + return isset($this->ctype) ? $this->ctype : 0; + } + + public function hasCtype() + { + return isset($this->ctype); + } + + public function clearCtype() + { + unset($this->ctype); } /** @@ -204,16 +207,10 @@ class FieldOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldOptions\CType::class); $this->ctype = $var; - $this->has_ctype = true; return $this; } - public function hasCtype() - { - return $this->has_ctype; - } - /** * The packed option can be enabled for repeated primitive fields to enable * a more efficient representation on the wire. Rather than repeatedly @@ -226,7 +223,17 @@ class FieldOptions extends \Google\Protobuf\Internal\Message */ public function getPacked() { - return $this->packed; + return isset($this->packed) ? $this->packed : false; + } + + public function hasPacked() + { + return isset($this->packed); + } + + public function clearPacked() + { + unset($this->packed); } /** @@ -244,16 +251,10 @@ class FieldOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->packed = $var; - $this->has_packed = true; return $this; } - public function hasPacked() - { - return $this->has_packed; - } - /** * The jstype option determines the JavaScript type used for values of the * field. The option is permitted only for 64 bit integral and fixed types @@ -271,7 +272,17 @@ class FieldOptions extends \Google\Protobuf\Internal\Message */ public function getJstype() { - return $this->jstype; + return isset($this->jstype) ? $this->jstype : 0; + } + + public function hasJstype() + { + return isset($this->jstype); + } + + public function clearJstype() + { + unset($this->jstype); } /** @@ -294,16 +305,10 @@ class FieldOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldOptions\JSType::class); $this->jstype = $var; - $this->has_jstype = true; return $this; } - public function hasJstype() - { - return $this->has_jstype; - } - /** * Should this field be parsed lazily? Lazy applies only to message-type * fields. It means that when the outer message is initially parsed, the @@ -335,7 +340,17 @@ class FieldOptions extends \Google\Protobuf\Internal\Message */ public function getLazy() { - return $this->lazy; + return isset($this->lazy) ? $this->lazy : false; + } + + public function hasLazy() + { + return isset($this->lazy); + } + + public function clearLazy() + { + unset($this->lazy); } /** @@ -372,16 +387,10 @@ class FieldOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->lazy = $var; - $this->has_lazy = true; return $this; } - public function hasLazy() - { - return $this->has_lazy; - } - /** * Is this field deprecated? * Depending on the target platform, this can emit Deprecated annotations @@ -393,7 +402,17 @@ class FieldOptions extends \Google\Protobuf\Internal\Message */ public function getDeprecated() { - return $this->deprecated; + return isset($this->deprecated) ? $this->deprecated : false; + } + + public function hasDeprecated() + { + return isset($this->deprecated); + } + + public function clearDeprecated() + { + unset($this->deprecated); } /** @@ -410,16 +429,10 @@ class FieldOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->deprecated = $var; - $this->has_deprecated = true; return $this; } - public function hasDeprecated() - { - return $this->has_deprecated; - } - /** * For Google-internal migration only. Do not use. * @@ -428,7 +441,17 @@ class FieldOptions extends \Google\Protobuf\Internal\Message */ public function getWeak() { - return $this->weak; + return isset($this->weak) ? $this->weak : false; + } + + public function hasWeak() + { + return isset($this->weak); + } + + public function clearWeak() + { + unset($this->weak); } /** @@ -442,16 +465,10 @@ class FieldOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->weak = $var; - $this->has_weak = true; return $this; } - public function hasWeak() - { - return $this->has_weak; - } - /** * The parser stores options it doesn't recognize here. See above. * @@ -474,15 +491,9 @@ class FieldOptions extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class); $this->uninterpreted_option = $arr; - $this->has_uninterpreted_option = true; return $this; } - public function hasUninterpretedOption() - { - return $this->has_uninterpreted_option; - } - } diff --git a/php/src/Google/Protobuf/Internal/FileDescriptorProto.php b/php/src/Google/Protobuf/Internal/FileDescriptorProto.php index c9e3648c23..96e2c6a6e7 100644 --- a/php/src/Google/Protobuf/Internal/FileDescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/FileDescriptorProto.php @@ -22,29 +22,25 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional string name = 1; */ - protected $name = ''; - private $has_name = false; + protected $name = null; /** * e.g. "foo", "foo.bar", etc. * * Generated from protobuf field optional string package = 2; */ - protected $package = ''; - private $has_package = false; + protected $package = null; /** * Names of files imported by this file. * * Generated from protobuf field repeated string dependency = 3; */ private $dependency; - private $has_dependency = false; /** * Indexes of the public imported files in the dependency list above. * * Generated from protobuf field repeated int32 public_dependency = 10; */ private $public_dependency; - private $has_public_dependency = false; /** * Indexes of the weak imported files in the dependency list. * For Google-internal migration only. Do not use. @@ -52,34 +48,28 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message * Generated from protobuf field repeated int32 weak_dependency = 11; */ private $weak_dependency; - private $has_weak_dependency = false; /** * All top-level definitions in this file. * * Generated from protobuf field repeated .google.protobuf.DescriptorProto message_type = 4; */ private $message_type; - private $has_message_type = false; /** * Generated from protobuf field repeated .google.protobuf.EnumDescriptorProto enum_type = 5; */ private $enum_type; - private $has_enum_type = false; /** * Generated from protobuf field repeated .google.protobuf.ServiceDescriptorProto service = 6; */ private $service; - private $has_service = false; /** * Generated from protobuf field repeated .google.protobuf.FieldDescriptorProto extension = 7; */ private $extension; - private $has_extension = false; /** * Generated from protobuf field optional .google.protobuf.FileOptions options = 8; */ protected $options = null; - private $has_options = false; /** * This field contains optional information about the original source code. * You may safely remove this entire field without harming runtime @@ -89,15 +79,13 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message * Generated from protobuf field optional .google.protobuf.SourceCodeInfo source_code_info = 9; */ protected $source_code_info = null; - private $has_source_code_info = false; /** * The syntax of the proto file. * The supported values are "proto2" and "proto3". * * Generated from protobuf field optional string syntax = 12; */ - protected $syntax = ''; - private $has_syntax = false; + protected $syntax = null; /** * Constructor. @@ -145,7 +133,17 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message */ public function getName() { - return $this->name; + return isset($this->name) ? $this->name : ''; + } + + public function hasName() + { + return isset($this->name); + } + + public function clearName() + { + unset($this->name); } /** @@ -159,16 +157,10 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->name = $var; - $this->has_name = true; return $this; } - public function hasName() - { - return $this->has_name; - } - /** * e.g. "foo", "foo.bar", etc. * @@ -177,7 +169,17 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message */ public function getPackage() { - return $this->package; + return isset($this->package) ? $this->package : ''; + } + + public function hasPackage() + { + return isset($this->package); + } + + public function clearPackage() + { + unset($this->package); } /** @@ -191,16 +193,10 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->package = $var; - $this->has_package = true; return $this; } - public function hasPackage() - { - return $this->has_package; - } - /** * Names of files imported by this file. * @@ -223,16 +219,10 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING); $this->dependency = $arr; - $this->has_dependency = true; return $this; } - public function hasDependency() - { - return $this->has_dependency; - } - /** * Indexes of the public imported files in the dependency list above. * @@ -255,16 +245,10 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32); $this->public_dependency = $arr; - $this->has_public_dependency = true; return $this; } - public function hasPublicDependency() - { - return $this->has_public_dependency; - } - /** * Indexes of the weak imported files in the dependency list. * For Google-internal migration only. Do not use. @@ -289,16 +273,10 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32); $this->weak_dependency = $arr; - $this->has_weak_dependency = true; return $this; } - public function hasWeakDependency() - { - return $this->has_weak_dependency; - } - /** * All top-level definitions in this file. * @@ -321,16 +299,10 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto::class); $this->message_type = $arr; - $this->has_message_type = true; return $this; } - public function hasMessageType() - { - return $this->has_message_type; - } - /** * Generated from protobuf field repeated .google.protobuf.EnumDescriptorProto enum_type = 5; * @return \Google\Protobuf\Internal\RepeatedField @@ -349,16 +321,10 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumDescriptorProto::class); $this->enum_type = $arr; - $this->has_enum_type = true; return $this; } - public function hasEnumType() - { - return $this->has_enum_type; - } - /** * Generated from protobuf field repeated .google.protobuf.ServiceDescriptorProto service = 6; * @return \Google\Protobuf\Internal\RepeatedField @@ -377,16 +343,10 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\ServiceDescriptorProto::class); $this->service = $arr; - $this->has_service = true; return $this; } - public function hasService() - { - return $this->has_service; - } - /** * Generated from protobuf field repeated .google.protobuf.FieldDescriptorProto extension = 7; * @return \Google\Protobuf\Internal\RepeatedField @@ -405,23 +365,27 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FieldDescriptorProto::class); $this->extension = $arr; - $this->has_extension = true; return $this; } - public function hasExtension() - { - return $this->has_extension; - } - /** * Generated from protobuf field optional .google.protobuf.FileOptions options = 8; * @return \Google\Protobuf\Internal\FileOptions */ public function getOptions() { - return $this->options; + return isset($this->options) ? $this->options : null; + } + + public function hasOptions() + { + return isset($this->options); + } + + public function clearOptions() + { + unset($this->options); } /** @@ -433,16 +397,10 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FileOptions::class); $this->options = $var; - $this->has_options = true; return $this; } - public function hasOptions() - { - return $this->has_options; - } - /** * This field contains optional information about the original source code. * You may safely remove this entire field without harming runtime @@ -454,7 +412,17 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message */ public function getSourceCodeInfo() { - return $this->source_code_info; + return isset($this->source_code_info) ? $this->source_code_info : null; + } + + public function hasSourceCodeInfo() + { + return isset($this->source_code_info); + } + + public function clearSourceCodeInfo() + { + unset($this->source_code_info); } /** @@ -471,16 +439,10 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkMessage($var, \Google\Protobuf\Internal\SourceCodeInfo::class); $this->source_code_info = $var; - $this->has_source_code_info = true; return $this; } - public function hasSourceCodeInfo() - { - return $this->has_source_code_info; - } - /** * The syntax of the proto file. * The supported values are "proto2" and "proto3". @@ -490,7 +452,17 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message */ public function getSyntax() { - return $this->syntax; + return isset($this->syntax) ? $this->syntax : ''; + } + + public function hasSyntax() + { + return isset($this->syntax); + } + + public function clearSyntax() + { + unset($this->syntax); } /** @@ -505,15 +477,9 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->syntax = $var; - $this->has_syntax = true; return $this; } - public function hasSyntax() - { - return $this->has_syntax; - } - } diff --git a/php/src/Google/Protobuf/Internal/FileDescriptorSet.php b/php/src/Google/Protobuf/Internal/FileDescriptorSet.php index 9907b17d73..794e6347a3 100644 --- a/php/src/Google/Protobuf/Internal/FileDescriptorSet.php +++ b/php/src/Google/Protobuf/Internal/FileDescriptorSet.php @@ -22,7 +22,6 @@ class FileDescriptorSet extends \Google\Protobuf\Internal\Message * Generated from protobuf field repeated .google.protobuf.FileDescriptorProto file = 1; */ private $file; - private $has_file = false; /** * Constructor. @@ -56,15 +55,9 @@ class FileDescriptorSet extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FileDescriptorProto::class); $this->file = $arr; - $this->has_file = true; return $this; } - public function hasFile() - { - return $this->has_file; - } - } diff --git a/php/src/Google/Protobuf/Internal/FileOptions.php b/php/src/Google/Protobuf/Internal/FileOptions.php index 666c6c9075..f415b07f2c 100644 --- a/php/src/Google/Protobuf/Internal/FileOptions.php +++ b/php/src/Google/Protobuf/Internal/FileOptions.php @@ -23,8 +23,7 @@ class FileOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional string java_package = 1; */ - protected $java_package = ''; - private $has_java_package = false; + protected $java_package = null; /** * If set, all the classes from the .proto file are wrapped in a single * outer class with the given name. This applies to both Proto1 @@ -34,8 +33,7 @@ class FileOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional string java_outer_classname = 8; */ - protected $java_outer_classname = ''; - private $has_java_outer_classname = false; + protected $java_outer_classname = null; /** * If set true, then the Java code generator will generate a separate .java * file for each top-level message, enum, and service defined in the .proto @@ -46,15 +44,13 @@ class FileOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool java_multiple_files = 10 [default = false]; */ - protected $java_multiple_files = false; - private $has_java_multiple_files = false; + protected $java_multiple_files = null; /** * This option does nothing. * * Generated from protobuf field optional bool java_generate_equals_and_hash = 20 [deprecated = true]; */ - protected $java_generate_equals_and_hash = false; - private $has_java_generate_equals_and_hash = false; + protected $java_generate_equals_and_hash = null; /** * If set true, then the Java2 code generator will generate code that * throws an exception whenever an attempt is made to assign a non-UTF-8 @@ -65,13 +61,11 @@ class FileOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool java_string_check_utf8 = 27 [default = false]; */ - protected $java_string_check_utf8 = false; - private $has_java_string_check_utf8 = false; + protected $java_string_check_utf8 = null; /** * Generated from protobuf field optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; */ - protected $optimize_for = 0; - private $has_optimize_for = false; + protected $optimize_for = null; /** * Sets the Go package where structs generated from this .proto will be * placed. If omitted, the Go package will be derived from the following: @@ -81,8 +75,7 @@ class FileOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional string go_package = 11; */ - protected $go_package = ''; - private $has_go_package = false; + protected $go_package = null; /** * Should generic services be generated in each language? "Generic" services * are not specific to any particular RPC system. They are generated by the @@ -96,23 +89,19 @@ class FileOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool cc_generic_services = 16 [default = false]; */ - protected $cc_generic_services = false; - private $has_cc_generic_services = false; + protected $cc_generic_services = null; /** * Generated from protobuf field optional bool java_generic_services = 17 [default = false]; */ - protected $java_generic_services = false; - private $has_java_generic_services = false; + protected $java_generic_services = null; /** * Generated from protobuf field optional bool py_generic_services = 18 [default = false]; */ - protected $py_generic_services = false; - private $has_py_generic_services = false; + protected $py_generic_services = null; /** * Generated from protobuf field optional bool php_generic_services = 42 [default = false]; */ - protected $php_generic_services = false; - private $has_php_generic_services = false; + protected $php_generic_services = null; /** * Is this file deprecated? * Depending on the target platform, this can emit Deprecated annotations @@ -121,31 +110,27 @@ class FileOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool deprecated = 23 [default = false]; */ - protected $deprecated = false; - private $has_deprecated = false; + protected $deprecated = null; /** * Enables the use of arenas for the proto messages in this file. This applies * only to generated classes for C++. * * Generated from protobuf field optional bool cc_enable_arenas = 31 [default = true]; */ - protected $cc_enable_arenas = false; - private $has_cc_enable_arenas = false; + protected $cc_enable_arenas = null; /** * Sets the objective c class prefix which is prepended to all objective c * generated classes from this .proto. There is no default. * * Generated from protobuf field optional string objc_class_prefix = 36; */ - protected $objc_class_prefix = ''; - private $has_objc_class_prefix = false; + protected $objc_class_prefix = null; /** * Namespace for generated classes; defaults to the package. * * Generated from protobuf field optional string csharp_namespace = 37; */ - protected $csharp_namespace = ''; - private $has_csharp_namespace = false; + protected $csharp_namespace = null; /** * By default Swift generators will take the proto package and CamelCase it * replacing '.' with underscore and use that to prefix the types/symbols @@ -154,16 +139,14 @@ class FileOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional string swift_prefix = 39; */ - protected $swift_prefix = ''; - private $has_swift_prefix = false; + protected $swift_prefix = null; /** * Sets the php class prefix which is prepended to all php generated classes * from this .proto. Default is empty. * * Generated from protobuf field optional string php_class_prefix = 40; */ - protected $php_class_prefix = ''; - private $has_php_class_prefix = false; + protected $php_class_prefix = null; /** * Use this option to change the namespace of php generated classes. Default * is empty. When this option is empty, the package name will be used for @@ -171,8 +154,7 @@ class FileOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional string php_namespace = 41; */ - protected $php_namespace = ''; - private $has_php_namespace = false; + protected $php_namespace = null; /** * Use this option to change the namespace of php generated metadata classes. * Default is empty. When this option is empty, the proto file name will be @@ -180,8 +162,7 @@ class FileOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional string php_metadata_namespace = 44; */ - protected $php_metadata_namespace = ''; - private $has_php_metadata_namespace = false; + protected $php_metadata_namespace = null; /** * Use this option to change the package of ruby generated classes. Default * is empty. When this option is not set, the package name will be used for @@ -189,8 +170,7 @@ class FileOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional string ruby_package = 45; */ - protected $ruby_package = ''; - private $has_ruby_package = false; + protected $ruby_package = null; /** * The parser stores options it doesn't recognize here. * See the documentation for the "Options" section above. @@ -198,7 +178,6 @@ class FileOptions extends \Google\Protobuf\Internal\Message * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; */ private $uninterpreted_option; - private $has_uninterpreted_option = false; /** * Constructor. @@ -307,7 +286,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message */ public function getJavaPackage() { - return $this->java_package; + return isset($this->java_package) ? $this->java_package : ''; + } + + public function hasJavaPackage() + { + return isset($this->java_package); + } + + public function clearJavaPackage() + { + unset($this->java_package); } /** @@ -324,16 +313,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->java_package = $var; - $this->has_java_package = true; return $this; } - public function hasJavaPackage() - { - return $this->has_java_package; - } - /** * If set, all the classes from the .proto file are wrapped in a single * outer class with the given name. This applies to both Proto1 @@ -346,7 +329,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message */ public function getJavaOuterClassname() { - return $this->java_outer_classname; + return isset($this->java_outer_classname) ? $this->java_outer_classname : ''; + } + + public function hasJavaOuterClassname() + { + return isset($this->java_outer_classname); + } + + public function clearJavaOuterClassname() + { + unset($this->java_outer_classname); } /** @@ -364,16 +357,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->java_outer_classname = $var; - $this->has_java_outer_classname = true; return $this; } - public function hasJavaOuterClassname() - { - return $this->has_java_outer_classname; - } - /** * If set true, then the Java code generator will generate a separate .java * file for each top-level message, enum, and service defined in the .proto @@ -387,7 +374,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message */ public function getJavaMultipleFiles() { - return $this->java_multiple_files; + return isset($this->java_multiple_files) ? $this->java_multiple_files : false; + } + + public function hasJavaMultipleFiles() + { + return isset($this->java_multiple_files); + } + + public function clearJavaMultipleFiles() + { + unset($this->java_multiple_files); } /** @@ -406,16 +403,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->java_multiple_files = $var; - $this->has_java_multiple_files = true; return $this; } - public function hasJavaMultipleFiles() - { - return $this->has_java_multiple_files; - } - /** * This option does nothing. * @@ -424,7 +415,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message */ public function getJavaGenerateEqualsAndHash() { - return $this->java_generate_equals_and_hash; + return isset($this->java_generate_equals_and_hash) ? $this->java_generate_equals_and_hash : false; + } + + public function hasJavaGenerateEqualsAndHash() + { + return isset($this->java_generate_equals_and_hash); + } + + public function clearJavaGenerateEqualsAndHash() + { + unset($this->java_generate_equals_and_hash); } /** @@ -438,16 +439,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->java_generate_equals_and_hash = $var; - $this->has_java_generate_equals_and_hash = true; return $this; } - public function hasJavaGenerateEqualsAndHash() - { - return $this->has_java_generate_equals_and_hash; - } - /** * If set true, then the Java2 code generator will generate code that * throws an exception whenever an attempt is made to assign a non-UTF-8 @@ -461,7 +456,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message */ public function getJavaStringCheckUtf8() { - return $this->java_string_check_utf8; + return isset($this->java_string_check_utf8) ? $this->java_string_check_utf8 : false; + } + + public function hasJavaStringCheckUtf8() + { + return isset($this->java_string_check_utf8); + } + + public function clearJavaStringCheckUtf8() + { + unset($this->java_string_check_utf8); } /** @@ -480,23 +485,27 @@ class FileOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->java_string_check_utf8 = $var; - $this->has_java_string_check_utf8 = true; return $this; } - public function hasJavaStringCheckUtf8() - { - return $this->has_java_string_check_utf8; - } - /** * Generated from protobuf field optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; * @return int */ public function getOptimizeFor() { - return $this->optimize_for; + return isset($this->optimize_for) ? $this->optimize_for : 0; + } + + public function hasOptimizeFor() + { + return isset($this->optimize_for); + } + + public function clearOptimizeFor() + { + unset($this->optimize_for); } /** @@ -508,16 +517,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FileOptions\OptimizeMode::class); $this->optimize_for = $var; - $this->has_optimize_for = true; return $this; } - public function hasOptimizeFor() - { - return $this->has_optimize_for; - } - /** * Sets the Go package where structs generated from this .proto will be * placed. If omitted, the Go package will be derived from the following: @@ -530,7 +533,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message */ public function getGoPackage() { - return $this->go_package; + return isset($this->go_package) ? $this->go_package : ''; + } + + public function hasGoPackage() + { + return isset($this->go_package); + } + + public function clearGoPackage() + { + unset($this->go_package); } /** @@ -548,16 +561,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->go_package = $var; - $this->has_go_package = true; return $this; } - public function hasGoPackage() - { - return $this->has_go_package; - } - /** * Should generic services be generated in each language? "Generic" services * are not specific to any particular RPC system. They are generated by the @@ -574,7 +581,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message */ public function getCcGenericServices() { - return $this->cc_generic_services; + return isset($this->cc_generic_services) ? $this->cc_generic_services : false; + } + + public function hasCcGenericServices() + { + return isset($this->cc_generic_services); + } + + public function clearCcGenericServices() + { + unset($this->cc_generic_services); } /** @@ -596,23 +613,27 @@ class FileOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->cc_generic_services = $var; - $this->has_cc_generic_services = true; return $this; } - public function hasCcGenericServices() - { - return $this->has_cc_generic_services; - } - /** * Generated from protobuf field optional bool java_generic_services = 17 [default = false]; * @return bool */ public function getJavaGenericServices() { - return $this->java_generic_services; + return isset($this->java_generic_services) ? $this->java_generic_services : false; + } + + public function hasJavaGenericServices() + { + return isset($this->java_generic_services); + } + + public function clearJavaGenericServices() + { + unset($this->java_generic_services); } /** @@ -624,23 +645,27 @@ class FileOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->java_generic_services = $var; - $this->has_java_generic_services = true; return $this; } - public function hasJavaGenericServices() - { - return $this->has_java_generic_services; - } - /** * Generated from protobuf field optional bool py_generic_services = 18 [default = false]; * @return bool */ public function getPyGenericServices() { - return $this->py_generic_services; + return isset($this->py_generic_services) ? $this->py_generic_services : false; + } + + public function hasPyGenericServices() + { + return isset($this->py_generic_services); + } + + public function clearPyGenericServices() + { + unset($this->py_generic_services); } /** @@ -652,23 +677,27 @@ class FileOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->py_generic_services = $var; - $this->has_py_generic_services = true; return $this; } - public function hasPyGenericServices() - { - return $this->has_py_generic_services; - } - /** * Generated from protobuf field optional bool php_generic_services = 42 [default = false]; * @return bool */ public function getPhpGenericServices() { - return $this->php_generic_services; + return isset($this->php_generic_services) ? $this->php_generic_services : false; + } + + public function hasPhpGenericServices() + { + return isset($this->php_generic_services); + } + + public function clearPhpGenericServices() + { + unset($this->php_generic_services); } /** @@ -680,16 +709,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->php_generic_services = $var; - $this->has_php_generic_services = true; return $this; } - public function hasPhpGenericServices() - { - return $this->has_php_generic_services; - } - /** * Is this file deprecated? * Depending on the target platform, this can emit Deprecated annotations @@ -701,7 +724,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message */ public function getDeprecated() { - return $this->deprecated; + return isset($this->deprecated) ? $this->deprecated : false; + } + + public function hasDeprecated() + { + return isset($this->deprecated); + } + + public function clearDeprecated() + { + unset($this->deprecated); } /** @@ -718,16 +751,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->deprecated = $var; - $this->has_deprecated = true; return $this; } - public function hasDeprecated() - { - return $this->has_deprecated; - } - /** * Enables the use of arenas for the proto messages in this file. This applies * only to generated classes for C++. @@ -737,7 +764,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message */ public function getCcEnableArenas() { - return $this->cc_enable_arenas; + return isset($this->cc_enable_arenas) ? $this->cc_enable_arenas : false; + } + + public function hasCcEnableArenas() + { + return isset($this->cc_enable_arenas); + } + + public function clearCcEnableArenas() + { + unset($this->cc_enable_arenas); } /** @@ -752,16 +789,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->cc_enable_arenas = $var; - $this->has_cc_enable_arenas = true; return $this; } - public function hasCcEnableArenas() - { - return $this->has_cc_enable_arenas; - } - /** * Sets the objective c class prefix which is prepended to all objective c * generated classes from this .proto. There is no default. @@ -771,7 +802,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message */ public function getObjcClassPrefix() { - return $this->objc_class_prefix; + return isset($this->objc_class_prefix) ? $this->objc_class_prefix : ''; + } + + public function hasObjcClassPrefix() + { + return isset($this->objc_class_prefix); + } + + public function clearObjcClassPrefix() + { + unset($this->objc_class_prefix); } /** @@ -786,16 +827,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->objc_class_prefix = $var; - $this->has_objc_class_prefix = true; return $this; } - public function hasObjcClassPrefix() - { - return $this->has_objc_class_prefix; - } - /** * Namespace for generated classes; defaults to the package. * @@ -804,7 +839,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message */ public function getCsharpNamespace() { - return $this->csharp_namespace; + return isset($this->csharp_namespace) ? $this->csharp_namespace : ''; + } + + public function hasCsharpNamespace() + { + return isset($this->csharp_namespace); + } + + public function clearCsharpNamespace() + { + unset($this->csharp_namespace); } /** @@ -818,16 +863,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->csharp_namespace = $var; - $this->has_csharp_namespace = true; return $this; } - public function hasCsharpNamespace() - { - return $this->has_csharp_namespace; - } - /** * By default Swift generators will take the proto package and CamelCase it * replacing '.' with underscore and use that to prefix the types/symbols @@ -839,7 +878,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message */ public function getSwiftPrefix() { - return $this->swift_prefix; + return isset($this->swift_prefix) ? $this->swift_prefix : ''; + } + + public function hasSwiftPrefix() + { + return isset($this->swift_prefix); + } + + public function clearSwiftPrefix() + { + unset($this->swift_prefix); } /** @@ -856,16 +905,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->swift_prefix = $var; - $this->has_swift_prefix = true; return $this; } - public function hasSwiftPrefix() - { - return $this->has_swift_prefix; - } - /** * Sets the php class prefix which is prepended to all php generated classes * from this .proto. Default is empty. @@ -875,7 +918,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message */ public function getPhpClassPrefix() { - return $this->php_class_prefix; + return isset($this->php_class_prefix) ? $this->php_class_prefix : ''; + } + + public function hasPhpClassPrefix() + { + return isset($this->php_class_prefix); + } + + public function clearPhpClassPrefix() + { + unset($this->php_class_prefix); } /** @@ -890,16 +943,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->php_class_prefix = $var; - $this->has_php_class_prefix = true; return $this; } - public function hasPhpClassPrefix() - { - return $this->has_php_class_prefix; - } - /** * Use this option to change the namespace of php generated classes. Default * is empty. When this option is empty, the package name will be used for @@ -910,7 +957,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message */ public function getPhpNamespace() { - return $this->php_namespace; + return isset($this->php_namespace) ? $this->php_namespace : ''; + } + + public function hasPhpNamespace() + { + return isset($this->php_namespace); + } + + public function clearPhpNamespace() + { + unset($this->php_namespace); } /** @@ -926,16 +983,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->php_namespace = $var; - $this->has_php_namespace = true; return $this; } - public function hasPhpNamespace() - { - return $this->has_php_namespace; - } - /** * Use this option to change the namespace of php generated metadata classes. * Default is empty. When this option is empty, the proto file name will be @@ -946,7 +997,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message */ public function getPhpMetadataNamespace() { - return $this->php_metadata_namespace; + return isset($this->php_metadata_namespace) ? $this->php_metadata_namespace : ''; + } + + public function hasPhpMetadataNamespace() + { + return isset($this->php_metadata_namespace); + } + + public function clearPhpMetadataNamespace() + { + unset($this->php_metadata_namespace); } /** @@ -962,16 +1023,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->php_metadata_namespace = $var; - $this->has_php_metadata_namespace = true; return $this; } - public function hasPhpMetadataNamespace() - { - return $this->has_php_metadata_namespace; - } - /** * Use this option to change the package of ruby generated classes. Default * is empty. When this option is not set, the package name will be used for @@ -982,7 +1037,17 @@ class FileOptions extends \Google\Protobuf\Internal\Message */ public function getRubyPackage() { - return $this->ruby_package; + return isset($this->ruby_package) ? $this->ruby_package : ''; + } + + public function hasRubyPackage() + { + return isset($this->ruby_package); + } + + public function clearRubyPackage() + { + unset($this->ruby_package); } /** @@ -998,16 +1063,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->ruby_package = $var; - $this->has_ruby_package = true; return $this; } - public function hasRubyPackage() - { - return $this->has_ruby_package; - } - /** * The parser stores options it doesn't recognize here. * See the documentation for the "Options" section above. @@ -1032,15 +1091,9 @@ class FileOptions extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class); $this->uninterpreted_option = $arr; - $this->has_uninterpreted_option = true; return $this; } - public function hasUninterpretedOption() - { - return $this->has_uninterpreted_option; - } - } diff --git a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php index f5a65bea46..c261ed6ec9 100644 --- a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php +++ b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php @@ -26,7 +26,6 @@ class GeneratedCodeInfo extends \Google\Protobuf\Internal\Message * Generated from protobuf field repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; */ private $annotation; - private $has_annotation = false; /** * Constructor. @@ -68,15 +67,9 @@ class GeneratedCodeInfo extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\GeneratedCodeInfo\Annotation::class); $this->annotation = $arr; - $this->has_annotation = true; return $this; } - public function hasAnnotation() - { - return $this->has_annotation; - } - } diff --git a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php index 369fea4892..0b043d0665 100644 --- a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php +++ b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php @@ -22,22 +22,19 @@ class Annotation extends \Google\Protobuf\Internal\Message * Generated from protobuf field repeated int32 path = 1 [packed = true]; */ private $path; - private $has_path = false; /** * Identifies the filesystem path to the original source .proto. * * Generated from protobuf field optional string source_file = 2; */ - protected $source_file = ''; - private $has_source_file = false; + protected $source_file = null; /** * Identifies the starting offset in bytes in the generated code * that relates to the identified object. * * Generated from protobuf field optional int32 begin = 3; */ - protected $begin = 0; - private $has_begin = false; + protected $begin = null; /** * Identifies the ending offset in bytes in the generated code that * relates to the identified offset. The end offset should be one past @@ -45,8 +42,7 @@ class Annotation extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional int32 end = 4; */ - protected $end = 0; - private $has_end = false; + protected $end = null; /** * Constructor. @@ -97,16 +93,10 @@ class Annotation extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32); $this->path = $arr; - $this->has_path = true; return $this; } - public function hasPath() - { - return $this->has_path; - } - /** * Identifies the filesystem path to the original source .proto. * @@ -115,7 +105,17 @@ class Annotation extends \Google\Protobuf\Internal\Message */ public function getSourceFile() { - return $this->source_file; + return isset($this->source_file) ? $this->source_file : ''; + } + + public function hasSourceFile() + { + return isset($this->source_file); + } + + public function clearSourceFile() + { + unset($this->source_file); } /** @@ -129,16 +129,10 @@ class Annotation extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->source_file = $var; - $this->has_source_file = true; return $this; } - public function hasSourceFile() - { - return $this->has_source_file; - } - /** * Identifies the starting offset in bytes in the generated code * that relates to the identified object. @@ -148,7 +142,17 @@ class Annotation extends \Google\Protobuf\Internal\Message */ public function getBegin() { - return $this->begin; + return isset($this->begin) ? $this->begin : 0; + } + + public function hasBegin() + { + return isset($this->begin); + } + + public function clearBegin() + { + unset($this->begin); } /** @@ -163,16 +167,10 @@ class Annotation extends \Google\Protobuf\Internal\Message { GPBUtil::checkInt32($var); $this->begin = $var; - $this->has_begin = true; return $this; } - public function hasBegin() - { - return $this->has_begin; - } - /** * Identifies the ending offset in bytes in the generated code that * relates to the identified offset. The end offset should be one past @@ -183,7 +181,17 @@ class Annotation extends \Google\Protobuf\Internal\Message */ public function getEnd() { - return $this->end; + return isset($this->end) ? $this->end : 0; + } + + public function hasEnd() + { + return isset($this->end); + } + + public function clearEnd() + { + unset($this->end); } /** @@ -199,16 +207,10 @@ class Annotation extends \Google\Protobuf\Internal\Message { GPBUtil::checkInt32($var); $this->end = $var; - $this->has_end = true; return $this; } - public function hasEnd() - { - return $this->has_end; - } - } // Adding a class alias for backwards compatibility with the previous class name. diff --git a/php/src/Google/Protobuf/Internal/Message.php b/php/src/Google/Protobuf/Internal/Message.php index 77614bc0e9..c02d2b4517 100644 --- a/php/src/Google/Protobuf/Internal/Message.php +++ b/php/src/Google/Protobuf/Internal/Message.php @@ -225,6 +225,15 @@ class Message } } + protected function hasOneof($number) + { + $field = $this->desc->getFieldByNumber($number); + $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()]; + $oneof_name = $oneof->getName(); + $oneof_field = $this->$oneof_name; + return $number === $oneof_field->getNumber(); + } + protected function writeOneof($number, $value) { $field = $this->desc->getFieldByNumber($number); @@ -1559,14 +1568,19 @@ class Message */ private function existField($field) { - $oneof_index = $field->getOneofIndex(); - if ($oneof_index !== -1) { - $oneof = $this->desc->getOneofDecl()[$oneof_index]; - $oneof_name = $oneof->getName(); - return $this->$oneof_name->getNumber() === $field->getNumber(); + $getter = $field->getGetter(); + $hazzer = "has" . substr($getter, 3); + + if (method_exists($this, $hazzer)) { + return $this->$hazzer(); + } else if ($field->getOneofIndex() !== -1) { + // For old generated code, which does not have hazzers for oneof + // fields. + $oneof = $this->desc->getOneofDecl()[$field->getOneofIndex()]; + $oneof_name = $oneof->getName(); + return $this->$oneof_name->getNumber() === $field->getNumber(); } - $getter = $field->getGetter(); $values = $this->$getter(); if ($field->isMap()) { return count($values) !== 0; diff --git a/php/src/Google/Protobuf/Internal/MessageOptions.php b/php/src/Google/Protobuf/Internal/MessageOptions.php index 95bb706a5a..2f4e3cb7f4 100644 --- a/php/src/Google/Protobuf/Internal/MessageOptions.php +++ b/php/src/Google/Protobuf/Internal/MessageOptions.php @@ -34,8 +34,7 @@ class MessageOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool message_set_wire_format = 1 [default = false]; */ - protected $message_set_wire_format = false; - private $has_message_set_wire_format = false; + protected $message_set_wire_format = null; /** * Disables the generation of the standard "descriptor()" accessor, which can * conflict with a field of the same name. This is meant to make migration @@ -43,8 +42,7 @@ class MessageOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool no_standard_descriptor_accessor = 2 [default = false]; */ - protected $no_standard_descriptor_accessor = false; - private $has_no_standard_descriptor_accessor = false; + protected $no_standard_descriptor_accessor = null; /** * Is this message deprecated? * Depending on the target platform, this can emit Deprecated annotations @@ -53,8 +51,7 @@ class MessageOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool deprecated = 3 [default = false]; */ - protected $deprecated = false; - private $has_deprecated = false; + protected $deprecated = null; /** * Whether the message is an automatically generated map entry type for the * maps field. @@ -77,15 +74,13 @@ class MessageOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool map_entry = 7; */ - protected $map_entry = false; - private $has_map_entry = false; + protected $map_entry = null; /** * The parser stores options it doesn't recognize here. See above. * * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; */ private $uninterpreted_option; - private $has_uninterpreted_option = false; /** * Constructor. @@ -168,7 +163,17 @@ class MessageOptions extends \Google\Protobuf\Internal\Message */ public function getMessageSetWireFormat() { - return $this->message_set_wire_format; + return isset($this->message_set_wire_format) ? $this->message_set_wire_format : false; + } + + public function hasMessageSetWireFormat() + { + return isset($this->message_set_wire_format); + } + + public function clearMessageSetWireFormat() + { + unset($this->message_set_wire_format); } /** @@ -196,16 +201,10 @@ class MessageOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->message_set_wire_format = $var; - $this->has_message_set_wire_format = true; return $this; } - public function hasMessageSetWireFormat() - { - return $this->has_message_set_wire_format; - } - /** * Disables the generation of the standard "descriptor()" accessor, which can * conflict with a field of the same name. This is meant to make migration @@ -216,7 +215,17 @@ class MessageOptions extends \Google\Protobuf\Internal\Message */ public function getNoStandardDescriptorAccessor() { - return $this->no_standard_descriptor_accessor; + return isset($this->no_standard_descriptor_accessor) ? $this->no_standard_descriptor_accessor : false; + } + + public function hasNoStandardDescriptorAccessor() + { + return isset($this->no_standard_descriptor_accessor); + } + + public function clearNoStandardDescriptorAccessor() + { + unset($this->no_standard_descriptor_accessor); } /** @@ -232,16 +241,10 @@ class MessageOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->no_standard_descriptor_accessor = $var; - $this->has_no_standard_descriptor_accessor = true; return $this; } - public function hasNoStandardDescriptorAccessor() - { - return $this->has_no_standard_descriptor_accessor; - } - /** * Is this message deprecated? * Depending on the target platform, this can emit Deprecated annotations @@ -253,7 +256,17 @@ class MessageOptions extends \Google\Protobuf\Internal\Message */ public function getDeprecated() { - return $this->deprecated; + return isset($this->deprecated) ? $this->deprecated : false; + } + + public function hasDeprecated() + { + return isset($this->deprecated); + } + + public function clearDeprecated() + { + unset($this->deprecated); } /** @@ -270,16 +283,10 @@ class MessageOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->deprecated = $var; - $this->has_deprecated = true; return $this; } - public function hasDeprecated() - { - return $this->has_deprecated; - } - /** * Whether the message is an automatically generated map entry type for the * maps field. @@ -305,7 +312,17 @@ class MessageOptions extends \Google\Protobuf\Internal\Message */ public function getMapEntry() { - return $this->map_entry; + return isset($this->map_entry) ? $this->map_entry : false; + } + + public function hasMapEntry() + { + return isset($this->map_entry); + } + + public function clearMapEntry() + { + unset($this->map_entry); } /** @@ -336,16 +353,10 @@ class MessageOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->map_entry = $var; - $this->has_map_entry = true; return $this; } - public function hasMapEntry() - { - return $this->has_map_entry; - } - /** * The parser stores options it doesn't recognize here. See above. * @@ -368,15 +379,9 @@ class MessageOptions extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class); $this->uninterpreted_option = $arr; - $this->has_uninterpreted_option = true; return $this; } - public function hasUninterpretedOption() - { - return $this->has_uninterpreted_option; - } - } diff --git a/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php b/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php index f40f20f0d7..e2ea8ea6c5 100644 --- a/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php @@ -20,40 +20,34 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message /** * Generated from protobuf field optional string name = 1; */ - protected $name = ''; - private $has_name = false; + protected $name = null; /** * Input and output type names. These are resolved in the same way as * FieldDescriptorProto.type_name, but must refer to a message type. * * Generated from protobuf field optional string input_type = 2; */ - protected $input_type = ''; - private $has_input_type = false; + protected $input_type = null; /** * Generated from protobuf field optional string output_type = 3; */ - protected $output_type = ''; - private $has_output_type = false; + protected $output_type = null; /** * Generated from protobuf field optional .google.protobuf.MethodOptions options = 4; */ protected $options = null; - private $has_options = false; /** * Identifies if client streams multiple client messages * * Generated from protobuf field optional bool client_streaming = 5 [default = false]; */ - protected $client_streaming = false; - private $has_client_streaming = false; + protected $client_streaming = null; /** * Identifies if server streams multiple server messages * * Generated from protobuf field optional bool server_streaming = 6 [default = false]; */ - protected $server_streaming = false; - private $has_server_streaming = false; + protected $server_streaming = null; /** * Constructor. @@ -84,7 +78,17 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message */ public function getName() { - return $this->name; + return isset($this->name) ? $this->name : ''; + } + + public function hasName() + { + return isset($this->name); + } + + public function clearName() + { + unset($this->name); } /** @@ -96,16 +100,10 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->name = $var; - $this->has_name = true; return $this; } - public function hasName() - { - return $this->has_name; - } - /** * Input and output type names. These are resolved in the same way as * FieldDescriptorProto.type_name, but must refer to a message type. @@ -115,7 +113,17 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message */ public function getInputType() { - return $this->input_type; + return isset($this->input_type) ? $this->input_type : ''; + } + + public function hasInputType() + { + return isset($this->input_type); + } + + public function clearInputType() + { + unset($this->input_type); } /** @@ -130,23 +138,27 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->input_type = $var; - $this->has_input_type = true; return $this; } - public function hasInputType() - { - return $this->has_input_type; - } - /** * Generated from protobuf field optional string output_type = 3; * @return string */ public function getOutputType() { - return $this->output_type; + return isset($this->output_type) ? $this->output_type : ''; + } + + public function hasOutputType() + { + return isset($this->output_type); + } + + public function clearOutputType() + { + unset($this->output_type); } /** @@ -158,23 +170,27 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->output_type = $var; - $this->has_output_type = true; return $this; } - public function hasOutputType() - { - return $this->has_output_type; - } - /** * Generated from protobuf field optional .google.protobuf.MethodOptions options = 4; * @return \Google\Protobuf\Internal\MethodOptions */ public function getOptions() { - return $this->options; + return isset($this->options) ? $this->options : null; + } + + public function hasOptions() + { + return isset($this->options); + } + + public function clearOptions() + { + unset($this->options); } /** @@ -186,16 +202,10 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkMessage($var, \Google\Protobuf\Internal\MethodOptions::class); $this->options = $var; - $this->has_options = true; return $this; } - public function hasOptions() - { - return $this->has_options; - } - /** * Identifies if client streams multiple client messages * @@ -204,7 +214,17 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message */ public function getClientStreaming() { - return $this->client_streaming; + return isset($this->client_streaming) ? $this->client_streaming : false; + } + + public function hasClientStreaming() + { + return isset($this->client_streaming); + } + + public function clearClientStreaming() + { + unset($this->client_streaming); } /** @@ -218,16 +238,10 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->client_streaming = $var; - $this->has_client_streaming = true; return $this; } - public function hasClientStreaming() - { - return $this->has_client_streaming; - } - /** * Identifies if server streams multiple server messages * @@ -236,7 +250,17 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message */ public function getServerStreaming() { - return $this->server_streaming; + return isset($this->server_streaming) ? $this->server_streaming : false; + } + + public function hasServerStreaming() + { + return isset($this->server_streaming); + } + + public function clearServerStreaming() + { + unset($this->server_streaming); } /** @@ -250,15 +274,9 @@ class MethodDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->server_streaming = $var; - $this->has_server_streaming = true; return $this; } - public function hasServerStreaming() - { - return $this->has_server_streaming; - } - } diff --git a/php/src/Google/Protobuf/Internal/MethodOptions.php b/php/src/Google/Protobuf/Internal/MethodOptions.php index f96dd3c22c..a4595b7448 100644 --- a/php/src/Google/Protobuf/Internal/MethodOptions.php +++ b/php/src/Google/Protobuf/Internal/MethodOptions.php @@ -23,20 +23,17 @@ class MethodOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool deprecated = 33 [default = false]; */ - protected $deprecated = false; - private $has_deprecated = false; + protected $deprecated = null; /** * Generated from protobuf field optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; */ - protected $idempotency_level = 0; - private $has_idempotency_level = false; + protected $idempotency_level = null; /** * The parser stores options it doesn't recognize here. See above. * * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; */ private $uninterpreted_option; - private $has_uninterpreted_option = false; /** * Constructor. @@ -70,7 +67,17 @@ class MethodOptions extends \Google\Protobuf\Internal\Message */ public function getDeprecated() { - return $this->deprecated; + return isset($this->deprecated) ? $this->deprecated : false; + } + + public function hasDeprecated() + { + return isset($this->deprecated); + } + + public function clearDeprecated() + { + unset($this->deprecated); } /** @@ -87,23 +94,27 @@ class MethodOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->deprecated = $var; - $this->has_deprecated = true; return $this; } - public function hasDeprecated() - { - return $this->has_deprecated; - } - /** * Generated from protobuf field optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; * @return int */ public function getIdempotencyLevel() { - return $this->idempotency_level; + return isset($this->idempotency_level) ? $this->idempotency_level : 0; + } + + public function hasIdempotencyLevel() + { + return isset($this->idempotency_level); + } + + public function clearIdempotencyLevel() + { + unset($this->idempotency_level); } /** @@ -115,16 +126,10 @@ class MethodOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkEnum($var, \Google\Protobuf\Internal\MethodOptions\IdempotencyLevel::class); $this->idempotency_level = $var; - $this->has_idempotency_level = true; return $this; } - public function hasIdempotencyLevel() - { - return $this->has_idempotency_level; - } - /** * The parser stores options it doesn't recognize here. See above. * @@ -147,15 +152,9 @@ class MethodOptions extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class); $this->uninterpreted_option = $arr; - $this->has_uninterpreted_option = true; return $this; } - public function hasUninterpretedOption() - { - return $this->has_uninterpreted_option; - } - } diff --git a/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php b/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php index 413b8e55eb..5ae36ce7d5 100644 --- a/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php @@ -20,13 +20,11 @@ class OneofDescriptorProto extends \Google\Protobuf\Internal\Message /** * Generated from protobuf field optional string name = 1; */ - protected $name = ''; - private $has_name = false; + protected $name = null; /** * Generated from protobuf field optional .google.protobuf.OneofOptions options = 2; */ protected $options = null; - private $has_options = false; /** * Constructor. @@ -49,7 +47,17 @@ class OneofDescriptorProto extends \Google\Protobuf\Internal\Message */ public function getName() { - return $this->name; + return isset($this->name) ? $this->name : ''; + } + + public function hasName() + { + return isset($this->name); + } + + public function clearName() + { + unset($this->name); } /** @@ -61,23 +69,27 @@ class OneofDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->name = $var; - $this->has_name = true; return $this; } - public function hasName() - { - return $this->has_name; - } - /** * Generated from protobuf field optional .google.protobuf.OneofOptions options = 2; * @return \Google\Protobuf\Internal\OneofOptions */ public function getOptions() { - return $this->options; + return isset($this->options) ? $this->options : null; + } + + public function hasOptions() + { + return isset($this->options); + } + + public function clearOptions() + { + unset($this->options); } /** @@ -89,15 +101,9 @@ class OneofDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkMessage($var, \Google\Protobuf\Internal\OneofOptions::class); $this->options = $var; - $this->has_options = true; return $this; } - public function hasOptions() - { - return $this->has_options; - } - } diff --git a/php/src/Google/Protobuf/Internal/OneofOptions.php b/php/src/Google/Protobuf/Internal/OneofOptions.php index 46b516f301..8dde8f3b17 100644 --- a/php/src/Google/Protobuf/Internal/OneofOptions.php +++ b/php/src/Google/Protobuf/Internal/OneofOptions.php @@ -21,7 +21,6 @@ class OneofOptions extends \Google\Protobuf\Internal\Message * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; */ private $uninterpreted_option; - private $has_uninterpreted_option = false; /** * Constructor. @@ -60,15 +59,9 @@ class OneofOptions extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class); $this->uninterpreted_option = $arr; - $this->has_uninterpreted_option = true; return $this; } - public function hasUninterpretedOption() - { - return $this->has_uninterpreted_option; - } - } diff --git a/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php b/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php index aaeefbc9ea..9c2cc8fc90 100644 --- a/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php @@ -20,18 +20,15 @@ class ServiceDescriptorProto extends \Google\Protobuf\Internal\Message /** * Generated from protobuf field optional string name = 1; */ - protected $name = ''; - private $has_name = false; + protected $name = null; /** * Generated from protobuf field repeated .google.protobuf.MethodDescriptorProto method = 2; */ private $method; - private $has_method = false; /** * Generated from protobuf field optional .google.protobuf.ServiceOptions options = 3; */ protected $options = null; - private $has_options = false; /** * Constructor. @@ -55,7 +52,17 @@ class ServiceDescriptorProto extends \Google\Protobuf\Internal\Message */ public function getName() { - return $this->name; + return isset($this->name) ? $this->name : ''; + } + + public function hasName() + { + return isset($this->name); + } + + public function clearName() + { + unset($this->name); } /** @@ -67,16 +74,10 @@ class ServiceDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->name = $var; - $this->has_name = true; return $this; } - public function hasName() - { - return $this->has_name; - } - /** * Generated from protobuf field repeated .google.protobuf.MethodDescriptorProto method = 2; * @return \Google\Protobuf\Internal\RepeatedField @@ -95,23 +96,27 @@ class ServiceDescriptorProto extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\MethodDescriptorProto::class); $this->method = $arr; - $this->has_method = true; return $this; } - public function hasMethod() - { - return $this->has_method; - } - /** * Generated from protobuf field optional .google.protobuf.ServiceOptions options = 3; * @return \Google\Protobuf\Internal\ServiceOptions */ public function getOptions() { - return $this->options; + return isset($this->options) ? $this->options : null; + } + + public function hasOptions() + { + return isset($this->options); + } + + public function clearOptions() + { + unset($this->options); } /** @@ -123,15 +128,9 @@ class ServiceDescriptorProto extends \Google\Protobuf\Internal\Message { GPBUtil::checkMessage($var, \Google\Protobuf\Internal\ServiceOptions::class); $this->options = $var; - $this->has_options = true; return $this; } - public function hasOptions() - { - return $this->has_options; - } - } diff --git a/php/src/Google/Protobuf/Internal/ServiceOptions.php b/php/src/Google/Protobuf/Internal/ServiceOptions.php index 0581efbafc..d15a36ae0a 100644 --- a/php/src/Google/Protobuf/Internal/ServiceOptions.php +++ b/php/src/Google/Protobuf/Internal/ServiceOptions.php @@ -23,15 +23,13 @@ class ServiceOptions extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional bool deprecated = 33 [default = false]; */ - protected $deprecated = false; - private $has_deprecated = false; + protected $deprecated = null; /** * The parser stores options it doesn't recognize here. See above. * * Generated from protobuf field repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; */ private $uninterpreted_option; - private $has_uninterpreted_option = false; /** * Constructor. @@ -64,7 +62,17 @@ class ServiceOptions extends \Google\Protobuf\Internal\Message */ public function getDeprecated() { - return $this->deprecated; + return isset($this->deprecated) ? $this->deprecated : false; + } + + public function hasDeprecated() + { + return isset($this->deprecated); + } + + public function clearDeprecated() + { + unset($this->deprecated); } /** @@ -81,16 +89,10 @@ class ServiceOptions extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->deprecated = $var; - $this->has_deprecated = true; return $this; } - public function hasDeprecated() - { - return $this->has_deprecated; - } - /** * The parser stores options it doesn't recognize here. See above. * @@ -113,15 +115,9 @@ class ServiceOptions extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class); $this->uninterpreted_option = $arr; - $this->has_uninterpreted_option = true; return $this; } - public function hasUninterpretedOption() - { - return $this->has_uninterpreted_option; - } - } diff --git a/php/src/Google/Protobuf/Internal/SourceCodeInfo.php b/php/src/Google/Protobuf/Internal/SourceCodeInfo.php index dfeb69ff69..1c572e75eb 100644 --- a/php/src/Google/Protobuf/Internal/SourceCodeInfo.php +++ b/php/src/Google/Protobuf/Internal/SourceCodeInfo.php @@ -64,7 +64,6 @@ class SourceCodeInfo extends \Google\Protobuf\Internal\Message * Generated from protobuf field repeated .google.protobuf.SourceCodeInfo.Location location = 1; */ private $location; - private $has_location = false; /** * Constructor. @@ -223,15 +222,9 @@ class SourceCodeInfo extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\SourceCodeInfo\Location::class); $this->location = $arr; - $this->has_location = true; return $this; } - public function hasLocation() - { - return $this->has_location; - } - } diff --git a/php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php b/php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php index 0aeea61cae..c4cc667e3a 100644 --- a/php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php +++ b/php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php @@ -41,7 +41,6 @@ class Location extends \Google\Protobuf\Internal\Message * Generated from protobuf field repeated int32 path = 1 [packed = true]; */ private $path; - private $has_path = false; /** * Always has exactly three or four elements: start line, start column, * end line (optional, otherwise assumed same as start line), end column. @@ -52,7 +51,6 @@ class Location extends \Google\Protobuf\Internal\Message * Generated from protobuf field repeated int32 span = 2 [packed = true]; */ private $span; - private $has_span = false; /** * If this SourceCodeInfo represents a complete declaration, these are any * comments appearing before and after the declaration which appear to be @@ -93,18 +91,15 @@ class Location extends \Google\Protobuf\Internal\Message * * Generated from protobuf field optional string leading_comments = 3; */ - protected $leading_comments = ''; - private $has_leading_comments = false; + protected $leading_comments = null; /** * Generated from protobuf field optional string trailing_comments = 4; */ - protected $trailing_comments = ''; - private $has_trailing_comments = false; + protected $trailing_comments = null; /** * Generated from protobuf field repeated string leading_detached_comments = 6; */ private $leading_detached_comments; - private $has_leading_detached_comments = false; /** * Constructor. @@ -248,16 +243,10 @@ class Location extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32); $this->path = $arr; - $this->has_path = true; return $this; } - public function hasPath() - { - return $this->has_path; - } - /** * Always has exactly three or four elements: start line, start column, * end line (optional, otherwise assumed same as start line), end column. @@ -288,16 +277,10 @@ class Location extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32); $this->span = $arr; - $this->has_span = true; return $this; } - public function hasSpan() - { - return $this->has_span; - } - /** * If this SourceCodeInfo represents a complete declaration, these are any * comments appearing before and after the declaration which appear to be @@ -341,7 +324,17 @@ class Location extends \Google\Protobuf\Internal\Message */ public function getLeadingComments() { - return $this->leading_comments; + return isset($this->leading_comments) ? $this->leading_comments : ''; + } + + public function hasLeadingComments() + { + return isset($this->leading_comments); + } + + public function clearLeadingComments() + { + unset($this->leading_comments); } /** @@ -390,23 +383,27 @@ class Location extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->leading_comments = $var; - $this->has_leading_comments = true; return $this; } - public function hasLeadingComments() - { - return $this->has_leading_comments; - } - /** * Generated from protobuf field optional string trailing_comments = 4; * @return string */ public function getTrailingComments() { - return $this->trailing_comments; + return isset($this->trailing_comments) ? $this->trailing_comments : ''; + } + + public function hasTrailingComments() + { + return isset($this->trailing_comments); + } + + public function clearTrailingComments() + { + unset($this->trailing_comments); } /** @@ -418,16 +415,10 @@ class Location extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->trailing_comments = $var; - $this->has_trailing_comments = true; return $this; } - public function hasTrailingComments() - { - return $this->has_trailing_comments; - } - /** * Generated from protobuf field repeated string leading_detached_comments = 6; * @return \Google\Protobuf\Internal\RepeatedField @@ -446,16 +437,10 @@ class Location extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING); $this->leading_detached_comments = $arr; - $this->has_leading_detached_comments = true; return $this; } - public function hasLeadingDetachedComments() - { - return $this->has_leading_detached_comments; - } - } // Adding a class alias for backwards compatibility with the previous class name. diff --git a/php/src/Google/Protobuf/Internal/UninterpretedOption.php b/php/src/Google/Protobuf/Internal/UninterpretedOption.php index 6c871cc1ae..a2aae3e0a7 100644 --- a/php/src/Google/Protobuf/Internal/UninterpretedOption.php +++ b/php/src/Google/Protobuf/Internal/UninterpretedOption.php @@ -26,40 +26,33 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message * Generated from protobuf field repeated .google.protobuf.UninterpretedOption.NamePart name = 2; */ private $name; - private $has_name = false; /** * The value of the uninterpreted option, in whatever type the tokenizer * identified it as during parsing. Exactly one of these should be set. * * Generated from protobuf field optional string identifier_value = 3; */ - protected $identifier_value = ''; - private $has_identifier_value = false; + protected $identifier_value = null; /** * Generated from protobuf field optional uint64 positive_int_value = 4; */ - protected $positive_int_value = 0; - private $has_positive_int_value = false; + protected $positive_int_value = null; /** * Generated from protobuf field optional int64 negative_int_value = 5; */ - protected $negative_int_value = 0; - private $has_negative_int_value = false; + protected $negative_int_value = null; /** * Generated from protobuf field optional double double_value = 6; */ - protected $double_value = 0.0; - private $has_double_value = false; + protected $double_value = null; /** * Generated from protobuf field optional bytes string_value = 7; */ - protected $string_value = ''; - private $has_string_value = false; + protected $string_value = null; /** * Generated from protobuf field optional string aggregate_value = 8; */ - protected $aggregate_value = ''; - private $has_aggregate_value = false; + protected $aggregate_value = null; /** * Constructor. @@ -101,16 +94,10 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message { $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption\NamePart::class); $this->name = $arr; - $this->has_name = true; return $this; } - public function hasName() - { - return $this->has_name; - } - /** * The value of the uninterpreted option, in whatever type the tokenizer * identified it as during parsing. Exactly one of these should be set. @@ -120,7 +107,17 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message */ public function getIdentifierValue() { - return $this->identifier_value; + return isset($this->identifier_value) ? $this->identifier_value : ''; + } + + public function hasIdentifierValue() + { + return isset($this->identifier_value); + } + + public function clearIdentifierValue() + { + unset($this->identifier_value); } /** @@ -135,23 +132,27 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->identifier_value = $var; - $this->has_identifier_value = true; return $this; } - public function hasIdentifierValue() - { - return $this->has_identifier_value; - } - /** * Generated from protobuf field optional uint64 positive_int_value = 4; * @return int|string */ public function getPositiveIntValue() { - return $this->positive_int_value; + return isset($this->positive_int_value) ? $this->positive_int_value : 0; + } + + public function hasPositiveIntValue() + { + return isset($this->positive_int_value); + } + + public function clearPositiveIntValue() + { + unset($this->positive_int_value); } /** @@ -163,23 +164,27 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message { GPBUtil::checkUint64($var); $this->positive_int_value = $var; - $this->has_positive_int_value = true; return $this; } - public function hasPositiveIntValue() - { - return $this->has_positive_int_value; - } - /** * Generated from protobuf field optional int64 negative_int_value = 5; * @return int|string */ public function getNegativeIntValue() { - return $this->negative_int_value; + return isset($this->negative_int_value) ? $this->negative_int_value : 0; + } + + public function hasNegativeIntValue() + { + return isset($this->negative_int_value); + } + + public function clearNegativeIntValue() + { + unset($this->negative_int_value); } /** @@ -191,23 +196,27 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message { GPBUtil::checkInt64($var); $this->negative_int_value = $var; - $this->has_negative_int_value = true; return $this; } - public function hasNegativeIntValue() - { - return $this->has_negative_int_value; - } - /** * Generated from protobuf field optional double double_value = 6; * @return float */ public function getDoubleValue() { - return $this->double_value; + return isset($this->double_value) ? $this->double_value : 0.0; + } + + public function hasDoubleValue() + { + return isset($this->double_value); + } + + public function clearDoubleValue() + { + unset($this->double_value); } /** @@ -219,23 +228,27 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message { GPBUtil::checkDouble($var); $this->double_value = $var; - $this->has_double_value = true; return $this; } - public function hasDoubleValue() - { - return $this->has_double_value; - } - /** * Generated from protobuf field optional bytes string_value = 7; * @return string */ public function getStringValue() { - return $this->string_value; + return isset($this->string_value) ? $this->string_value : ''; + } + + public function hasStringValue() + { + return isset($this->string_value); + } + + public function clearStringValue() + { + unset($this->string_value); } /** @@ -247,23 +260,27 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, False); $this->string_value = $var; - $this->has_string_value = true; return $this; } - public function hasStringValue() - { - return $this->has_string_value; - } - /** * Generated from protobuf field optional string aggregate_value = 8; * @return string */ public function getAggregateValue() { - return $this->aggregate_value; + return isset($this->aggregate_value) ? $this->aggregate_value : ''; + } + + public function hasAggregateValue() + { + return isset($this->aggregate_value); + } + + public function clearAggregateValue() + { + unset($this->aggregate_value); } /** @@ -275,15 +292,9 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->aggregate_value = $var; - $this->has_aggregate_value = true; return $this; } - public function hasAggregateValue() - { - return $this->has_aggregate_value; - } - } diff --git a/php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php b/php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php index 1956ba7f08..6212d1e457 100644 --- a/php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php +++ b/php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php @@ -24,13 +24,11 @@ class NamePart extends \Google\Protobuf\Internal\Message /** * Generated from protobuf field required string name_part = 1; */ - protected $name_part = ''; - private $has_name_part = false; + protected $name_part = null; /** * Generated from protobuf field required bool is_extension = 2; */ - protected $is_extension = false; - private $has_is_extension = false; + protected $is_extension = null; /** * Constructor. @@ -53,7 +51,17 @@ class NamePart extends \Google\Protobuf\Internal\Message */ public function getNamePart() { - return $this->name_part; + return isset($this->name_part) ? $this->name_part : ''; + } + + public function hasNamePart() + { + return isset($this->name_part); + } + + public function clearNamePart() + { + unset($this->name_part); } /** @@ -65,23 +73,27 @@ class NamePart extends \Google\Protobuf\Internal\Message { GPBUtil::checkString($var, True); $this->name_part = $var; - $this->has_name_part = true; return $this; } - public function hasNamePart() - { - return $this->has_name_part; - } - /** * Generated from protobuf field required bool is_extension = 2; * @return bool */ public function getIsExtension() { - return $this->is_extension; + return isset($this->is_extension) ? $this->is_extension : false; + } + + public function hasIsExtension() + { + return isset($this->is_extension); + } + + public function clearIsExtension() + { + unset($this->is_extension); } /** @@ -93,16 +105,10 @@ class NamePart extends \Google\Protobuf\Internal\Message { GPBUtil::checkBool($var); $this->is_extension = $var; - $this->has_is_extension = true; return $this; } - public function hasIsExtension() - { - return $this->has_is_extension; - } - } // Adding a class alias for backwards compatibility with the previous class name. diff --git a/php/src/Google/Protobuf/Mixin.php b/php/src/Google/Protobuf/Mixin.php index a2ea59c757..cf6277eb70 100644 --- a/php/src/Google/Protobuf/Mixin.php +++ b/php/src/Google/Protobuf/Mixin.php @@ -46,7 +46,7 @@ use Google\Protobuf\Internal\GPBUtil; * The mixin construct implies that all methods in `AccessControl` are * also declared with same name and request/response types in * `Storage`. A documentation generator or annotation processor will - * see the effective `Storage.GetAcl` method after inherting + * see the effective `Storage.GetAcl` method after inheriting * documentation and annotations as follows: * service Storage { * // Get the underlying ACL object. diff --git a/php/src/Google/Protobuf/NullValue.php b/php/src/Google/Protobuf/NullValue.php index a72cbb2edb..61569f8a36 100644 --- a/php/src/Google/Protobuf/NullValue.php +++ b/php/src/Google/Protobuf/NullValue.php @@ -35,6 +35,7 @@ class NullValue return self::$valueToName[$value]; } + public static function value($name) { $const = __CLASS__ . '::' . strtoupper($name); diff --git a/php/src/Google/Protobuf/OneofDescriptor.php b/php/src/Google/Protobuf/OneofDescriptor.php index d9736634e3..92b4e279da 100644 --- a/php/src/Google/Protobuf/OneofDescriptor.php +++ b/php/src/Google/Protobuf/OneofDescriptor.php @@ -72,4 +72,9 @@ class OneofDescriptor { return count($this->internal_desc->getFields()); } + + public function isSynthetic() + { + return $this->internal_desc->isSynthetic(); + } } diff --git a/php/src/Google/Protobuf/Value.php b/php/src/Google/Protobuf/Value.php index 5c1e864c3d..20db3cc3e3 100644 --- a/php/src/Google/Protobuf/Value.php +++ b/php/src/Google/Protobuf/Value.php @@ -57,6 +57,11 @@ class Value extends \Google\Protobuf\Internal\Message return $this->readOneof(1); } + public function hasNullValue() + { + return $this->hasOneof(1); + } + /** * Represents a null value. * @@ -83,6 +88,11 @@ class Value extends \Google\Protobuf\Internal\Message return $this->readOneof(2); } + public function hasNumberValue() + { + return $this->hasOneof(2); + } + /** * Represents a double value. * @@ -109,6 +119,11 @@ class Value extends \Google\Protobuf\Internal\Message return $this->readOneof(3); } + public function hasStringValue() + { + return $this->hasOneof(3); + } + /** * Represents a string value. * @@ -135,6 +150,11 @@ class Value extends \Google\Protobuf\Internal\Message return $this->readOneof(4); } + public function hasBoolValue() + { + return $this->hasOneof(4); + } + /** * Represents a boolean value. * @@ -161,6 +181,11 @@ class Value extends \Google\Protobuf\Internal\Message return $this->readOneof(5); } + public function hasStructValue() + { + return $this->hasOneof(5); + } + /** * Represents a structured value. * @@ -187,6 +212,11 @@ class Value extends \Google\Protobuf\Internal\Message return $this->readOneof(6); } + public function hasListValue() + { + return $this->hasOneof(6); + } + /** * Represents a repeated `Value`. * diff --git a/php/tests/array_test.php b/php/tests/ArrayTest.php similarity index 99% rename from php/tests/array_test.php rename to php/tests/ArrayTest.php index b251404083..2cb4b3910d 100644 --- a/php/tests/array_test.php +++ b/php/tests/ArrayTest.php @@ -7,7 +7,7 @@ use Google\Protobuf\Internal\GPBType; use Foo\TestMessage; use Foo\TestMessage\Sub; -class RepeatedFieldTest extends \PHPUnit\Framework\TestCase +class ArrayTest extends \PHPUnit\Framework\TestCase { ######################################################### diff --git a/php/tests/descriptors_test.php b/php/tests/DescriptorsTest.php similarity index 99% rename from php/tests/descriptors_test.php rename to php/tests/DescriptorsTest.php index 60a6292cb6..b2c5e0144d 100644 --- a/php/tests/descriptors_test.php +++ b/php/tests/DescriptorsTest.php @@ -108,7 +108,7 @@ class DescriptorsTest extends TestBase public function testEnumDescriptor() { - // WARNINIG - we need to do this so that TestDescriptorsEnum is registered!!? + // WARNING - we need to do this so that TestDescriptorsEnum is registered!!? new TestDescriptorsMessage(); $pool = DescriptorPool::getGeneratedPool(); diff --git a/php/tests/encode_decode_test.php b/php/tests/EncodeDecodeTest.php similarity index 97% rename from php/tests/encode_decode_test.php rename to php/tests/EncodeDecodeTest.php index 5442f504d5..cea1e6a47f 100644 --- a/php/tests/encode_decode_test.php +++ b/php/tests/EncodeDecodeTest.php @@ -326,6 +326,42 @@ class EncodeDecodeTest extends TestBase } + public function testEncodeDecodeOptional() + { + $m = new TestMessage(); + $this->assertFalse($m->hasTrueOptionalInt32()); + $data = $m->serializeToString(); + $this->assertSame("", $data); + + $m->setTrueOptionalInt32(0); + $this->assertTrue($m->hasTrueOptionalInt32()); + $data = $m->serializeToString(); + $this->assertNotSame("", $data); + + $m2 = new TestMessage(); + $m2->mergeFromString($data); + $this->assertTrue($m2->hasTrueOptionalInt32()); + $this->assertSame(0, $m2->getTrueOptionalInt32()); + } + + public function testJsonEncodeDecodeOptional() + { + $m = new TestMessage(); + $this->assertFalse($m->hasTrueOptionalInt32()); + $data = $m->serializeToJsonString(); + $this->assertSame("{}", $data); + + $m->setTrueOptionalInt32(0); + $this->assertTrue($m->hasTrueOptionalInt32()); + $data = $m->serializeToJsonString(); + $this->assertNotSame("{}", $data); + + $m2 = new TestMessage(); + $m2->mergeFromJsonString($data); + $this->assertTrue($m2->hasTrueOptionalInt32()); + $this->assertSame(0, $m2->getTrueOptionalInt32()); + } + public function testJsonEncodeDecodeOneof() { $m = new TestMessage(); diff --git a/php/tests/generated_class_test.php b/php/tests/GeneratedClassTest.php similarity index 98% rename from php/tests/generated_class_test.php rename to php/tests/GeneratedClassTest.php index 053697d2ec..f49c4e970c 100644 --- a/php/tests/generated_class_test.php +++ b/php/tests/GeneratedClassTest.php @@ -71,6 +71,28 @@ class GeneratedClassTest extends TestBase $this->assertSame(MIN_INT32, $m->getOptionalInt32()); } + ######################################################### + # Test optional int32 field. + ######################################################### + + public function testOptionalInt32Field() + { + $m = new TestMessage(); + + $this->assertFalse($m->hasTrueOptionalInt32()); + $this->assertSame(0, $m->getTrueOptionalInt32()); + + // Set integer. + $m->setTrueOptionalInt32(MAX_INT32); + $this->assertTrue($m->hasTrueOptionalInt32()); + $this->assertSame(MAX_INT32, $m->getTrueOptionalInt32()); + + // Clear integer. + $m->clearTrueOptionalInt32(); + $this->assertFalse($m->hasTrueOptionalInt32()); + $this->assertSame(0, $m->getTrueOptionalInt32()); + } + ######################################################### # Test uint32 field. ######################################################### diff --git a/php/tests/generated_phpdoc_test.php b/php/tests/GeneratedPhpdocTest.php similarity index 100% rename from php/tests/generated_phpdoc_test.php rename to php/tests/GeneratedPhpdocTest.php diff --git a/php/tests/generated_service_test.php b/php/tests/GeneratedServiceTest.php similarity index 100% rename from php/tests/generated_service_test.php rename to php/tests/GeneratedServiceTest.php diff --git a/php/tests/map_field_test.php b/php/tests/MapFieldTest.php similarity index 100% rename from php/tests/map_field_test.php rename to php/tests/MapFieldTest.php diff --git a/php/tests/php_implementation_test.php b/php/tests/PhpImplementationTest.php similarity index 99% rename from php/tests/php_implementation_test.php rename to php/tests/PhpImplementationTest.php index db3c361caf..f9fc1fd5ea 100644 --- a/php/tests/php_implementation_test.php +++ b/php/tests/PhpImplementationTest.php @@ -515,7 +515,7 @@ class ImplementationTest extends TestBase { $m = new TestMessage(); TestUtil::setTestMessage($m); - $this->assertSame(518, $m->byteSize()); + $this->assertSame(504, $m->byteSize()); } public function testPackedByteSize() diff --git a/php/tests/well_known_test.php b/php/tests/WellKnownTest.php similarity index 100% rename from php/tests/well_known_test.php rename to php/tests/WellKnownTest.php diff --git a/php/tests/wrapper_type_setters_test.php b/php/tests/WrapperTypeSettersTest.php similarity index 100% rename from php/tests/wrapper_type_setters_test.php rename to php/tests/WrapperTypeSettersTest.php diff --git a/php/tests/compatibility_test.sh b/php/tests/compatibility_test.sh index ddf05e85c7..7e44cce06b 100755 --- a/php/tests/compatibility_test.sh +++ b/php/tests/compatibility_test.sh @@ -100,11 +100,18 @@ cd protobuf/php composer install # Remove implementation detail tests. -tests=( array_test.php encode_decode_test.php generated_class_test.php map_field_test.php well_known_test.php ) +# TODO(teboring): Temporarily disable encode_decode_test.php. In 3.13.0-rc1, +# repeated primitive field encoding is changed to packed, which is a bug fix. +# However, this fails the compatibility test which hard coded old encoding. +# Will re-enable the test after making a release. After the version bump, the +# compatibility test will use the updated test code. +tests=( array_test.php generated_class_test.php map_field_test.php well_known_test.php ) sed -i.bak '/php_implementation_test.php/d' phpunit.xml sed -i.bak '/generated_phpdoc_test.php/d' phpunit.xml +sed -i.bak '/encode_decode_test.php/d' phpunit.xml sed -i.bak 's/generated_phpdoc_test.php//g' tests/test.sh sed -i.bak 's/generated_service_test.php//g' tests/test.sh +sed -i.bak 's/encode_decode_test.php//g' tests/test.sh sed -i.bak '/memory_leak_test.php/d' tests/test.sh sed -i.bak '/^ public function testTimestamp()$/,/^ }$/d' tests/well_known_test.php sed -i.bak 's/PHPUnit_Framework_TestCase/\\PHPUnit\\Framework\\TestCase/g' tests/array_test.php diff --git a/php/tests/compile_extension.sh b/php/tests/compile_extension.sh index 5834249e39..d6dcabcbbb 100755 --- a/php/tests/compile_extension.sh +++ b/php/tests/compile_extension.sh @@ -4,17 +4,17 @@ set -ex cd $(dirname $0) +pushd ../ext/google/protobuf +phpize --clean +rm -f configure.in configure.ac +php make-preload.php +phpize if [ "$1" = "--release" ]; then - CFLAGS="-Wall" + ./configure --with-php-config=$(which php-config) else # To get debugging symbols in PHP itself, build PHP with: # $ ./configure --enable-debug CFLAGS='-g -O0' - CFLAGS="-g -O0 -Wall" + ./configure --with-php-config=$(which php-config) CFLAGS="-g -O0 -Wall" fi - -pushd ../ext/google/protobuf -phpize --clean -rm -f configure.in configure.ac -php make-preload.php -phpize && ./configure --with-php-config=$(which php-config) CFLAGS="$CFLAGS" && make +make popd diff --git a/php/tests/generate_protos.sh b/php/tests/generate_protos.sh index 0c2a5550aa..e83c3c1c06 100755 --- a/php/tests/generate_protos.sh +++ b/php/tests/generate_protos.sh @@ -7,10 +7,10 @@ cd `dirname $0` rm -rf generated mkdir -p generated -find proto -type f -name "*.proto"| xargs ../../src/protoc --php_out=generated -I../../src -I. +find proto -type f -name "*.proto"| xargs ../../src/protoc --experimental_allow_proto3_optional --php_out=generated -I../../src -I. if [ "$1" = "--aggregate_metadata" ]; then # Overwrite some of the files to use aggregation. AGGREGATED_FILES="proto/test.proto proto/test_include.proto proto/test_import_descriptor_proto.proto" - ../../src/protoc --php_out=aggregate_metadata=foo#bar:generated -I../../src -I. $AGGREGATED_FILES + ../../src/protoc --experimental_allow_proto3_optional --php_out=aggregate_metadata=foo#bar:generated -I../../src -I. $AGGREGATED_FILES fi diff --git a/php/tests/proto/test.proto b/php/tests/proto/test.proto index 95057090f9..368b19ec4d 100644 --- a/php/tests/proto/test.proto +++ b/php/tests/proto/test.proto @@ -34,6 +34,27 @@ message TestMessage { bar.TestInclude optional_included_message = 18; TestMessage recursive = 19; + // True optional + optional int32 true_optional_int32 = 201; + optional int64 true_optional_int64 = 202; + optional uint32 true_optional_uint32 = 203; + optional uint64 true_optional_uint64 = 204; + optional sint32 true_optional_sint32 = 205; + optional sint64 true_optional_sint64 = 206; + optional fixed32 true_optional_fixed32 = 207; + optional fixed64 true_optional_fixed64 = 208; + optional sfixed32 true_optional_sfixed32 = 209; + optional sfixed64 true_optional_sfixed64 = 210; + optional float true_optional_float = 211; + optional double true_optional_double = 212; + optional bool true_optional_bool = 213; + optional string true_optional_string = 214; + optional bytes true_optional_bytes = 215; + + optional TestEnum true_optional_enum = 216; + optional Sub true_optional_message = 217; + optional bar.TestInclude true_optional_included_message = 218; + // Repeated repeated int32 repeated_int32 = 31; repeated int64 repeated_int64 = 32; diff --git a/php/tests/test.sh b/php/tests/test.sh index b10b57fd19..91ea56ec8f 100755 --- a/php/tests/test.sh +++ b/php/tests/test.sh @@ -18,6 +18,9 @@ case "$PHP_VERSION" in 7.3.*|7.4.*) PHPUNIT=phpunit-8.phar ;; + 8.0.*) + PHPUNIT=phpunit-9.phar + ;; *) echo "ERROR: Unsupported PHP version $PHP_VERSION" exit 1 @@ -26,7 +29,7 @@ esac [ -f $PHPUNIT ] || wget https://phar.phpunit.de/$PHPUNIT -tests=( array_test.php encode_decode_test.php generated_class_test.php map_field_test.php well_known_test.php descriptors_test.php wrapper_type_setters_test.php) +tests=( ArrayTest.php EncodeDecodeTest.php GeneratedClassTest.php MapFieldTest.php WellKnownTest.php DescriptorsTest.php WrapperTypeSettersTest.php) for t in "${tests[@]}" do @@ -51,11 +54,11 @@ done export ZEND_DONT_UNLOAD_MODULES=1 export USE_ZEND_ALLOC=0 -valgrind --leak-check=yes php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php -valgrind --leak-check=yes php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php +valgrind --suppressions=valgrind.supp --leak-check=yes php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php +valgrind --suppressions=valgrind.supp --leak-check=yes php -d protobuf.keep_descriptor_pool_after_request=1 -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php # TODO(teboring): Only for debug (phpunit has memory leak which blocks this beging used by -# regresssion test.) +# regression test.) # for t in "${tests[@]}" # do diff --git a/php/tests/test_util.php b/php/tests/test_util.php index 2c5b59541c..c47bf586a9 100644 --- a/php/tests/test_util.php +++ b/php/tests/test_util.php @@ -338,38 +338,24 @@ class TestUtil "800101" . "8A01020821" . - "F801D6FFFFFFFFFFFFFFFF01" . - "F801CCFFFFFFFFFFFFFFFF01" . - "8002D5FFFFFFFFFFFFFFFF01" . - "8002CBFFFFFFFFFFFFFFFF01" . - "88022A" . - "880234" . - "90022B" . - "900235" . - "980257" . - "98026B" . - "A00259" . - "A0026D" . - "AD022E000000" . - "AD0238000000" . - "B1022F00000000000000" . - "B1023900000000000000" . - "BD02D2FFFFFF" . - "BD02C8FFFFFF" . - "C102D1FFFFFFFFFFFFFF" . - "C102C7FFFFFFFFFFFFFF" . - "CD020000C03F" . - "CD0200002040" . - "D1029A9999999999F93F" . - "D102CDCCCCCCCCCC0440" . - "D80201" . - "D80200" . + "FA0114D6FFFFFFFFFFFFFFFF01CCFFFFFFFFFFFFFFFF01" . + "820214D5FFFFFFFFFFFFFFFF01CBFFFFFFFFFFFFFFFF01" . + "8A02022A34" . + "9202022B35" . + "9A0202576B" . + "A20202596D" . + "AA02082E00000038000000" . + "B202102F000000000000003900000000000000" . + "BA0208D2FFFFFFC8FFFFFF" . + "C20210D1FFFFFFFFFFFFFFC7FFFFFFFFFFFFFF" . + "CA02080000C03F00002040" . + "D202109A9999999999F93FCDCCCCCCCCCC0440" . + "DA02020100" . "E2020161" . "E2020163" . "EA020462626262" . "EA020464646464" . - "F00200" . - "F00201" . + "F202020001" . "FA02020822" . "FA02020823" . diff --git a/php/tests/valgrind.supp b/php/tests/valgrind.supp new file mode 100644 index 0000000000..e83b0a3dfa --- /dev/null +++ b/php/tests/valgrind.supp @@ -0,0 +1,12 @@ +{ + PHP_Equal_Val + Memcheck:Cond + fun:zend_string_equal_val +} + +{ + PHP_ScanDir_Tail + Memcheck:Cond + obj:/usr/bin/php7.3 + fun:__scandir64_tail +} diff --git a/protoc-artifacts/pom.xml b/protoc-artifacts/pom.xml index 6d750c5b67..27315e83f4 100644 --- a/protoc-artifacts/pom.xml +++ b/protoc-artifacts/pom.xml @@ -8,7 +8,7 @@ com.google.protobuf protoc - 3.12.3 + 3.13.0 pom Protobuf Compiler diff --git a/python/README.md b/python/README.md index a987c2dac8..cb8b7e9892 100644 --- a/python/README.md +++ b/python/README.md @@ -22,7 +22,7 @@ package. Development Warning =================== -The pure python performance is slow. For better preformance please +The pure python performance is slow. For better performance please use python c++ implementation. Installation diff --git a/python/google/protobuf/internal/enum_type_wrapper.py b/python/google/protobuf/internal/enum_type_wrapper.py index c8e10137b9..9ae0066584 100644 --- a/python/google/protobuf/internal/enum_type_wrapper.py +++ b/python/google/protobuf/internal/enum_type_wrapper.py @@ -108,7 +108,9 @@ class EnumTypeWrapper(object): def __getattr__(self, name): """Returns the value corresponding to the given enum name.""" try: - return self._enum_type.values_by_name[name].number + return super( + EnumTypeWrapper, + self).__getattribute__('_enum_type').values_by_name[name].number except KeyError: pass # fall out to break exception chaining raise AttributeError('Enum {} has no value defined for name {!r}'.format( diff --git a/python/release.sh b/python/release.sh index c915e124d8..6db87f0bb2 100755 --- a/python/release.sh +++ b/python/release.sh @@ -11,7 +11,10 @@ function run_install_test() { local PYTHON=$2 local PYPI=$3 - virtualenv --no-site-packages -p `which $PYTHON` test-venv + # Setuptools 45.0 removed support for Python 2, so to test with Python 2 we + # pass --no-setuptools here and then install an older setuptools version + # below. + virtualenv -p `which $PYTHON` --no-setuptools test-venv # Intentionally put a broken protoc in the path to make sure installation # doesn't require protoc installed. @@ -19,6 +22,7 @@ function run_install_test() { chmod +x test-venv/bin/protoc source test-venv/bin/activate + pip install "setuptools<45" pip install -i ${PYPI} protobuf==${VERSION} --no-cache-dir deactivate rm -fr test-venv diff --git a/ruby/ext/google/protobuf_c/upb.h b/ruby/ext/google/protobuf_c/upb.h index bdc20ebeef..b7da76fa00 100644 --- a/ruby/ext/google/protobuf_c/upb.h +++ b/ruby/ext/google/protobuf_c/upb.h @@ -200,7 +200,7 @@ int msvc_vsnprintf(char* s, size_t n, const char* format, va_list arg); ** store pointers or integers of at least 32 bits (upb isn't really useful on ** systems where sizeof(void*) < 4). ** -** The table must be homogenous (all values of the same type). In debug +** The table must be homogeneous (all values of the same type). In debug ** mode, we check this on insert and lookup. */ @@ -6057,7 +6057,7 @@ typedef struct { 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 optimze so that the JIT uses + * 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; diff --git a/ruby/google-protobuf.gemspec b/ruby/google-protobuf.gemspec index 2160d520ab..21528fe4c3 100644 --- a/ruby/google-protobuf.gemspec +++ b/ruby/google-protobuf.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |s| s.name = "google-protobuf" - s.version = "3.12.3" + s.version = "3.13.0" git_tag = "v#{s.version.to_s.sub('.rc.', '-rc')}" # Converts X.Y.Z.rc.N to vX.Y.Z-rcN, used for the git tag s.licenses = ["BSD-3-Clause"] s.summary = "Protocol Buffers" diff --git a/src/Makefile.am b/src/Makefile.am index 714fe71170..ca460aa73f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -208,6 +208,7 @@ libprotobuf_lite_la_SOURCES = \ google/protobuf/generated_message_table_driven_lite.h \ google/protobuf/generated_message_table_driven_lite.cc \ google/protobuf/implicit_weak_message.cc \ + google/protobuf/map.cc \ google/protobuf/message_lite.cc \ google/protobuf/parse_context.cc \ google/protobuf/repeated_field.cc \ diff --git a/src/google/protobuf/any.cc b/src/google/protobuf/any.cc index a9876fc4ed..ebe9ba7e0a 100644 --- a/src/google/protobuf/any.cc +++ b/src/google/protobuf/any.cc @@ -47,18 +47,20 @@ void AnyMetadata::PackFrom(const Message& message) { void AnyMetadata::PackFrom(const Message& message, StringPiece type_url_prefix) { - type_url_->SetNoArena( + type_url_->Set( &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString(), - GetTypeUrl(message.GetDescriptor()->full_name(), type_url_prefix)); - message.SerializeToString(value_->MutableNoArena( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())); + GetTypeUrl(message.GetDescriptor()->full_name(), type_url_prefix), + nullptr); + message.SerializeToString(value_->Mutable( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + nullptr)); } bool AnyMetadata::UnpackTo(Message* message) const { if (!InternalIs(message->GetDescriptor()->full_name())) { return false; } - return message->ParseFromString(value_->GetNoArena()); + return message->ParseFromString(value_->Get()); } bool GetAnyFieldDescriptors(const Message& message, diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc index 7eed87c5eb..3170748106 100644 --- a/src/google/protobuf/any.pb.cc +++ b/src/google/protobuf/any.pb.cc @@ -28,7 +28,6 @@ static void InitDefaultsscc_info_Any_google_2fprotobuf_2fany_2eproto() { new (ptr) PROTOBUF_NAMESPACE_ID::Any(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::Any::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Any_google_2fprotobuf_2fany_2eproto = @@ -82,8 +81,6 @@ PROTOBUF_NAMESPACE_OPEN // =================================================================== -void Any::InitAsDefaultInstance() { -} bool Any::GetAnyFieldDescriptors( const ::PROTOBUF_NAMESPACE_ID::Message& message, const ::PROTOBUF_NAMESPACE_ID::FieldDescriptor** type_url_field, diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h index 90cd342080..1c50d6eb72 100644 --- a/src/google/protobuf/any.pb.h +++ b/src/google/protobuf/any.pb.h @@ -102,7 +102,6 @@ class PROTOBUF_EXPORT Any PROTOBUF_FINAL : } static const Any& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const Any* internal_default_instance() { return reinterpret_cast( &_Any_default_instance_); diff --git a/src/google/protobuf/any_lite.cc b/src/google/protobuf/any_lite.cc index 3badb411f1..206b01fbd1 100644 --- a/src/google/protobuf/any_lite.cc +++ b/src/google/protobuf/any_lite.cc @@ -59,10 +59,10 @@ AnyMetadata::AnyMetadata(UrlType* type_url, ValueType* value) void AnyMetadata::InternalPackFrom(const MessageLite& message, StringPiece type_url_prefix, StringPiece type_name) { - type_url_->SetNoArena(&::google::protobuf::internal::GetEmptyString(), - GetTypeUrl(type_name, type_url_prefix)); - message.SerializeToString(value_->MutableNoArena( - &::google::protobuf::internal::GetEmptyStringAlreadyInited())); + type_url_->Set(&::google::protobuf::internal::GetEmptyString(), + GetTypeUrl(type_name, type_url_prefix), nullptr); + message.SerializeToString(value_->Mutable( + &::google::protobuf::internal::GetEmptyStringAlreadyInited(), nullptr)); } bool AnyMetadata::InternalUnpackTo(StringPiece type_name, @@ -70,31 +70,11 @@ bool AnyMetadata::InternalUnpackTo(StringPiece type_name, if (!InternalIs(type_name)) { return false; } - return message->ParseFromString(value_->GetNoArena()); + return message->ParseFromString(value_->Get()); } -namespace { - -// The type URL could be stored in either an ArenaStringPtr or a -// StringPieceField, so we provide these helpers to get a string_view from -// either type. We use a template function as a way to avoid depending on -// StringPieceField. - -template -StringPiece Get(const T* ptr) { - return ptr->Get(); -} - -template <> -// NOLINTNEXTLINE: clang-diagnostic-unused-function -StringPiece Get(const ArenaStringPtr* ptr) { - return ptr->GetNoArena(); -} - -} // namespace - bool AnyMetadata::InternalIs(StringPiece type_name) const { - StringPiece type_url = Get(type_url_); + StringPiece type_url = type_url_->Get(); return type_url.size() >= type_name.size() + 1 && type_url[type_url.size() - type_name.size() - 1] == '/' && HasSuffixString(type_url, type_name); diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc index 6ae678a120..f8e20a11d9 100644 --- a/src/google/protobuf/api.pb.cc +++ b/src/google/protobuf/api.pb.cc @@ -40,7 +40,6 @@ static void InitDefaultsscc_info_Api_google_2fprotobuf_2fapi_2eproto() { new (ptr) PROTOBUF_NAMESPACE_ID::Api(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::Api::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<4> scc_info_Api_google_2fprotobuf_2fapi_2eproto = @@ -58,7 +57,6 @@ static void InitDefaultsscc_info_Method_google_2fprotobuf_2fapi_2eproto() { new (ptr) PROTOBUF_NAMESPACE_ID::Method(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::Method::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Method_google_2fprotobuf_2fapi_2eproto = @@ -73,7 +71,6 @@ static void InitDefaultsscc_info_Mixin_google_2fprotobuf_2fapi_2eproto() { new (ptr) PROTOBUF_NAMESPACE_ID::Mixin(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::Mixin::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Mixin_google_2fprotobuf_2fapi_2eproto = @@ -172,10 +169,6 @@ PROTOBUF_NAMESPACE_OPEN // =================================================================== -void Api::InitAsDefaultInstance() { - PROTOBUF_NAMESPACE_ID::_Api_default_instance_._instance.get_mutable()->source_context_ = const_cast< PROTOBUF_NAMESPACE_ID::SourceContext*>( - PROTOBUF_NAMESPACE_ID::SourceContext::internal_default_instance()); -} class Api::_Internal { public: static const PROTOBUF_NAMESPACE_ID::SourceContext& source_context(const Api* msg); @@ -601,8 +594,6 @@ void Api::InternalSwap(Api* other) { // =================================================================== -void Method::InitAsDefaultInstance() { -} class Method::_Internal { public: }; @@ -1002,8 +993,6 @@ void Method::InternalSwap(Method* other) { // =================================================================== -void Mixin::InitAsDefaultInstance() { -} class Mixin::_Internal { public: }; diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h index a3c61a4e3b..64f90ee0e6 100644 --- a/src/google/protobuf/api.pb.h +++ b/src/google/protobuf/api.pb.h @@ -112,7 +112,6 @@ class PROTOBUF_EXPORT Api PROTOBUF_FINAL : } static const Api& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const Api* internal_default_instance() { return reinterpret_cast( &_Api_default_instance_); @@ -365,7 +364,6 @@ class PROTOBUF_EXPORT Method PROTOBUF_FINAL : } static const Method& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const Method* internal_default_instance() { return reinterpret_cast( &_Method_default_instance_); @@ -598,7 +596,6 @@ class PROTOBUF_EXPORT Mixin PROTOBUF_FINAL : } static const Mixin& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const Mixin* internal_default_instance() { return reinterpret_cast( &_Mixin_default_instance_); @@ -941,8 +938,8 @@ inline bool Api::has_source_context() const { } inline const PROTOBUF_NAMESPACE_ID::SourceContext& Api::_internal_source_context() const { const PROTOBUF_NAMESPACE_ID::SourceContext* p = source_context_; - return p != nullptr ? *p : *reinterpret_cast( - &PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_); + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_); } inline const PROTOBUF_NAMESPACE_ID::SourceContext& Api::source_context() const { // @@protoc_insertion_point(field_get:google.protobuf.Api.source_context) diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc index 7362b62950..13e11b51aa 100644 --- a/src/google/protobuf/arena.cc +++ b/src/google/protobuf/arena.cc @@ -166,27 +166,19 @@ void ArenaImpl::AddCleanup(void* elem, void (*cleanup)(void*)) { PROTOBUF_NOINLINE void* ArenaImpl::AllocateAlignedFallback(size_t n) { - return GetSerialArena()->AllocateAligned(n); + return GetSerialArenaFallback(&thread_cache())->AllocateAligned(n); } PROTOBUF_NOINLINE void* ArenaImpl::AllocateAlignedAndAddCleanupFallback(size_t n, void (*cleanup)(void*)) { - return GetSerialArena()->AllocateAlignedAndAddCleanup(n, cleanup); + return GetSerialArenaFallback( + &thread_cache())->AllocateAlignedAndAddCleanup(n, cleanup); } PROTOBUF_NOINLINE void ArenaImpl::AddCleanupFallback(void* elem, void (*cleanup)(void*)) { - GetSerialArena()->AddCleanup(elem, cleanup); -} - -ArenaImpl::SerialArena* ArenaImpl::GetSerialArena() { - SerialArena* arena; - if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) { - return arena; - } else { - return GetSerialArenaFallback(&thread_cache()); - } + GetSerialArenaFallback(&thread_cache())->AddCleanup(elem, cleanup); } PROTOBUF_NOINLINE diff --git a/src/google/protobuf/arena_impl.h b/src/google/protobuf/arena_impl.h index c9b4c54fcb..2f8d343fd3 100644 --- a/src/google/protobuf/arena_impl.h +++ b/src/google/protobuf/arena_impl.h @@ -329,7 +329,6 @@ class PROTOBUF_EXPORT ArenaImpl { Block* NewBlock(Block* last_block, size_t min_bytes); - SerialArena* GetSerialArena(); PROTOBUF_ALWAYS_INLINE bool GetSerialArenaFast(SerialArena** arena) { if (GetSerialArenaFromThreadCache(arena)) return true; diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc index 85784201c2..8919027a89 100644 --- a/src/google/protobuf/arena_unittest.cc +++ b/src/google/protobuf/arena_unittest.cc @@ -1166,7 +1166,6 @@ TEST(ArenaTest, MessageLiteOnArena) { } #endif // PROTOBUF_RTTI - // RepeatedField should support non-POD types, and invoke constructors and // destructors appropriately, because it's used this way by lots of other code // (even if this was not its original intent). diff --git a/src/google/protobuf/arenastring.h b/src/google/protobuf/arenastring.h index 122f391e51..b87be8e39b 100644 --- a/src/google/protobuf/arenastring.h +++ b/src/google/protobuf/arenastring.h @@ -229,7 +229,6 @@ struct PROTOBUF_EXPORT ArenaStringPtr { // Clears content, assuming that the current value is not the empty string // default. inline void ClearNonDefaultToEmpty() { ptr_->clear(); } - inline void ClearNonDefaultToEmptyNoArena() { ptr_->clear(); } // Clears content, but keeps allocated string if arena != NULL, to avoid the // overhead of heap operations. After this returns, the content (as seen by @@ -257,93 +256,13 @@ struct PROTOBUF_EXPORT ArenaStringPtr { ptr_ = const_cast< ::std::string*>(default_value); } - // The 'NoArena' variants of methods below assume arena == NULL and are - // optimized to provide very little overhead relative to a raw string pointer - // (while still being in-memory compatible with other code that assumes - // ArenaStringPtr). Note the invariant that a class instance that has only - // ever been mutated by NoArena methods must *only* be in the String state - // (i.e., tag bits are not used), *NEVER* ArenaString. This allows all - // tagged-pointer manipulations to be avoided. - inline void SetNoArena(const ::std::string* default_value, - const ::std::string& value) { - if (ptr_ == default_value) { - CreateInstanceNoArena(&value); - } else { - *ptr_ = value; - } - } - - void SetNoArena(const ::std::string* default_value, ::std::string&& value) { - if (IsDefault(default_value)) { - ptr_ = new ::std::string(std::move(value)); - } else { - *ptr_ = std::move(value); - } - } - - void AssignWithDefault(const ::std::string* default_value, - ArenaStringPtr value); - - inline const ::std::string& GetNoArena() const { return *ptr_; } - - inline ::std::string* MutableNoArena(const ::std::string* default_value) { - if (ptr_ == default_value) { - CreateInstanceNoArena(default_value); - } - return ptr_; - } - - inline ::std::string* ReleaseNoArena(const ::std::string* default_value) { - if (ptr_ == default_value) { - return NULL; - } else { - return ReleaseNonDefaultNoArena(default_value); - } - } - - inline ::std::string* ReleaseNonDefaultNoArena( - const ::std::string* default_value) { - GOOGLE_DCHECK(!IsDefault(default_value)); - ::std::string* released = ptr_; - ptr_ = const_cast< ::std::string*>(default_value); - return released; - } - - inline void SetAllocatedNoArena(const ::std::string* default_value, - ::std::string* value) { - if (ptr_ != default_value) { - delete ptr_; - } - if (value != NULL) { - ptr_ = value; - } else { - ptr_ = const_cast< ::std::string*>(default_value); - } - } - + // Destroy the string. Assumes `arena == nullptr`. inline void DestroyNoArena(const ::std::string* default_value) { if (ptr_ != default_value) { delete ptr_; } } - inline void ClearToEmptyNoArena(const ::std::string* default_value) { - if (ptr_ == default_value) { - // Nothing: already equal to default (which is the empty string). - } else { - ptr_->clear(); - } - } - - inline void ClearToDefaultNoArena(const ::std::string* default_value) { - if (ptr_ == default_value) { - // Nothing: already set to default. - } else { - // Reuse existing allocated instance. - *ptr_ = *default_value; - } - } - // Internal accessor used only at parse time to provide direct access to the // raw pointer from the shared parse routine (in the non-arenas case). The // parse routine does the string allocation in order to save code size in the @@ -379,22 +298,6 @@ struct PROTOBUF_EXPORT ArenaStringPtr { } }; -} // namespace internal -} // namespace protobuf - -namespace protobuf { -namespace internal { - -inline void ArenaStringPtr::AssignWithDefault( - const ::std::string* default_value, ArenaStringPtr value) { - const ::std::string* me = *UnsafeRawStringPointer(); - const ::std::string* other = *value.UnsafeRawStringPointer(); - // If the pointers are the same then do nothing. - if (me != other) { - SetNoArena(default_value, value.GetNoArena()); - } -} - } // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc index 693300df08..4d78bb1176 100644 --- a/src/google/protobuf/compiler/code_generator.cc +++ b/src/google/protobuf/compiler/code_generator.cc @@ -85,6 +85,12 @@ io::ZeroCopyOutputStream* GeneratorContext::OpenForInsert( return NULL; // make compiler happy } +io::ZeroCopyOutputStream* GeneratorContext::OpenForInsertWithGeneratedCodeInfo( + const std::string& filename, const std::string& insertion_point, + const google::protobuf::GeneratedCodeInfo& /*info*/) { + return OpenForInsert(filename, insertion_point); +} + void GeneratorContext::ListParsedFiles( std::vector* output) { GOOGLE_LOG(FATAL) << "This GeneratorContext does not support ListParsedFiles"; diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h index 21131d5a25..323f48e4a9 100644 --- a/src/google/protobuf/compiler/code_generator.h +++ b/src/google/protobuf/compiler/code_generator.h @@ -52,6 +52,7 @@ namespace io { class ZeroCopyOutputStream; } class FileDescriptor; +class GeneratedCodeInfo; namespace compiler { class AccessInfoMap; @@ -156,6 +157,15 @@ class PROTOC_EXPORT GeneratorContext { virtual io::ZeroCopyOutputStream* OpenForInsert( const std::string& filename, const std::string& insertion_point); + // Similar to OpenForInsert, but if `info` is non-empty, will open (or create) + // filename.pb.meta and insert info at the appropriate place with the + // necessary shifts. The default implementation ignores `info`. + // + // WARNING: This feature will be REMOVED in the near future. + virtual io::ZeroCopyOutputStream* OpenForInsertWithGeneratedCodeInfo( + const std::string& filename, const std::string& insertion_point, + const google::protobuf::GeneratedCodeInfo& info); + // Returns a vector of FileDescriptors for all the files being compiled // in this run. Useful for languages, such as Go, that treat files // differently when compiled as a set rather than individually. diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 1ada897af1..859eb8b831 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -386,6 +386,9 @@ class CommandLineInterface::GeneratorContextImpl : public GeneratorContext { io::ZeroCopyOutputStream* OpenForAppend(const std::string& filename); io::ZeroCopyOutputStream* OpenForInsert(const std::string& filename, const std::string& insertion_point); + io::ZeroCopyOutputStream* OpenForInsertWithGeneratedCodeInfo( + const std::string& filename, const std::string& insertion_point, + const google::protobuf::GeneratedCodeInfo& info); void ListParsedFiles(std::vector* output) { *output = parsed_files_; } @@ -393,7 +396,8 @@ class CommandLineInterface::GeneratorContextImpl : public GeneratorContext { private: friend class MemoryOutputStream; - // map instead of unordered_map so that files are written in order (good when + // The files_ field maps from path keys to file content values. It's a map + // instead of an unordered_map so that files are written in order (good when // writing zips). std::map files_; const std::vector& parsed_files_; @@ -408,6 +412,10 @@ class CommandLineInterface::MemoryOutputStream MemoryOutputStream(GeneratorContextImpl* directory, const std::string& filename, const std::string& insertion_point); + MemoryOutputStream(GeneratorContextImpl* directory, + const std::string& filename, + const std::string& insertion_point, + const google::protobuf::GeneratedCodeInfo& info); virtual ~MemoryOutputStream(); // implements ZeroCopyOutputStream --------------------------------- @@ -418,12 +426,23 @@ class CommandLineInterface::MemoryOutputStream int64_t ByteCount() const override { return inner_->ByteCount(); } private: - // Checks to see if "filename_.meta" exists in directory_; if so, fixes the + // Checks to see if "filename_.pb.meta" exists in directory_; if so, fixes the // offsets in that GeneratedCodeInfo record to reflect bytes inserted in // filename_ at original offset insertion_offset with length insertion_length. - // We assume that insertions will not occur within any given annotated span - // of text. - void UpdateMetadata(size_t insertion_offset, size_t insertion_length); + // Also adds in the data from info_to_insert_ with updated offsets governed by + // insertion_offset and indent_length. We assume that insertions will not + // occur within any given annotated span of text. insertion_content must end + // with an endline. + void UpdateMetadata(const std::string& insertion_content, + size_t insertion_offset, size_t insertion_length, + size_t indent_length); + + // Inserts info_to_insert_ into target_info, assuming that the relevant + // insertion was made at insertion_offset in file_content with the given + // indent_length. insertion_content must end with an endline. + void InsertShiftedInfo(const std::string& insertion_content, + size_t insertion_offset, size_t indent_length, + google::protobuf::GeneratedCodeInfo& target_info); // Where to insert the string when it's done. GeneratorContextImpl* directory_; @@ -438,6 +457,9 @@ class CommandLineInterface::MemoryOutputStream // StringOutputStream writing to data_. std::unique_ptr inner_; + + // The GeneratedCodeInfo to insert at the insertion point. + google::protobuf::GeneratedCodeInfo info_to_insert_; }; // ------------------------------------------------------------------- @@ -594,6 +616,13 @@ CommandLineInterface::GeneratorContextImpl::OpenForInsert( return new MemoryOutputStream(this, filename, insertion_point); } +io::ZeroCopyOutputStream* +CommandLineInterface::GeneratorContextImpl::OpenForInsertWithGeneratedCodeInfo( + const std::string& filename, const std::string& insertion_point, + const google::protobuf::GeneratedCodeInfo& info) { + return new MemoryOutputStream(this, filename, insertion_point, info); +} + // ------------------------------------------------------------------- CommandLineInterface::MemoryOutputStream::MemoryOutputStream( @@ -612,40 +641,114 @@ CommandLineInterface::MemoryOutputStream::MemoryOutputStream( insertion_point_(insertion_point), inner_(new io::StringOutputStream(&data_)) {} +CommandLineInterface::MemoryOutputStream::MemoryOutputStream( + GeneratorContextImpl* directory, const std::string& filename, + const std::string& insertion_point, const google::protobuf::GeneratedCodeInfo& info) + : directory_(directory), + filename_(filename), + insertion_point_(insertion_point), + inner_(new io::StringOutputStream(&data_)), + info_to_insert_(info) {} + +void CommandLineInterface::MemoryOutputStream::InsertShiftedInfo( + const std::string& insertion_content, size_t insertion_offset, + size_t indent_length, google::protobuf::GeneratedCodeInfo& target_info) { + // Keep track of how much extra data was added for indents before the + // current annotation being inserted. `pos` and `source_annotation.begin()` + // are offsets in `insertion_content`. `insertion_offset` is updated so that + // it can be added to an annotation's `begin` field to reflect that + // annotation's updated location after `insertion_content` was inserted into + // the target file. + size_t pos = 0; + insertion_offset += indent_length; + for (const auto& source_annotation : info_to_insert_.annotation()) { + GeneratedCodeInfo::Annotation* annotation = target_info.add_annotation(); + int inner_indent = 0; + // insertion_content is guaranteed to end in an endline. This last endline + // has no effect on indentation. + for (; pos < source_annotation.end() && pos < insertion_content.size() - 1; + ++pos) { + if (insertion_content[pos] == '\n') { + if (pos >= source_annotation.begin()) { + // The beginning of the annotation is at insertion_offset, but the end + // can still move further in the target file. + inner_indent += indent_length; + } else { + insertion_offset += indent_length; + } + } + } + *annotation = source_annotation; + annotation->set_begin(annotation->begin() + insertion_offset); + insertion_offset += inner_indent; + annotation->set_end(annotation->end() + insertion_offset); + } +} + void CommandLineInterface::MemoryOutputStream::UpdateMetadata( - size_t insertion_offset, size_t insertion_length) { - auto it = directory_->files_.find(filename_ + ".meta"); - if (it == directory_->files_.end()) { + const std::string& insertion_content, size_t insertion_offset, + size_t insertion_length, size_t indent_length) { + auto it = directory_->files_.find(filename_ + ".pb.meta"); + if (it == directory_->files_.end() && info_to_insert_.annotation().empty()) { // No metadata was recorded for this file. return; } - std::string& encoded_data = it->second; GeneratedCodeInfo metadata; bool is_text_format = false; - if (!metadata.ParseFromString(encoded_data)) { - if (!TextFormat::ParseFromString(encoded_data, &metadata)) { - // The metadata is invalid. - std::cerr << filename_ - << ".meta: Could not parse metadata as wire or text format." - << std::endl; - return; - } - // Generators that use the public plugin interface emit text-format - // metadata (because in the public plugin protocol, file content must be - // UTF8-encoded strings). - is_text_format = true; - } - for (int i = 0; i < metadata.annotation_size(); ++i) { - GeneratedCodeInfo::Annotation* annotation = metadata.mutable_annotation(i); - if (annotation->begin() >= insertion_offset) { - annotation->set_begin(annotation->begin() + insertion_length); - annotation->set_end(annotation->end() + insertion_length); + std::string* encoded_data = nullptr; + if (it != directory_->files_.end()) { + encoded_data = &it->second; + // Try to decode a GeneratedCodeInfo proto from the .pb.meta file. It may be + // in wire or text format. Keep the same format when the data is written out + // later. + if (!metadata.ParseFromString(*encoded_data)) { + if (!TextFormat::ParseFromString(*encoded_data, &metadata)) { + // The metadata is invalid. + std::cerr + << filename_ + << ".pb.meta: Could not parse metadata as wire or text format." + << std::endl; + return; + } + // Generators that use the public plugin interface emit text-format + // metadata (because in the public plugin protocol, file content must be + // UTF8-encoded strings). + is_text_format = true; } + } else { + // Create a new file to store the new metadata in info_to_insert_. + encoded_data = + &directory_->files_.insert({filename_ + ".pb.meta", ""}).first->second; + } + GeneratedCodeInfo new_metadata; + bool crossed_offset = false; + size_t to_add = 0; + for (const auto& source_annotation : metadata.annotation()) { + // The first time an annotation at or after the insertion point is found, + // insert the new metadata from info_to_insert_. Shift all annotations + // after the new metadata by the length of the text that was inserted + // (including any additional indent length). + if (source_annotation.begin() >= insertion_offset && !crossed_offset) { + crossed_offset = true; + InsertShiftedInfo(insertion_content, insertion_offset, indent_length, + new_metadata); + to_add += insertion_length; + } + GeneratedCodeInfo::Annotation* annotation = new_metadata.add_annotation(); + *annotation = source_annotation; + annotation->set_begin(annotation->begin() + to_add); + annotation->set_end(annotation->end() + to_add); + } + // If there were never any annotations at or after the insertion point, + // make sure to still insert the new metadata from info_to_insert_. + if (!crossed_offset) { + InsertShiftedInfo(insertion_content, insertion_offset, indent_length, + new_metadata); } if (is_text_format) { - TextFormat::PrintToString(metadata, &encoded_data); + TextFormat::PrintToString(new_metadata, encoded_data); } else { - metadata.SerializeToString(&encoded_data); + new_metadata.SerializeToString(encoded_data); } } @@ -728,7 +831,7 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { if (indent_.empty()) { // No indent. This makes things easier. target->insert(pos, data_); - UpdateMetadata(pos, data_.size()); + UpdateMetadata(data_, pos, data_.size(), 0); } else { // Calculate how much space we need. int indent_size = 0; @@ -738,7 +841,6 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { // Make a hole for it. target->insert(pos, data_.size() + indent_size, '\0'); - UpdateMetadata(pos, data_.size() + indent_size); // Now copy in the data. std::string::size_type data_pos = 0; @@ -757,6 +859,7 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { target_ptr += line_length; data_pos += line_length; } + UpdateMetadata(data_, pos, data_.size() + indent_size, indent_.size()); GOOGLE_CHECK_EQ(target_ptr, ::google::protobuf::string_as_array(target) + pos + data_.size() + indent_size); @@ -1427,13 +1530,33 @@ CommandLineInterface::ParseArgumentStatus CommandLineInterface::ParseArguments( proto_path_.push_back(std::pair("", ".")); } - // Check some error cases. - bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty(); - if (decoding_raw && !input_files_.empty()) { - std::cerr << "When using --decode_raw, no input files should be given." + // Check error cases that span multiple flag values. + bool missing_proto_definitions; + switch (mode_) { + case MODE_COMPILE: + missing_proto_definitions = input_files_.empty(); + break; + case MODE_DECODE: + // Handle --decode_raw separately, since it requires that no proto + // definitions are specified. + if (codec_type_.empty()) { + if (!input_files_.empty() || !descriptor_set_in_names_.empty()) { + std::cerr + << "When using --decode_raw, no input files should be given." << std::endl; - return PARSE_ARGUMENT_FAIL; - } else if (!decoding_raw && input_files_.empty()) { + return PARSE_ARGUMENT_FAIL; + } + missing_proto_definitions = false; + break; // only for --decode_raw + } + // --decode (not raw) is handled the same way as the rest of the modes. + PROTOBUF_FALLTHROUGH_INTENDED; + case MODE_ENCODE: + case MODE_PRINT: + missing_proto_definitions = + input_files_.empty() && descriptor_set_in_names_.empty(); + } + if (missing_proto_definitions) { std::cerr << "Missing input file." << std::endl; return PARSE_ARGUMENT_FAIL; } @@ -2224,8 +2347,10 @@ bool CommandLineInterface::GeneratePluginOutput( // We reset current_output to NULL first so that the old file is closed // before the new one is opened. current_output.reset(); - current_output.reset(generator_context->OpenForInsert( - filename, output_file.insertion_point())); + current_output.reset( + generator_context->OpenForInsertWithGeneratedCodeInfo( + filename, output_file.insertion_point(), + output_file.generated_code_info())); } else if (!output_file.name().empty()) { // Starting a new file. Open it. // We reset current_output to NULL first so that the old file is closed diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index e42ca26e76..5d91042845 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -1192,8 +1192,8 @@ TEST_F(CommandLineInterfaceTest, InsertWithAnnotationFixup) { Run("protocol_compiler " "--test_out=TestParameter:$tmpdir " "--plug_out=TestPluginParameter:$tmpdir " - "--test_out=insert=test_generator,test_plugin:$tmpdir " - "--plug_out=insert=test_generator,test_plugin:$tmpdir " + "--test_out=insert_endlines=test_generator,test_plugin:$tmpdir " + "--plug_out=insert_endlines=test_generator,test_plugin:$tmpdir " "--proto_path=$tmpdir foo.proto"); ExpectNoErrors(); @@ -2564,20 +2564,22 @@ class EncodeDecodeTest : public testing::TestWithParam { enum Type { TEXT, BINARY }; enum ReturnCode { SUCCESS, ERROR }; - bool Run(const std::string& command) { + bool Run(const std::string& command, bool specify_proto_files = true) { std::vector args; args.push_back("protoc"); SplitStringUsing(command, " ", &args); - switch (GetParam()) { - case PROTO_PATH: - args.push_back("--proto_path=" + TestUtil::TestSourceDir()); - break; - case DESCRIPTOR_SET_IN: - args.push_back(StrCat("--descriptor_set_in=", - unittest_proto_descriptor_set_filename_)); - break; - default: - ADD_FAILURE() << "unexpected EncodeDecodeTestMode: " << GetParam(); + if (specify_proto_files) { + switch (GetParam()) { + case PROTO_PATH: + args.push_back("--proto_path=" + TestUtil::TestSourceDir()); + break; + case DESCRIPTOR_SET_IN: + args.push_back(StrCat("--descriptor_set_in=", + unittest_proto_descriptor_set_filename_)); + break; + default: + ADD_FAILURE() << "unexpected EncodeDecodeTestMode: " << GetParam(); + } } std::unique_ptr argv(new const char*[args.size()]); @@ -2659,9 +2661,12 @@ TEST_P(EncodeDecodeTest, Encode) { RedirectStdinFromFile(TestUtil::GetTestDataPath( "net/proto2/internal/" "testdata/text_format_unittest_data_oneof_implemented.txt")); - EXPECT_TRUE( - Run(TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto") + - " --encode=protobuf_unittest.TestAllTypes")); + std::string args; + if (GetParam() != DESCRIPTOR_SET_IN) { + args.append( + TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto")); + } + EXPECT_TRUE(Run(args + " --encode=protobuf_unittest.TestAllTypes")); ExpectStdoutMatchesBinaryFile(TestUtil::GetTestDataPath( "net/proto2/internal/testdata/golden_message_oneof_implemented")); ExpectStderrMatchesText(""); @@ -2697,7 +2702,7 @@ TEST_P(EncodeDecodeTest, DecodeRaw) { message.SerializeToString(&data); RedirectStdinFromText(data); - EXPECT_TRUE(Run("--decode_raw")); + EXPECT_TRUE(Run("--decode_raw", /*specify_proto_files=*/false)); ExpectStdoutMatchesText( "1: 123\n" "14: \"foo\"\n"); diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index 7d69eb566b..c27b464f95 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -441,12 +441,11 @@ void FileGenerator::GenerateSourceDefaultInstance(int idx, " ::$proto_ns$::internal::ExplicitlyConstructed<$2$> _instance;\n", DefaultInstanceType(generator->descriptor_, options_), generator->classname_); - format.Indent(); - generator->GenerateExtraDefaultFields(printer); - format.Outdent(); format("} $1$;\n", DefaultInstanceName(generator->descriptor_, options_)); + if (options_.lite_implicit_weak_fields) { - format("$1$DefaultTypeInternal* $2$ = &$3$;\n", generator->classname_, + format("$1$* $2$ = &$3$;\n", + DefaultInstanceType(generator->descriptor_, options_), DefaultInstancePtr(generator->descriptor_, options_), DefaultInstanceName(generator->descriptor_, options_)); } @@ -942,8 +941,6 @@ void FileGenerator::GenerateInitForSCC(const SCC* scc, if (scc_analyzer_.GetSCC(message_generators_[i]->descriptor_) != scc) { continue; } - // TODO(gerbens) This requires this function to be friend. Remove - // the need for this. message_generators_[i]->GenerateFieldDefaultInstances(printer); format( "{\n" @@ -961,17 +958,6 @@ void FileGenerator::GenerateInitForSCC(const SCC* scc, } format("}\n"); } - - // TODO(gerbens) make default instances be the same as normal instances. - // Default instances differ from normal instances because they have cross - // linked message fields. - for (int i = 0; i < message_generators_.size(); i++) { - if (scc_analyzer_.GetSCC(message_generators_[i]->descriptor_) != scc) { - continue; - } - format("$1$::InitAsDefaultInstance();\n", - QualifiedClassName(message_generators_[i]->descriptor_, options_)); - } format.Outdent(); format("}\n\n"); diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc index 976823afa8..2a338ae59f 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc @@ -1388,7 +1388,7 @@ class ParseLoopGenerator { std::vector ordered_fields; for (auto field : FieldRange(descriptor)) { - if (IsFieldUsed(field, options_)) { + if (!IsFieldStripped(field, options_)) { ordered_fields.push_back(field); } } @@ -1615,9 +1615,13 @@ class ParseLoopGenerator { } } else if (IsWeak(field, options_)) { format_( - "ptr = ctx->ParseMessage(_weak_field_map_.MutableMessage($1$," - " _$classname$_default_instance_.$2$_), ptr);\n", - field->number(), FieldName(field)); + "{\n" + " auto* default_ = &reinterpret_cast($1$);\n" + " ptr = ctx->ParseMessage(_weak_field_map_.MutableMessage($2$," + " default_), ptr);\n" + "}\n", + QualifiedDefaultInstanceName(field->message_type(), options_), + field->number()); } else { format_("ptr = ctx->ParseMessage(_internal_$1$_$2$(), ptr);\n", field->is_repeated() ? "add" : "mutable", FieldName(field)); diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h index 988e6092c1..4ee19b8b15 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.h +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h @@ -347,12 +347,16 @@ inline bool IsLazy(const FieldDescriptor* field, const Options& options) { !options.opensource_runtime; } -// Returns true if "field" is used. -inline bool IsFieldUsed(const FieldDescriptor* /*field*/, - const Options& /*options*/) { +inline bool IsFieldUsed(const FieldDescriptor* field, const Options& options) { return true; } +// Returns true if "field" is stripped. +inline bool IsFieldStripped(const FieldDescriptor* /*field*/, + const Options& /*options*/) { + return false; +} + // Does the file contain any definitions that need extension_set.h? bool HasExtensionsOrExtendableMessage(const FileDescriptor* file); @@ -450,27 +454,11 @@ inline bool HasPreservingUnknownEnumSemantics(const FieldDescriptor* field) { return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3; } -inline bool SupportsArenas(const FileDescriptor* file) { - return file->options().cc_enable_arenas(); -} - -inline bool SupportsArenas(const Descriptor* desc) { - return SupportsArenas(desc->file()); -} - -inline bool SupportsArenas(const FieldDescriptor* field) { - return SupportsArenas(field->file()); -} - inline bool IsCrossFileMessage(const FieldDescriptor* field) { return field->type() == FieldDescriptor::TYPE_MESSAGE && field->message_type()->file() != field->file(); } -inline std::string MessageCreateFunction(const Descriptor* d) { - return SupportsArenas(d) ? "CreateMessage" : "Create"; -} - inline std::string MakeDefaultName(const FieldDescriptor* field) { return "_i_give_permission_to_break_this_code_default_" + FieldName(field) + "_"; diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index 7c7461fa6f..19bf4252e5 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -316,6 +316,17 @@ bool ShouldMarkNewAsFinal(const Descriptor* descriptor, options.opensource_runtime; } +// 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 +// --the message is in the allowlist (true) +// --GOOGLE_PROTOBUF_SHUFFLE_SERIALIZE is defined (false) +// --a ranage of message names that are allowed to stay in order (true) +bool ShouldSerializeInOrder(const Descriptor* descriptor, + const Options& options) { + return true; +} + bool TableDrivenParsingEnabled(const Descriptor* descriptor, const Options& options) { if (!options.table_driven_parsing) { @@ -584,7 +595,7 @@ MessageGenerator::MessageGenerator( // Compute optimized field order to be used for layout and initialization // purposes. for (auto field : FieldRange(descriptor_)) { - if (!IsFieldUsed(field, options_)) { + if (IsFieldStripped(field, options_)) { continue; } @@ -673,7 +684,7 @@ void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) { optimized_order_.end()); for (auto field : FieldRange(descriptor_)) { if (!field->real_containing_oneof() && !field->options().weak() && - IsFieldUsed(field, options_)) { + !IsFieldStripped(field, options_)) { continue; } ordered_fields.push_back(field); @@ -702,8 +713,8 @@ void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) { if (field->is_repeated()) { format("$deprecated_attr$int ${1$$name$_size$}$() const$2$\n", field, - IsFieldUsed(field, options_) ? ";" : " {__builtin_trap();}"); - if (IsFieldUsed(field, options_)) { + !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}"); + if (!IsFieldStripped(field, options_)) { format( "private:\n" "int ${1$_internal_$name$_size$}$() const;\n" @@ -712,15 +723,15 @@ void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) { } } else if (HasHasMethod(field)) { format("$deprecated_attr$bool ${1$has_$name$$}$() const$2$\n", field, - IsFieldUsed(field, options_) ? ";" : " {__builtin_trap();}"); - if (IsFieldUsed(field, options_)) { + !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}"); + if (!IsFieldStripped(field, options_)) { format( "private:\n" "bool _internal_has_$name$() const;\n" "public:\n"); } } else if (HasPrivateHasMethod(field)) { - if (IsFieldUsed(field, options_)) { + if (!IsFieldStripped(field, options_)) { format( "private:\n" "bool ${1$_internal_has_$name$$}$() const;\n" @@ -729,7 +740,7 @@ void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) { } } format("$deprecated_attr$void ${1$clear_$name$$}$()$2$\n", field, - IsFieldUsed(field, options_) ? ";" : "{__builtin_trap();}"); + !IsFieldStripped(field, options_) ? ";" : "{__builtin_trap();}"); // Generate type-specific accessor declarations. field_generators_.get(field).GenerateAccessorDeclarations(printer); @@ -764,7 +775,7 @@ void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) { void MessageGenerator::GenerateSingularFieldHasBits( const FieldDescriptor* field, Formatter format) { - if (!IsFieldUsed(field, options_)) { + if (IsFieldStripped(field, options_)) { format( "inline bool $classname$::has_$name$() const { " "__builtin_trap(); }\n"); @@ -845,7 +856,7 @@ void MessageGenerator::GenerateOneofHasBits(io::Printer* printer) { void MessageGenerator::GenerateOneofMemberHasBits(const FieldDescriptor* field, const Formatter& format) { - if (!IsFieldUsed(field, options_)) { + if (IsFieldStripped(field, options_)) { if (HasHasMethod(field)) { format( "inline bool $classname$::has_$name$() const { " @@ -890,7 +901,7 @@ void MessageGenerator::GenerateOneofMemberHasBits(const FieldDescriptor* field, void MessageGenerator::GenerateFieldClear(const FieldDescriptor* field, bool is_inline, Formatter format) { - if (!IsFieldUsed(field, options_)) { + if (IsFieldStripped(field, options_)) { format("void $classname$::clear_$name$() { __builtin_trap(); }\n"); return; } @@ -936,7 +947,7 @@ void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* printer) { for (auto field : FieldRange(descriptor_)) { PrintFieldComment(format, field); - if (!IsFieldUsed(field, options_)) { + if (IsFieldStripped(field, options_)) { continue; } @@ -948,7 +959,7 @@ void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* printer) { // Generate has_$name$() or $name$_size(). if (field->is_repeated()) { - if (!IsFieldUsed(field, options_)) { + if (IsFieldStripped(field, options_)) { format( "inline int $classname$::$name$_size() const { " "__builtin_trap(); }\n"); @@ -982,7 +993,7 @@ void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* printer) { } // Generate type-specific accessors. - if (IsFieldUsed(field, options_)) { + if (!IsFieldStripped(field, options_)) { field_generators_.get(field).GenerateInlineAccessorDefinitions(printer); } @@ -1105,13 +1116,8 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { format(" public:\n"); format.Indent(); - if (SupportsArenas(descriptor_)) { - format("inline $classname$() : $classname$(nullptr) {}\n"); - } else { - format("$classname$();\n"); - } - format( + "inline $classname$() : $classname$(nullptr) {}\n" "virtual ~$classname$();\n" "\n" "$classname$(const $classname$& from);\n" @@ -1207,7 +1213,6 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { // TODO(gerbens) make this private, while still granting other protos access. format( - "static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY\n" "static inline const $classname$* internal_default_instance() {\n" " return reinterpret_cast(\n" " &_$classname$_default_instance_);\n" @@ -1290,31 +1295,21 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { format( "friend void swap($classname$& a, $classname$& b) {\n" " a.Swap(&b);\n" + "}\n" + "inline void Swap($classname$* other) {\n" + " if (other == this) return;\n" + " if (GetArena() == other->GetArena()) {\n" + " InternalSwap(other);\n" + " } else {\n" + " ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);\n" + " }\n" + "}\n" + "void UnsafeArenaSwap($classname$* other) {\n" + " if (other == this) return;\n" + " $DCHK$(GetArena() == other->GetArena());\n" + " InternalSwap(other);\n" "}\n"); - if (SupportsArenas(descriptor_)) { - format( - "inline void Swap($classname$* other) {\n" - " if (other == this) return;\n" - " if (GetArena() == other->GetArena()) {\n" - " InternalSwap(other);\n" - " } else {\n" - " ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);\n" - " }\n" - "}\n" - "void UnsafeArenaSwap($classname$* other) {\n" - " if (other == this) return;\n" - " $DCHK$(GetArena() == other->GetArena());\n" - " InternalSwap(other);\n" - "}\n"); - } else { - format( - "inline void Swap($classname$* other) {\n" - " if (other == this) return;\n" - " InternalSwap(other);\n" - "}\n"); - } - format( "\n" "// implements Message ----------------------------------------------\n" @@ -1387,17 +1382,15 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { options_.opensource_runtime ? "::PROTOBUF_NAMESPACE_ID::StringPiece" : "::StringPiece"); - if (SupportsArenas(descriptor_)) { - format( - // TODO(gerbens) Make this private! Currently people are deriving from - // protos to give access to this constructor, breaking the invariants - // we rely on. - "protected:\n" - "explicit $classname$(::$proto_ns$::Arena* arena);\n" - "private:\n" - "static void ArenaDtor(void* object);\n" - "inline void RegisterArenaDtor(::$proto_ns$::Arena* arena);\n"); - } + format( + // TODO(gerbens) Make this private! Currently people are deriving from + // protos to give access to this constructor, breaking the invariants + // we rely on. + "protected:\n" + "explicit $classname$(::$proto_ns$::Arena* arena);\n" + "private:\n" + "static void ArenaDtor(void* object);\n" + "inline void RegisterArenaDtor(::$proto_ns$::Arena* arena);\n"); format( "public:\n" @@ -1520,13 +1513,11 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { "\n"); } - if (SupportsArenas(descriptor_)) { - format( - "template friend class " - "::$proto_ns$::Arena::InternalHelper;\n" - "typedef void InternalArenaConstructable_;\n" - "typedef void DestructorSkippable_;\n"); - } + format( + "template friend class " + "::$proto_ns$::Arena::InternalHelper;\n" + "typedef void InternalArenaConstructable_;\n" + "typedef void DestructorSkippable_;\n"); if (!has_bit_indices_.empty()) { // _has_bits_ is frequently accessed, so to reduce code size and improve @@ -1558,14 +1549,14 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { camel_oneof_name); format.Indent(); for (auto field : FieldRange(oneof)) { - if (IsFieldUsed(field, options_)) { + if (!IsFieldStripped(field, options_)) { field_generators_.get(field).GeneratePrivateMembers(printer); } } format.Outdent(); format("} $1$_;\n", oneof->name()); for (auto field : FieldRange(oneof)) { - if (IsFieldUsed(field, options_)) { + if (!IsFieldStripped(field, options_)) { field_generators_.get(field).GenerateStaticMembers(printer); } } @@ -1623,30 +1614,6 @@ void MessageGenerator::GenerateInlineMethods(io::Printer* printer) { } } -void MessageGenerator::GenerateExtraDefaultFields(io::Printer* printer) { - // Generate oneof default instance and weak field instances for reflection - // usage. - Formatter format(printer, variables_); - for (auto oneof : OneOfRange(descriptor_)) { - for (auto field : FieldRange(oneof)) { - if (!IsFieldUsed(field, options_)) { - continue; - } - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || - (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && - EffectiveStringCType(field, options_) != FieldOptions::STRING)) { - format("const "); - } - field_generators_.get(field).GeneratePrivateMembers(printer); - } - } - for (auto field : FieldRange(descriptor_)) { - if (field->options().weak() && IsFieldUsed(field, options_)) { - format(" const ::$proto_ns$::Message* $1$_;\n", FieldName(field)); - } - } -} - bool MessageGenerator::GenerateParseTable(io::Printer* printer, size_t offset, size_t aux_offset) { Formatter format(printer, variables_); @@ -1938,66 +1905,6 @@ void MessageGenerator::GenerateFieldDefaultInstances(io::Printer* printer) { } } -void MessageGenerator::GenerateDefaultInstanceInitializer( - io::Printer* printer) { - Formatter format(printer, variables_); - - // The default instance needs all of its embedded message pointers - // cross-linked to other default instances. We can't do this initialization - // in the constructor because some other default instances may not have been - // constructed yet at that time. - // TODO(kenton): Maybe all message fields (even for non-default messages) - // should be initialized to point at default instances rather than NULL? - for (auto field : FieldRange(descriptor_)) { - if (!IsFieldUsed(field, options_)) { - continue; - } - Formatter::SaveState saver(&format); - - if (!field->is_repeated() && !IsLazy(field, options_) && - field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && - (!field->real_containing_oneof() || - HasDescriptorMethods(descriptor_->file(), options_))) { - std::string name; - if (field->real_containing_oneof() || field->options().weak()) { - name = "_" + classname_ + "_default_instance_."; - } else { - name = - "_" + classname_ + "_default_instance_._instance.get_mutable()->"; - } - name += FieldName(field); - format.Set("name", name); - if (IsWeak(field, options_)) { - format( - "$package_ns$::$name$_ = reinterpret_cast(&$1$);\n" - "if ($package_ns$::$name$_ == nullptr) {\n" - " $package_ns$::$name$_ = " - "::$proto_ns$::Empty::internal_default_instance();\n" - "}\n", - QualifiedDefaultInstanceName(field->message_type(), - options_)); // 1 - continue; - } - if (IsImplicitWeakField(field, options_, scc_analyzer_)) { - format( - "$package_ns$::$name$_ = reinterpret_cast<$1$*>(\n" - " $2$);\n", - FieldMessageTypeName(field, options_), - QualifiedDefaultInstancePtr(field->message_type(), options_)); - } else { - format( - "$package_ns$::$name$_ = const_cast< $1$*>(\n" - " $1$::internal_default_instance());\n", - FieldMessageTypeName(field, options_)); - } - } else if (field->real_containing_oneof() && - HasDescriptorMethods(descriptor_->file(), options_)) { - field_generators_.get(field).GenerateConstructorCode(printer); - } - } -} - void MessageGenerator::GenerateClassMethods(io::Printer* printer) { Formatter format(printer, variables_); if (IsMapEntryMessage(descriptor_)) { @@ -2023,14 +1930,6 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) { return; } - // TODO(gerbens) Remove this function. With a little bit of cleanup and - // refactoring this is superfluous. - format("void $classname$::InitAsDefaultInstance() {\n"); - format.Indent(); - GenerateDefaultInstanceInitializer(printer); - format.Outdent(); - format("}\n"); - if (IsAnyMessage(descriptor_, options_)) { if (HasDescriptorMethods(descriptor_->file(), options_)) { format( @@ -2062,7 +1961,7 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) { } for (auto field : FieldRange(descriptor_)) { field_generators_.get(field).GenerateInternalAccessorDeclarations(printer); - if (!IsFieldUsed(field, options_)) { + if (IsFieldStripped(field, options_)) { continue; } if (HasHasbit(field)) { @@ -2088,14 +1987,14 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) { format.Outdent(); format("};\n\n"); for (auto field : FieldRange(descriptor_)) { - if (IsFieldUsed(field, options_)) { + if (!IsFieldStripped(field, options_)) { field_generators_.get(field).GenerateInternalAccessorDefinitions(printer); } } // Generate non-inline field definitions. for (auto field : FieldRange(descriptor_)) { - if (!IsFieldUsed(field, options_)) { + if (IsFieldStripped(field, options_)) { continue; } field_generators_.get(field).GenerateNonInlineAccessorDefinitions(printer); @@ -2400,13 +2299,16 @@ std::pair MessageGenerator::GenerateOffsets( descriptor_->real_oneof_decl_count(); size_t entries = offsets; for (auto field : FieldRange(descriptor_)) { - if (!IsFieldUsed(field, options_)) { + if (IsFieldStripped(field, options_)) { format("~0u, // stripped\n"); continue; } - if (field->real_containing_oneof() || field->options().weak()) { - format("offsetof($classtype$DefaultTypeInternal, $1$_)", - FieldName(field)); + // TODO(sbenza): We should not have an entry in the offset table for fields + // that do not use them. + if (field->options().weak() || field->real_containing_oneof()) { + // Mark the field to prevent unintentional access through reflection. + // Don't use the top bit because that is for unused fields. + format("::$proto_ns$::internal::kInvalidFieldOffsetTag"); } else { format("PROTOBUF_FIELD_OFFSET($classtype$, $1$_)", FieldName(field)); } @@ -2416,7 +2318,11 @@ std::pair MessageGenerator::GenerateOffsets( format(" | $1$", tag); } - format(",\n"); + if (!IsFieldUsed(field, options_)) { + format(" | 0x80000000u, // unused\n"); + } else { + format(",\n"); + } } int count = 0; @@ -2470,9 +2376,7 @@ void MessageGenerator::GenerateSharedDestructorCode(io::Printer* printer) { format("void $classname$::SharedDtor() {\n"); format.Indent(); - if (SupportsArenas(descriptor_)) { - format("$DCHK$(GetArena() == nullptr);\n"); - } + format("$DCHK$(GetArena() == nullptr);\n"); // Write the destructors for each field except oneof members. // optimized_order_ does not contain oneof fields. for (auto field : optimized_order_) { @@ -2528,7 +2432,7 @@ void MessageGenerator::GenerateArenaDestructorCode(io::Printer* printer) { // and returns false for oneof fields. for (auto oneof : OneOfRange(descriptor_)) { for (auto field : FieldRange(oneof)) { - if (IsFieldUsed(field, options_) && + if (!IsFieldStripped(field, options_) && field_generators_.get(field).GenerateArenaDestructorCode(printer)) { need_registration = true; } @@ -2631,7 +2535,7 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) { // Initialize member variables with arena constructor. for (auto field : optimized_order_) { - GOOGLE_DCHECK(IsFieldUsed(field, options_)); + GOOGLE_DCHECK(!IsFieldStripped(field, options_)); bool has_arena_constructor = field->is_repeated(); if (!field->real_containing_oneof() && (IsLazy(field, options_) || IsStringPiece(field, options_))) { @@ -2658,24 +2562,14 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) { initializer_null += ", _weak_field_map_(nullptr)"; } - if (SupportsArenas(descriptor_)) { - format( - "$classname$::$classname$(::$proto_ns$::Arena* arena)\n" - " : $1$ {\n" - " SharedCtor();\n" - " RegisterArenaDtor(arena);\n" - " // @@protoc_insertion_point(arena_constructor:$full_name$)\n" - "}\n", - initializer_with_arena); - } else { - format( - "$classname$::$classname$()\n" - " : $1$ {\n" - " SharedCtor();\n" - " // @@protoc_insertion_point(constructor:$full_name$)\n" - "}\n", - initializer_null); - } + format( + "$classname$::$classname$(::$proto_ns$::Arena* arena)\n" + " : $1$ {\n" + " SharedCtor();\n" + " RegisterArenaDtor(arena);\n" + " // @@protoc_insertion_point(arena_constructor:$full_name$)\n" + "}\n", + initializer_with_arena); std::map vars; SetUnknkownFieldsVariable(descriptor_, options_, &vars); @@ -2747,7 +2641,7 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) { for (auto field : FieldRange(oneof)) { format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); format.Indent(); - if (IsFieldUsed(field, options_)) { + if (!IsFieldStripped(field, options_)) { field_generators_.get(field).GenerateMergingCode(printer); } format("break;\n"); @@ -2786,9 +2680,7 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) { GenerateSharedDestructorCode(printer); // Generate the arena-specific destructor code. - if (SupportsArenas(descriptor_)) { - GenerateArenaDestructorCode(printer); - } + GenerateArenaDestructorCode(printer); // Generate SetCachedSize. format( @@ -2811,9 +2703,8 @@ void MessageGenerator::GenerateSourceInProto2Namespace(io::Printer* printer) { "template<> " "PROTOBUF_NOINLINE " "$classtype$* Arena::CreateMaybeMessage< $classtype$ >(Arena* arena) {\n" - " return Arena::$1$Internal< $classtype$ >(arena);\n" - "}\n", - MessageCreateFunction(descriptor_)); + " return Arena::CreateMessageInternal< $classtype$ >(arena);\n" + "}\n"); } void MessageGenerator::GenerateClear(io::Printer* printer) { @@ -3005,7 +2896,7 @@ void MessageGenerator::GenerateOneofClear(io::Printer* printer) { format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); format.Indent(); // We clear only allocated objects in oneofs - if (!IsStringOrMessage(field) || !IsFieldUsed(field, options_)) { + if (!IsStringOrMessage(field) || IsFieldStripped(field, options_)) { format("// No need to clear\n"); } else { field_generators_.get(field).GenerateClearingCode(printer); @@ -3294,7 +3185,7 @@ void MessageGenerator::GenerateClassSpecificMergeFrom(io::Printer* printer) { for (auto field : FieldRange(oneof)) { format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); format.Indent(); - if (IsFieldUsed(field, options_)) { + if (!IsFieldStripped(field, options_)) { field_generators_.get(field).GenerateMergingCode(printer); } format("break;\n"); @@ -3514,8 +3405,26 @@ void MessageGenerator::GenerateSerializeWithCachedSizesToArray( format("// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n"); + if (!ShouldSerializeInOrder(descriptor_, options_)) { + format.Outdent(); + format("#ifdef NDEBUG\n"); + format.Indent(); + } + GenerateSerializeWithCachedSizesBody(printer); + if (!ShouldSerializeInOrder(descriptor_, options_)) { + format.Outdent(); + format("#else // NDEBUG\n"); + format.Indent(); + + GenerateSerializeWithCachedSizesBodyShuffled(printer); + + format.Outdent(); + format("#endif // !NDEBUG\n"); + format.Indent(); + } + format("// @@protoc_insertion_point(serialize_to_array_end:$full_name$)\n"); format.Outdent(); @@ -3630,11 +3539,14 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody( (i < descriptor_->field_count() && ordered_fields[i]->number() < sorted_extensions[j]->start)) { const FieldDescriptor* field = ordered_fields[i++]; - if (!IsFieldUsed(field, options_)) { + if (IsFieldStripped(field, options_)) { continue; } if (field->options().weak()) { - last_weak_field = field; + if (last_weak_field == nullptr || + last_weak_field->number() < field->number()) { + last_weak_field = field; + } PrintFieldComment(format, field); } else { if (last_weak_field != nullptr) { @@ -3677,6 +3589,115 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody( format("}\n"); } +void MessageGenerator::GenerateSerializeWithCachedSizesBodyShuffled( + io::Printer* printer) { + Formatter format(printer, variables_); + + std::vector ordered_fields = + SortFieldsByNumber(descriptor_); + ordered_fields.erase( + std::remove_if(ordered_fields.begin(), ordered_fields.end(), + [this](const FieldDescriptor* f) { + return !IsFieldUsed(f, options_); + }), + ordered_fields.end()); + + std::vector sorted_extensions; + sorted_extensions.reserve(descriptor_->extension_range_count()); + for (int i = 0; i < descriptor_->extension_range_count(); ++i) { + sorted_extensions.push_back(descriptor_->extension_range(i)); + } + std::sort(sorted_extensions.begin(), sorted_extensions.end(), + ExtensionRangeSorter()); + + int num_fields = ordered_fields.size() + sorted_extensions.size(); + constexpr int kLargePrime = 1000003; + GOOGLE_CHECK_LT(num_fields, kLargePrime) + << "Prime offset must be greater than the number of fields to ensure " + "those are coprime."; + + if (num_weak_fields_) { + format( + "::$proto_ns$::internal::WeakFieldMap::FieldWriter field_writer(" + "_weak_field_map_);\n"); + } + + format( + "static const int kStart = GetInvariantPerBuild($1$UL) % $2$;\n" + "bool first_pass = true;\n" + "for (int i = kStart; i != kStart || first_pass; i = ((i + $3$) % $2$)) " + "{\n", + 0, + num_fields, kLargePrime); + + format.Indent(); + format("switch(i) {\n"); + format.Indent(); + + bool first_pass_set = false; + int index = 0; + for (const auto* f : ordered_fields) { + format("case $1$: {\n", index++); + format.Indent(); + + if (!first_pass_set) { + first_pass_set = true; + format("first_pass = false;\n"); + } + + GenerateSerializeOneField(printer, f, -1); + + format("break;\n"); + format.Outdent(); + format("}\n"); + } + + for (const auto* r : sorted_extensions) { + format("case $1$: {\n", index++); + format.Indent(); + + if (!first_pass_set) { + first_pass_set = true; + format("first_pass = false;\n"); + } + + GenerateSerializeOneExtensionRange(printer, r); + + format("break;\n"); + format.Outdent(); + format("}\n"); + } + + format( + "default: {\n" + " $DCHK$(false) << \"Unexpected index: \" << i;\n" + "}\n"); + format.Outdent(); + format("}\n"); + + format.Outdent(); + format("}\n"); + + std::map vars; + SetUnknkownFieldsVariable(descriptor_, options_, &vars); + format.AddMap(vars); + format("if (PROTOBUF_PREDICT_FALSE($have_unknown_fields$)) {\n"); + format.Indent(); + if (UseUnknownFieldSet(descriptor_->file(), options_)) { + format( + "target = " + "::$proto_ns$::internal::WireFormat::" + "InternalSerializeUnknownFieldsToArray(\n" + " $unknown_fields$, target, stream);\n"); + } else { + format( + "target = stream->WriteRaw($unknown_fields$.data(),\n" + " static_cast($unknown_fields$.size()), target);\n"); + } + format.Outdent(); + format("}\n"); +} + std::vector MessageGenerator::RequiredFieldsBitMask() const { const int array_size = HasBitsSize(); std::vector masks(array_size, 0); @@ -3898,7 +3919,7 @@ void MessageGenerator::GenerateByteSize(io::Printer* printer) { PrintFieldComment(format, field); format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); format.Indent(); - if (IsFieldUsed(field, options_)) { + if (!IsFieldStripped(field, options_)) { field_generators_.get(field).GenerateByteSize(printer); } format("break;\n"); @@ -4026,7 +4047,7 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) { format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); format.Indent(); - if (IsFieldUsed(field, options_) && + if (!IsFieldStripped(field, options_) && field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && !ShouldIgnoreRequiredFieldCheck(field, options_) && scc_analyzer_->HasRequiredFields(field->message_type())) { diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h index a212ff416b..8917d1384d 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.h +++ b/src/google/protobuf/compiler/cpp/cpp_message.h @@ -82,17 +82,9 @@ class MessageGenerator { // Source file stuff. - // Generate extra fields - void GenerateExtraDefaultFields(io::Printer* printer); - // Generates code that creates default instances for fields. void GenerateFieldDefaultInstances(io::Printer* printer); - // Generates code that initializes the message's default instance. This - // is separate from allocating because all default instances must be - // allocated before any can be initialized. - void GenerateDefaultInstanceInitializer(io::Printer* printer); - // Generate all non-inline methods for this class. void GenerateClassMethods(io::Printer* printer); @@ -142,6 +134,7 @@ class MessageGenerator { void GenerateSerializeWithCachedSizes(io::Printer* printer); void GenerateSerializeWithCachedSizesToArray(io::Printer* printer); void GenerateSerializeWithCachedSizesBody(io::Printer* printer); + void GenerateSerializeWithCachedSizesBodyShuffled(io::Printer* printer); void GenerateByteSize(io::Printer* printer); void GenerateMergeFrom(io::Printer* printer); void GenerateClassSpecificMergeFrom(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 38fcb52e6c..f1a5cef1de 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc @@ -67,8 +67,9 @@ void SetMessageVariables(const FieldDescriptor* descriptor, QualifiedDefaultInstancePtr(descriptor->message_type(), options); (*variables)["type_reference_function"] = implicit_weak ? (" ::" + (*variables)["proto_ns"] + - "::internal::StrongReference(" + - (*variables)["type_default_instance"] + ");\n") + "::internal::StrongReference(reinterpret_cast(\n" + + (*variables)["type_default_instance"] + "));\n") : ""; // NOTE: Escaped here to unblock proto1->proto2 migration. // TODO(liujisi): Extend this to apply for other conflicting methods. @@ -104,7 +105,7 @@ void MessageFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const { void MessageFieldGenerator::GenerateAccessorDeclarations( io::Printer* printer) const { Formatter format(printer, variables_); - if (!IsFieldUsed(descriptor_, options_)) { + if (IsFieldStripped(descriptor_, options_)) { format( "$deprecated_attr$const $type$& ${1$$name$$}$() const { " "__builtin_trap(); }\n" @@ -113,17 +114,13 @@ void MessageFieldGenerator::GenerateAccessorDeclarations( "$deprecated_attr$$type$* ${1$mutable_$name$$}$() { " "__builtin_trap(); }\n" "$deprecated_attr$void ${1$set_allocated_$name$$}$" - "($type$* $name$) { __builtin_trap(); }\n", + "($type$* $name$) { __builtin_trap(); }\n" + "$deprecated_attr$void " + "${1$unsafe_arena_set_allocated_$name$$}$(\n" + " $type$* $name$) { __builtin_trap(); }\n" + "$deprecated_attr$$type$* ${1$unsafe_arena_release_$name$$}$() { " + "__builtin_trap(); }\n", descriptor_); - if (SupportsArenas(descriptor_)) { - format( - "$deprecated_attr$void " - "${1$unsafe_arena_set_allocated_$name$$}$(\n" - " $type$* $name$) { __builtin_trap(); }\n" - "$deprecated_attr$$type$* ${1$unsafe_arena_release_$name$$}$() { " - "__builtin_trap(); }\n", - descriptor_); - } return; } format( @@ -133,7 +130,7 @@ void MessageFieldGenerator::GenerateAccessorDeclarations( "$deprecated_attr$void ${1$set_allocated_$name$$}$" "($type$* $name$);\n", descriptor_); - if (IsFieldUsed(descriptor_, options_)) { + if (!IsFieldStripped(descriptor_, options_)) { format( "private:\n" "const $type$& ${1$_internal_$name$$}$() const;\n" @@ -141,14 +138,12 @@ void MessageFieldGenerator::GenerateAccessorDeclarations( "public:\n", descriptor_); } - if (SupportsArenas(descriptor_)) { - format( - "$deprecated_attr$void " - "${1$unsafe_arena_set_allocated_$name$$}$(\n" - " $type$* $name$);\n" - "$deprecated_attr$$type$* ${1$unsafe_arena_release_$name$$}$();\n", - descriptor_); - } + format( + "$deprecated_attr$void " + "${1$unsafe_arena_set_allocated_$name$$}$(\n" + " $type$* $name$);\n" + "$deprecated_attr$$type$* ${1$unsafe_arena_release_$name$$}$();\n", + descriptor_); } void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions( @@ -162,8 +157,8 @@ void MessageFieldGenerator::GenerateInlineAccessorDefinitions( "inline const $type$& $classname$::_internal_$name$() const {\n" "$type_reference_function$" " const $type$* p = $casted_member$;\n" - " return p != nullptr ? *p : *reinterpret_cast(\n" - " &$type_default_instance$);\n" + " return p != nullptr ? *p : reinterpret_cast(\n" + " $type_default_instance$);\n" "}\n" "inline const $type$& $classname$::$name$() const {\n" "$annotate_accessor$" @@ -171,48 +166,43 @@ void MessageFieldGenerator::GenerateInlineAccessorDefinitions( " return _internal_$name$();\n" "}\n"); - if (SupportsArenas(descriptor_)) { - format( - "inline void $classname$::unsafe_arena_set_allocated_$name$(\n" - " $type$* $name$) {\n" - "$annotate_accessor$" - // If we're not on an arena, free whatever we were holding before. - // (If we are on arena, we can just forget the earlier pointer.) - " if (GetArena() == nullptr) {\n" - " delete reinterpret_cast<::$proto_ns$::MessageLite*>($name$_);\n" - " }\n"); - if (implicit_weak_field_) { - format( - " $name$_ = " - "reinterpret_cast<::$proto_ns$::MessageLite*>($name$);\n"); - } else { - format(" $name$_ = $name$;\n"); - } - format( - " if ($name$) {\n" - " $set_hasbit$\n" - " } else {\n" - " $clear_hasbit$\n" - " }\n" - " // @@protoc_insertion_point(field_unsafe_arena_set_allocated" - ":$full_name$)\n" - "}\n"); + format( + "inline void $classname$::unsafe_arena_set_allocated_$name$(\n" + " $type$* $name$) {\n" + "$annotate_accessor$" + // If we're not on an arena, free whatever we were holding before. + // (If we are on arena, we can just forget the earlier pointer.) + " if (GetArena() == nullptr) {\n" + " delete reinterpret_cast<::$proto_ns$::MessageLite*>($name$_);\n" + " }\n"); + if (implicit_weak_field_) { format( - "inline $type$* $classname$::$release_name$() {\n" - "$type_reference_function$" - " $clear_hasbit$\n" - " $type$* temp = $casted_member$;\n" - " $name$_ = nullptr;\n" - " if (GetArena() != nullptr) {\n" - " temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n" - " }\n" - " return temp;\n" - "}\n" - "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"); + " $name$_ = " + "reinterpret_cast<::$proto_ns$::MessageLite*>($name$);\n"); } else { - format("inline $type$* $classname$::$release_name$() {\n"); + format(" $name$_ = $name$;\n"); } format( + " if ($name$) {\n" + " $set_hasbit$\n" + " } else {\n" + " $clear_hasbit$\n" + " }\n" + " // @@protoc_insertion_point(field_unsafe_arena_set_allocated" + ":$full_name$)\n" + "}\n"); + format( + "inline $type$* $classname$::$release_name$() {\n" + "$type_reference_function$" + " $clear_hasbit$\n" + " $type$* temp = $casted_member$;\n" + " $name$_ = nullptr;\n" + " if (GetArena() != nullptr) {\n" + " temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n" + " }\n" + " return temp;\n" + "}\n" + "inline $type$* $classname$::unsafe_arena_release_$name$() {\n" "$annotate_accessor$" " // @@protoc_insertion_point(field_release:$full_name$)\n" "$type_reference_function$" @@ -259,16 +249,13 @@ void MessageFieldGenerator::GenerateInlineAccessorDefinitions( format( " }\n" " if ($name$) {\n"); - if (SupportsArenas(descriptor_->message_type()) && - IsCrossFileMessage(descriptor_)) { + if (IsCrossFileMessage(descriptor_)) { // We have to read the arena through the virtual method, because the type // isn't defined in this file. format( " ::$proto_ns$::Arena* submessage_arena =\n" " " "reinterpret_cast<::$proto_ns$::MessageLite*>($name$)->GetArena();\n"); - } else if (!SupportsArenas(descriptor_->message_type())) { - format(" ::$proto_ns$::Arena* submessage_arena = nullptr;\n"); } else { format( " ::$proto_ns$::Arena* submessage_arena =\n" @@ -330,48 +317,26 @@ void MessageFieldGenerator::GenerateInternalAccessorDefinitions( "*::$proto_ns$::internal::ImplicitWeakMessage::default_instance();\n" " }\n" "}\n"); - if (SupportsArenas(descriptor_)) { - format( - "::$proto_ns$::MessageLite*\n" - "$classname$::_Internal::mutable_$name$($classname$* msg) {\n"); - if (HasFieldPresence(descriptor_->file())) { - format(" msg->$set_hasbit$\n"); - } - format( - " if (msg->$name$_ == nullptr) {\n" - " if ($type_default_instance_ptr$ == nullptr) {\n" - " msg->$name$_ = ::$proto_ns$::Arena::CreateMessage<\n" - " ::$proto_ns$::internal::ImplicitWeakMessage>(\n" - " msg->GetArena());\n" - " } else {\n" - " msg->$name$_ = reinterpret_cast(\n" - " $type_default_instance_ptr$)->New(msg->GetArena());\n" - " }\n" - " }\n" - " return msg->$name$_;\n" - "}\n"); - } else { - format( - "::$proto_ns$::MessageLite*\n" - "$classname$::_Internal::mutable_$name$($classname$* msg) {\n"); - if (HasFieldPresence(descriptor_->file())) { - format(" msg->$set_hasbit$\n"); - } - format( - " if (msg->$name$_ == nullptr) {\n" - " if ($type_default_instance_ptr$ == nullptr) {\n" - " msg->$name$_ = " - "new ::$proto_ns$::internal::ImplicitWeakMessage;\n" - " } else {\n" - " msg->$name$_ = " - "reinterpret_cast(\n" - " $type_default_instance_ptr$)->New();\n" - " }\n" - " }\n" - " return msg->$name$_;\n" - "}\n"); + format( + "::$proto_ns$::MessageLite*\n" + "$classname$::_Internal::mutable_$name$($classname$* msg) {\n"); + if (HasFieldPresence(descriptor_->file())) { + format(" msg->$set_hasbit$\n"); } + format( + " if (msg->$name$_ == nullptr) {\n" + " if ($type_default_instance_ptr$ == nullptr) {\n" + " msg->$name$_ = ::$proto_ns$::Arena::CreateMessage<\n" + " ::$proto_ns$::internal::ImplicitWeakMessage>(\n" + " msg->GetArena());\n" + " } else {\n" + " msg->$name$_ = reinterpret_cast(\n" + " $type_default_instance_ptr$)->New(msg->GetArena());\n" + " }\n" + " }\n" + " return msg->$name$_;\n" + "}\n"); } else { // This inline accessor directly returns member field and is used in // Serialize such that AFDO profile correctly captures access information to @@ -385,7 +350,7 @@ void MessageFieldGenerator::GenerateInternalAccessorDefinitions( } void MessageFieldGenerator::GenerateClearingCode(io::Printer* printer) const { - GOOGLE_CHECK(IsFieldUsed(descriptor_, options_)); + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); Formatter format(printer, variables_); if (!HasFieldPresence(descriptor_->file())) { @@ -403,7 +368,7 @@ void MessageFieldGenerator::GenerateClearingCode(io::Printer* printer) const { void MessageFieldGenerator::GenerateMessageClearingCode( io::Printer* printer) const { - GOOGLE_CHECK(IsFieldUsed(descriptor_, options_)); + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); Formatter format(printer, variables_); if (!HasFieldPresence(descriptor_->file())) { @@ -422,7 +387,7 @@ void MessageFieldGenerator::GenerateMessageClearingCode( } void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) const { - GOOGLE_CHECK(IsFieldUsed(descriptor_, options_)); + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); Formatter format(printer, variables_); if (implicit_weak_field_) { @@ -437,14 +402,14 @@ void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) const { } void MessageFieldGenerator::GenerateSwappingCode(io::Printer* printer) const { - GOOGLE_CHECK(IsFieldUsed(descriptor_, options_)); + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); Formatter format(printer, variables_); format("swap($name$_, other->$name$_);\n"); } void MessageFieldGenerator::GenerateDestructorCode(io::Printer* printer) const { - GOOGLE_CHECK(IsFieldUsed(descriptor_, options_)); + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); Formatter format(printer, variables_); if (options_.opensource_runtime) { @@ -460,7 +425,7 @@ void MessageFieldGenerator::GenerateDestructorCode(io::Printer* printer) const { void MessageFieldGenerator::GenerateConstructorCode( io::Printer* printer) const { - GOOGLE_CHECK(IsFieldUsed(descriptor_, options_)); + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); Formatter format(printer, variables_); format("$name$_ = nullptr;\n"); @@ -468,7 +433,7 @@ void MessageFieldGenerator::GenerateConstructorCode( void MessageFieldGenerator::GenerateCopyConstructorCode( io::Printer* printer) const { - GOOGLE_CHECK(IsFieldUsed(descriptor_, options_)); + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); Formatter format(printer, variables_); format( @@ -481,7 +446,7 @@ void MessageFieldGenerator::GenerateCopyConstructorCode( void MessageFieldGenerator::GenerateSerializeWithCachedSizesToArray( io::Printer* printer) const { - GOOGLE_CHECK(IsFieldUsed(descriptor_, options_)); + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); Formatter format(printer, variables_); format( @@ -492,7 +457,7 @@ void MessageFieldGenerator::GenerateSerializeWithCachedSizesToArray( } void MessageFieldGenerator::GenerateByteSize(io::Printer* printer) const { - GOOGLE_CHECK(IsFieldUsed(descriptor_, options_)); + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); Formatter format(printer, variables_); format( @@ -521,16 +486,13 @@ void MessageOneofFieldGenerator::GenerateNonInlineAccessorDefinitions( " ::$proto_ns$::Arena* message_arena = GetArena();\n" " clear_$oneof_name$();\n" " if ($name$) {\n"); - if (SupportsArenas(descriptor_->message_type()) && - descriptor_->file() != descriptor_->message_type()->file()) { + if (descriptor_->file() != descriptor_->message_type()->file()) { // We have to read the arena through the virtual method, because the type // isn't defined in this file. format( " ::$proto_ns$::Arena* submessage_arena =\n" " " "reinterpret_cast<::$proto_ns$::MessageLite*>($name$)->GetArena();\n"); - } else if (!SupportsArenas(descriptor_->message_type())) { - format(" ::$proto_ns$::Arena* submessage_arena = nullptr;\n"); } else { format( " ::$proto_ns$::Arena* submessage_arena =\n" @@ -557,14 +519,10 @@ void MessageOneofFieldGenerator::GenerateInlineAccessorDefinitions( " // @@protoc_insertion_point(field_release:$full_name$)\n" " if (_internal_has_$name$()) {\n" " clear_has_$oneof_name$();\n" - " $type$* temp = $field_member$;\n"); - if (SupportsArenas(descriptor_)) { - format( - " if (GetArena() != nullptr) {\n" - " temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n" - " }\n"); - } - format( + " $type$* temp = $field_member$;\n" + " if (GetArena() != nullptr) {\n" + " temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n" + " }\n" " $field_member$ = nullptr;\n" " return temp;\n" " } else {\n" @@ -576,46 +534,40 @@ void MessageOneofFieldGenerator::GenerateInlineAccessorDefinitions( "inline const $type$& $classname$::_internal_$name$() const {\n" " return _internal_has_$name$()\n" " ? *$field_member$\n" - " : *reinterpret_cast< $type$*>(&$type_default_instance$);\n" + " : reinterpret_cast< $type$&>($type_default_instance$);\n" "}\n" "inline const $type$& $classname$::$name$() const {\n" "$annotate_accessor$" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return _internal_$name$();\n" - "}\n"); - - if (SupportsArenas(descriptor_)) { - format( - "inline $type$* $classname$::unsafe_arena_release_$name$() {\n" - "$annotate_accessor$" - " // @@protoc_insertion_point(field_unsafe_arena_release" - ":$full_name$)\n" - " if (_internal_has_$name$()) {\n" - " clear_has_$oneof_name$();\n" - " $type$* temp = $field_member$;\n" - " $field_member$ = nullptr;\n" - " return temp;\n" - " } else {\n" - " return nullptr;\n" - " }\n" - "}\n" - "inline void $classname$::unsafe_arena_set_allocated_$name$" - "($type$* $name$) {\n" - "$annotate_accessor$" - // We rely on the oneof clear method to free the earlier contents of - // this oneof. We can directly use the pointer we're given to set the - // new value. - " clear_$oneof_name$();\n" - " if ($name$) {\n" - " set_has_$name$();\n" - " $field_member$ = $name$;\n" - " }\n" - " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:" - "$full_name$)\n" - "}\n"); - } - - format( + "}\n" + "inline $type$* $classname$::unsafe_arena_release_$name$() {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_unsafe_arena_release" + ":$full_name$)\n" + " if (_internal_has_$name$()) {\n" + " clear_has_$oneof_name$();\n" + " $type$* temp = $field_member$;\n" + " $field_member$ = nullptr;\n" + " return temp;\n" + " } else {\n" + " return nullptr;\n" + " }\n" + "}\n" + "inline void $classname$::unsafe_arena_set_allocated_$name$" + "($type$* $name$) {\n" + "$annotate_accessor$" + // We rely on the oneof clear method to free the earlier contents of + // this oneof. We can directly use the pointer we're given to set the + // new value. + " clear_$oneof_name$();\n" + " if ($name$) {\n" + " set_has_$name$();\n" + " $field_member$ = $name$;\n" + " }\n" + " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:" + "$full_name$)\n" + "}\n" "inline $type$* $classname$::_internal_mutable_$name$() {\n" " if (!_internal_has_$name$()) {\n" " clear_$oneof_name$();\n" @@ -633,17 +585,13 @@ void MessageOneofFieldGenerator::GenerateInlineAccessorDefinitions( void MessageOneofFieldGenerator::GenerateClearingCode( io::Printer* printer) const { - GOOGLE_CHECK(IsFieldUsed(descriptor_, options_)); + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); Formatter format(printer, variables_); - if (SupportsArenas(descriptor_)) { - format( - "if (GetArena() == nullptr) {\n" - " delete $field_member$;\n" - "}\n"); - } else { - format("delete $field_member$;\n"); - } + format( + "if (GetArena() == nullptr) {\n" + " delete $field_member$;\n" + "}\n"); } void MessageOneofFieldGenerator::GenerateMessageClearingCode( @@ -694,7 +642,7 @@ void RepeatedMessageFieldGenerator::GeneratePrivateMembers( void RepeatedMessageFieldGenerator::GenerateAccessorDeclarations( io::Printer* printer) const { Formatter format(printer, variables_); - if (!IsFieldUsed(descriptor_, options_)) { + if (IsFieldStripped(descriptor_, options_)) { format( "$deprecated_attr$$type$* ${1$mutable_$name$$}$(int index) { " "__builtin_trap(); }\n" @@ -714,7 +662,7 @@ void RepeatedMessageFieldGenerator::GenerateAccessorDeclarations( "$deprecated_attr$::$proto_ns$::RepeatedPtrField< $type$ >*\n" " ${1$mutable_$name$$}$();\n", descriptor_); - if (IsFieldUsed(descriptor_, options_)) { + if (!IsFieldStripped(descriptor_, options_)) { format( "private:\n" "const $type$& ${1$_internal_$name$$}$(int index) const;\n" @@ -756,7 +704,7 @@ void RepeatedMessageFieldGenerator::GenerateInlineAccessorDefinitions( "inline const $type$& $classname$::_internal_$name$(int index) const " "{\n" " return $name$_$weak$.InternalCheckedGet(index,\n" - " *reinterpret_cast(&$type_default_instance$));\n" + " reinterpret_cast($type_default_instance$));\n" "}\n"); } else { format( @@ -794,7 +742,7 @@ void RepeatedMessageFieldGenerator::GenerateInlineAccessorDefinitions( void RepeatedMessageFieldGenerator::GenerateClearingCode( io::Printer* printer) const { - GOOGLE_CHECK(IsFieldUsed(descriptor_, options_)); + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); Formatter format(printer, variables_); format("$name$_.Clear();\n"); @@ -802,7 +750,7 @@ void RepeatedMessageFieldGenerator::GenerateClearingCode( void RepeatedMessageFieldGenerator::GenerateMergingCode( io::Printer* printer) const { - GOOGLE_CHECK(IsFieldUsed(descriptor_, options_)); + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); Formatter format(printer, variables_); format("$name$_.MergeFrom(from.$name$_);\n"); @@ -810,7 +758,7 @@ void RepeatedMessageFieldGenerator::GenerateMergingCode( void RepeatedMessageFieldGenerator::GenerateSwappingCode( io::Printer* printer) const { - GOOGLE_CHECK(IsFieldUsed(descriptor_, options_)); + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); Formatter format(printer, variables_); format("$name$_.InternalSwap(&other->$name$_);\n"); @@ -823,7 +771,7 @@ void RepeatedMessageFieldGenerator::GenerateConstructorCode( void RepeatedMessageFieldGenerator::GenerateSerializeWithCachedSizesToArray( io::Printer* printer) const { - GOOGLE_CHECK(IsFieldUsed(descriptor_, options_)); + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); Formatter format(printer, variables_); if (implicit_weak_field_) { @@ -850,7 +798,7 @@ void RepeatedMessageFieldGenerator::GenerateSerializeWithCachedSizesToArray( void RepeatedMessageFieldGenerator::GenerateByteSize( io::Printer* printer) const { - GOOGLE_CHECK(IsFieldUsed(descriptor_, options_)); + GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); Formatter format(printer, variables_); format( diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc index 5cf82f6de2..9acc447983 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc @@ -99,18 +99,6 @@ void StringFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const { if (inlined_) { format("::$proto_ns$::internal::InlinedStringField $name$_;\n"); } else { - // N.B. that we continue to use |ArenaStringPtr| instead of |string*| for - // string fields, even when SupportArenas(descriptor_) == false. Why? The - // simple answer is to avoid unmaintainable complexity. The reflection code - // assumes ArenaStringPtrs. These are *almost* in-memory-compatible with - // string*, except for the pointer tags and related ownership semantics. We - // could modify the runtime code to use string* for the - // not-supporting-arenas case, but this would require a way to detect which - // type of class was generated (adding overhead and complexity to - // GeneratedMessageReflection) and littering the runtime code paths with - // conditionals. It's simpler to stick with this but use lightweight - // accessors that assume arena == NULL. There should be very little - // overhead anyway because it's just a tagged pointer in-memory. format("::$proto_ns$::internal::ArenaStringPtr $name$_;\n"); } } @@ -211,163 +199,82 @@ void StringFieldGenerator::GenerateInlineAccessorDefinitions( "$annotate_accessor$" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return _internal_mutable_$name$();\n" + "}\n" + "inline const std::string& $classname$::_internal_$name$() const {\n" + " return $name$_.Get();\n" + "}\n" + "inline void $classname$::_internal_set_$name$(const std::string& " + "value) {\n" + " $set_hasbit$\n" + " $name$_.Set$lite$($default_variable$, value, GetArena());\n" + "}\n" + "inline void $classname$::set_$name$(std::string&& value) {\n" + "$annotate_accessor$" + " $set_hasbit$\n" + " $name$_.Set$lite$(\n" + " $default_variable$, ::std::move(value), GetArena());\n" + " // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n" + "}\n" + "inline void $classname$::set_$name$(const char* value) {\n" + "$annotate_accessor$" + " $null_check$" + " $set_hasbit$\n" + " $name$_.Set$lite$($default_variable$, $string_piece$(value),\n" + " GetArena());\n" + " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n"); - if (SupportsArenas(descriptor_)) { + if (!options_.opensource_runtime) { format( - "inline const std::string& $classname$::_internal_$name$() const {\n" - " return $name$_.Get();\n" - "}\n" - "inline void $classname$::_internal_set_$name$(const std::string& " - "value) {\n" - " $set_hasbit$\n" - " $name$_.Set$lite$($default_variable$, value, GetArena());\n" - "}\n" - "inline void $classname$::set_$name$(std::string&& value) {\n" - "$annotate_accessor$" - " $set_hasbit$\n" - " $name$_.Set$lite$(\n" - " $default_variable$, ::std::move(value), GetArena());\n" - " // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n" - "}\n" - "inline void $classname$::set_$name$(const char* value) {\n" + "inline void $classname$::set_$name$(::StringPiece value) {\n" "$annotate_accessor$" - " $null_check$" " $set_hasbit$\n" - " $name$_.Set$lite$($default_variable$, $string_piece$(value),\n" - " GetArena());\n" - " // @@protoc_insertion_point(field_set_char:$full_name$)\n" + " $name$_.Set$lite$($default_variable$, value,GetArena());\n" + " // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n" "}\n"); - if (!options_.opensource_runtime) { - format( - "inline void $classname$::set_$name$(::StringPiece value) {\n" - "$annotate_accessor$" - " $set_hasbit$\n" - " $name$_.Set$lite$($default_variable$, value,GetArena());\n" - " // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n" - "}\n"); - } - format( - "inline " - "void $classname$::set_$name$(const $pointer_type$* value,\n" - " size_t size) {\n" - "$annotate_accessor$" - " $set_hasbit$\n" - " $name$_.Set$lite$($default_variable$, $string_piece$(\n" - " reinterpret_cast(value), size), GetArena());\n" - " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" - "}\n" - "inline std::string* $classname$::_internal_mutable_$name$() {\n" - " $set_hasbit$\n" - " return $name$_.Mutable($default_variable$, GetArena());\n" - "}\n" - "inline std::string* $classname$::$release_name$() {\n" - "$annotate_accessor$" - " // @@protoc_insertion_point(field_release:$full_name$)\n"); - - if (HasHasbit(descriptor_)) { - format( - " if (!_internal_has_$name$()) {\n" - " return nullptr;\n" - " }\n" - " $clear_hasbit$\n" - " return $name$_.ReleaseNonDefault(" - "$default_variable$, GetArena());\n"); - } else { - format( - " return $name$_.Release($default_variable$, GetArena());\n"); - } + } + format( + "inline " + "void $classname$::set_$name$(const $pointer_type$* value,\n" + " size_t size) {\n" + "$annotate_accessor$" + " $set_hasbit$\n" + " $name$_.Set$lite$($default_variable$, $string_piece$(\n" + " reinterpret_cast(value), size), GetArena());\n" + " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" + "}\n" + "inline std::string* $classname$::_internal_mutable_$name$() {\n" + " $set_hasbit$\n" + " return $name$_.Mutable($default_variable$, GetArena());\n" + "}\n" + "inline std::string* $classname$::$release_name$() {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_release:$full_name$)\n"); + if (HasHasbit(descriptor_)) { format( - "}\n" - "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n" - "$annotate_accessor$" - " if ($name$ != nullptr) {\n" - " $set_hasbit$\n" - " } else {\n" - " $clear_hasbit$\n" + " if (!_internal_has_$name$()) {\n" + " return nullptr;\n" " }\n" - " $name$_.SetAllocated($default_variable$, $name$,\n" - " GetArena());\n" - " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" - "}\n"); + " $clear_hasbit$\n" + " return $name$_.ReleaseNonDefault(" + "$default_variable$, GetArena());\n"); } else { - // No-arena case. - format( - "inline const std::string& $classname$::_internal_$name$() const {\n" - " return $name$_.GetNoArena();\n" - "}\n" - "inline void $classname$::_internal_set_$name$(const std::string& " - "value) {\n" - " $set_hasbit$\n" - " $name$_.SetNoArena($default_variable$, value);\n" - "}\n" - "inline void $classname$::set_$name$(std::string&& value) {\n" - "$annotate_accessor$" - " $set_hasbit$\n" - " $name$_.SetNoArena(\n" - " $default_variable$, ::std::move(value));\n" - " // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n" - "}\n" - "inline void $classname$::set_$name$(const char* value) {\n" - "$annotate_accessor$" - " $null_check$" - " $set_hasbit$\n" - " $name$_.SetNoArena($default_variable$, $string_piece$(value));\n" - " // @@protoc_insertion_point(field_set_char:$full_name$)\n" - "}\n"); - if (!options_.opensource_runtime) { - format( - "inline void $classname$::set_$name$(::StringPiece value) {\n" - "$annotate_accessor$" - " $set_hasbit$\n" - " $name$_.SetNoArena($default_variable$, value);\n" - " // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n" - "}\n"); - } - format( - "inline " - "void $classname$::set_$name$(const $pointer_type$* value, " - "size_t size) {\n" - "$annotate_accessor$" - " $set_hasbit$\n" - " $name$_.SetNoArena($default_variable$,\n" - " $string_piece$(reinterpret_cast(value), size));\n" - " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" - "}\n" - "inline std::string* $classname$::_internal_mutable_$name$() {\n" - " $set_hasbit$\n" - " return $name$_.MutableNoArena($default_variable$);\n" - "}\n" - "inline std::string* $classname$::$release_name$() {\n" - "$annotate_accessor$" - " // @@protoc_insertion_point(field_release:$full_name$)\n"); - - if (HasHasbit(descriptor_)) { - format( - " if (!_internal_has_$name$()) {\n" - " return nullptr;\n" - " }\n" - " $clear_hasbit$\n" - " return $name$_.ReleaseNonDefaultNoArena($default_variable$);\n"); - } else { - format( - " $clear_hasbit$\n" - " return $name$_.ReleaseNoArena($default_variable$);\n"); - } - - format( - "}\n" - "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n" - "$annotate_accessor$" - " if ($name$ != nullptr) {\n" - " $set_hasbit$\n" - " } else {\n" - " $clear_hasbit$\n" - " }\n" - " $name$_.SetAllocatedNoArena($default_variable$, $name$);\n" - " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" - "}\n"); + format(" return $name$_.Release($default_variable$, GetArena());\n"); } + + format( + "}\n" + "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n" + "$annotate_accessor$" + " if ($name$ != nullptr) {\n" + " $set_hasbit$\n" + " } else {\n" + " $clear_hasbit$\n" + " }\n" + " $name$_.SetAllocated($default_variable$, $name$,\n" + " GetArena());\n" + " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" + "}\n"); } void StringFieldGenerator::GenerateNonInlineAccessorDefinitions( @@ -387,18 +294,10 @@ void StringFieldGenerator::GenerateClearingCode(io::Printer* printer) const { // value is the empty string or not. Complexity here ensures the minimal // number of branches / amount of extraneous code at runtime (given that the // below methods are inlined one-liners)! - if (SupportsArenas(descriptor_)) { - if (descriptor_->default_value_string().empty()) { - format("$name$_.ClearToEmpty($default_variable$, GetArena());\n"); - } else { - format("$name$_.ClearToDefault($default_variable$, GetArena());\n"); - } + if (descriptor_->default_value_string().empty()) { + format("$name$_.ClearToEmpty($default_variable$, GetArena());\n"); } else { - if (descriptor_->default_value_string().empty()) { - format("$name$_.ClearToEmptyNoArena($default_variable$);\n"); - } else { - format("$name$_.ClearToDefaultNoArena($default_variable$);\n"); - } + format("$name$_.ClearToDefault($default_variable$, GetArena());\n"); } } @@ -427,45 +326,23 @@ void StringFieldGenerator::GenerateMessageClearingCode( format("$DCHK$(!$name$_.IsDefault($default_variable$));\n"); } - if (SupportsArenas(descriptor_)) { - if (descriptor_->default_value_string().empty()) { - if (must_be_present) { - format("$name$_.ClearNonDefaultToEmpty();\n"); - } else { - format("$name$_.ClearToEmpty($default_variable$, GetArena());\n"); - } - } else { - // Clear to a non-empty default is more involved, as we try to use the - // Arena if one is present and may need to reallocate the string. - format("$name$_.ClearToDefault($default_variable$, GetArena());\n"); - } - } else if (must_be_present) { - // When Arenas are disabled and field presence has been checked, we can - // safely treat the ArenaStringPtr as a string*. - if (descriptor_->default_value_string().empty()) { - format("$name$_.ClearNonDefaultToEmptyNoArena();\n"); + if (descriptor_->default_value_string().empty()) { + if (must_be_present) { + format("$name$_.ClearNonDefaultToEmpty();\n"); } else { - format("$name$_.UnsafeMutablePointer()->assign(*$default_variable$);\n"); + format("$name$_.ClearToEmpty($default_variable$, GetArena());\n"); } } else { - if (descriptor_->default_value_string().empty()) { - format("$name$_.ClearToEmptyNoArena($default_variable$);\n"); - } else { - format("$name$_.ClearToDefaultNoArena($default_variable$);\n"); - } + // Clear to a non-empty default is more involved, as we try to use the + // Arena if one is present and may need to reallocate the string. + format("$name$_.ClearToDefault($default_variable$, GetArena());\n"); } } void StringFieldGenerator::GenerateMergingCode(io::Printer* printer) const { Formatter format(printer, variables_); - if (SupportsArenas(descriptor_) || descriptor_->real_containing_oneof()) { - // TODO(gpike): improve this - format("_internal_set_$name$(from._internal_$name$());\n"); - } else { - format( - "$set_hasbit$\n" - "$name$_.AssignWithDefault($default_variable$, from.$name$_);\n"); - } + // TODO(gpike): improve this + format("_internal_set_$name$(from._internal_$name$());\n"); } void StringFieldGenerator::GenerateSwappingCode(io::Printer* printer) const { @@ -502,14 +379,10 @@ void StringFieldGenerator::GenerateCopyConstructorCode( format.Indent(); - if (SupportsArenas(descriptor_) || descriptor_->real_containing_oneof()) { - // TODO(gpike): improve this - format( - "$name$_.Set$lite$($default_variable$, from._internal_$name$(),\n" - " GetArena());\n"); - } else { - format("$name$_.AssignWithDefault($default_variable$, from.$name$_);\n"); - } + // TODO(gpike): improve this + format( + "$name$_.Set$lite$($default_variable$, from._internal_$name$(),\n" + " GetArena());\n"); format.Outdent(); format("}\n"); @@ -613,219 +486,115 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions( "$annotate_accessor$" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return _internal_mutable_$name$();\n" + "}\n" + "inline const std::string& $classname$::_internal_$name$() const {\n" + " if (_internal_has_$name$()) {\n" + " return $field_member$.Get();\n" + " }\n" + " return *$default_variable$;\n" + "}\n" + "inline void $classname$::_internal_set_$name$(const std::string& " + "value) {\n" + " if (!_internal_has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" + " }\n" + " $field_member$.Set$lite$($default_variable$, value, GetArena());\n" + "}\n" + "inline void $classname$::set_$name$(std::string&& value) {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_set:$full_name$)\n" + " if (!_internal_has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" + " }\n" + " $field_member$.Set$lite$(\n" + " $default_variable$, ::std::move(value), GetArena());\n" + " // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n" + "}\n" + "inline void $classname$::set_$name$(const char* value) {\n" + "$annotate_accessor$" + " $null_check$" + " if (!_internal_has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" + " }\n" + " $field_member$.Set$lite$($default_variable$,\n" + " $string_piece$(value), GetArena());\n" + " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n"); - if (SupportsArenas(descriptor_)) { - format( - "inline const std::string& $classname$::_internal_$name$() const {\n" - " if (_internal_has_$name$()) {\n" - " return $field_member$.Get();\n" - " }\n" - " return *$default_variable$;\n" - "}\n" - "inline void $classname$::_internal_set_$name$(const std::string& " - "value) {\n" - " if (!_internal_has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $field_member$.UnsafeSetDefault($default_variable$);\n" - " }\n" - " $field_member$.Set$lite$($default_variable$, value, GetArena());\n" - "}\n" - "inline void $classname$::set_$name$(std::string&& value) {\n" - "$annotate_accessor$" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - " if (!_internal_has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $field_member$.UnsafeSetDefault($default_variable$);\n" - " }\n" - " $field_member$.Set$lite$(\n" - " $default_variable$, ::std::move(value), GetArena());\n" - " // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n" - "}\n" - "inline void $classname$::set_$name$(const char* value) {\n" - "$annotate_accessor$" - " $null_check$" - " if (!_internal_has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $field_member$.UnsafeSetDefault($default_variable$);\n" - " }\n" - " $field_member$.Set$lite$($default_variable$,\n" - " $string_piece$(value), GetArena());\n" - " // @@protoc_insertion_point(field_set_char:$full_name$)\n" - "}\n"); - if (!options_.opensource_runtime) { - format( - "inline void $classname$::set_$name$(::StringPiece value) {\n" - "$annotate_accessor$" - " if (!_internal_has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $field_member$.UnsafeSetDefault($default_variable$);\n" - " }\n" - " $field_member$.Set$lite$($default_variable$, value,\n" - " GetArena());\n" - " // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n" - "}\n"); - } + if (!options_.opensource_runtime) { format( - "inline " - "void $classname$::set_$name$(const $pointer_type$* value,\n" - " size_t size) {\n" + "inline void $classname$::set_$name$(::StringPiece value) {\n" "$annotate_accessor$" " if (!_internal_has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" " $field_member$.UnsafeSetDefault($default_variable$);\n" " }\n" - " $field_member$.Set$lite$(\n" - " $default_variable$, $string_piece$(\n" - " reinterpret_cast(value), size),\n" + " $field_member$.Set$lite$($default_variable$, value,\n" " GetArena());\n" - " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" - "}\n" - "inline std::string* $classname$::_internal_mutable_$name$() {\n" - " if (!_internal_has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $field_member$.UnsafeSetDefault($default_variable$);\n" - " }\n" - " return $field_member$.Mutable($default_variable$, GetArena());\n" - "}\n" - "inline std::string* $classname$::$release_name$() {\n" - "$annotate_accessor$" - " // @@protoc_insertion_point(field_release:$full_name$)\n" - " if (_internal_has_$name$()) {\n" - " clear_has_$oneof_name$();\n" - " return $field_member$.Release($default_variable$, GetArena());\n" - " } else {\n" - " return nullptr;\n" - " }\n" - "}\n" - "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n" - "$annotate_accessor$" - " if (has_$oneof_name$()) {\n" - " clear_$oneof_name$();\n" - " }\n" - " if ($name$ != nullptr) {\n" - " set_has_$name$();\n" - " $field_member$.UnsafeSetDefault($name$);\n" - " ::$proto_ns$::Arena* arena = GetArena();\n" - " if (arena != nullptr) {\n" - " arena->Own($name$);\n" - " }\n" - " }\n" - " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" - "}\n"); - } else { - // No-arena case. - format( - "inline const std::string& $classname$::_internal_$name$() const {\n" - " if (_internal_has_$name$()) {\n" - " return $field_member$.GetNoArena();\n" - " }\n" - " return *$default_variable$;\n" - "}\n" - "inline void $classname$::_internal_set_$name$(const std::string& " - "value) {\n" - " if (!_internal_has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $field_member$.UnsafeSetDefault($default_variable$);\n" - " }\n" - " $field_member$.SetNoArena($default_variable$, value);\n" - "}\n" - "inline void $classname$::set_$name$(std::string&& value) {\n" - "$annotate_accessor$" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - " if (!_internal_has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $field_member$.UnsafeSetDefault($default_variable$);\n" - " }\n" - " $field_member$.SetNoArena($default_variable$, ::std::move(value));\n" - " // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n" - "}\n" - "inline void $classname$::set_$name$(const char* value) {\n" - "$annotate_accessor$" - " $null_check$" - " if (!_internal_has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $field_member$.UnsafeSetDefault($default_variable$);\n" - " }\n" - " $field_member$.SetNoArena($default_variable$,\n" - " $string_piece$(value));\n" - " // @@protoc_insertion_point(field_set_char:$full_name$)\n" - "}\n"); - if (!options_.opensource_runtime) { - format( - "inline void $classname$::set_$name$(::StringPiece value) {\n" - "$annotate_accessor$" - " if (!_internal_has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $field_member$.UnsafeSetDefault($default_variable$);\n" - " }\n" - " $field_member$.SetNoArena($default_variable$, value);\n" - " // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n" - "}\n"); - } - format( - "inline " - "void $classname$::set_$name$(const $pointer_type$* value, size_t " - "size) {\n" - "$annotate_accessor$" - " if (!_internal_has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $field_member$.UnsafeSetDefault($default_variable$);\n" - " }\n" - " $field_member$.SetNoArena($default_variable$, $string_piece$(\n" - " reinterpret_cast(value), size));\n" - " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" - "}\n" - "inline std::string* $classname$::_internal_mutable_$name$() {\n" - " if (!_internal_has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $field_member$.UnsafeSetDefault($default_variable$);\n" - " }\n" - " return $field_member$.MutableNoArena($default_variable$);\n" - "}\n" - "inline std::string* $classname$::$release_name$() {\n" - "$annotate_accessor$" - " // @@protoc_insertion_point(field_release:$full_name$)\n" - " if (_internal_has_$name$()) {\n" - " clear_has_$oneof_name$();\n" - " return $field_member$.ReleaseNoArena($default_variable$);\n" - " } else {\n" - " return nullptr;\n" - " }\n" - "}\n" - "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n" - "$annotate_accessor$" - " if (has_$oneof_name$()) {\n" - " clear_$oneof_name$();\n" - " }\n" - " if ($name$ != nullptr) {\n" - " set_has_$name$();\n" - " $field_member$.UnsafeSetDefault($name$);\n" - " }\n" - " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" + " // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n" "}\n"); } + format( + "inline " + "void $classname$::set_$name$(const $pointer_type$* value,\n" + " size_t size) {\n" + "$annotate_accessor$" + " if (!_internal_has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" + " }\n" + " $field_member$.Set$lite$(\n" + " $default_variable$, $string_piece$(\n" + " reinterpret_cast(value), size),\n" + " GetArena());\n" + " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" + "}\n" + "inline std::string* $classname$::_internal_mutable_$name$() {\n" + " if (!_internal_has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" + " }\n" + " return $field_member$.Mutable($default_variable$, GetArena());\n" + "}\n" + "inline std::string* $classname$::$release_name$() {\n" + "$annotate_accessor$" + " // @@protoc_insertion_point(field_release:$full_name$)\n" + " if (_internal_has_$name$()) {\n" + " clear_has_$oneof_name$();\n" + " return $field_member$.Release($default_variable$, GetArena());\n" + " } else {\n" + " return nullptr;\n" + " }\n" + "}\n" + "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n" + "$annotate_accessor$" + " if (has_$oneof_name$()) {\n" + " clear_$oneof_name$();\n" + " }\n" + " if ($name$ != nullptr) {\n" + " set_has_$name$();\n" + " $field_member$.UnsafeSetDefault($name$);\n" + " ::$proto_ns$::Arena* arena = GetArena();\n" + " if (arena != nullptr) {\n" + " arena->Own($name$);\n" + " }\n" + " }\n" + " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" + "}\n"); } void StringOneofFieldGenerator::GenerateClearingCode( io::Printer* printer) const { Formatter format(printer, variables_); - if (SupportsArenas(descriptor_)) { - format("$field_member$.Destroy($default_variable$, GetArena());\n"); - } else { - format("$field_member$.DestroyNoArena($default_variable$);\n"); - } + format("$field_member$.Destroy($default_variable$, GetArena());\n"); } void StringOneofFieldGenerator::GenerateMessageClearingCode( diff --git a/src/google/protobuf/compiler/importer.cc b/src/google/protobuf/compiler/importer.cc index ab5c356901..1ff8aadc6f 100644 --- a/src/google/protobuf/compiler/importer.cc +++ b/src/google/protobuf/compiler/importer.cc @@ -495,7 +495,7 @@ io::ZeroCopyInputStream* DiskSourceTree::OpenDiskFile( do { ret = stat(filename.c_str(), &sb); } while (ret != 0 && errno == EINTR); - if (sb.st_mode & S_IFDIR) { + if (ret == 0 && sb.st_mode & S_IFDIR) { last_error_message_ = "Input file is a directory."; return NULL; } diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc index 0b85056138..b463622d4a 100644 --- a/src/google/protobuf/compiler/mock_code_generator.cc +++ b/src/google/protobuf/compiler/mock_code_generator.cc @@ -166,17 +166,36 @@ void MockCodeGenerator::CheckGeneratedAnnotations( &file_content, true)); std::string meta_content; GOOGLE_CHECK_OK(File::GetContents( - output_directory + "/" + GetOutputFileName(name, file) + ".meta", + output_directory + "/" + GetOutputFileName(name, file) + ".pb.meta", &meta_content, true)); GeneratedCodeInfo annotations; GOOGLE_CHECK(TextFormat::ParseFromString(meta_content, &annotations)); - ASSERT_EQ(3, annotations.annotation_size()); + ASSERT_EQ(7, annotations.annotation_size()); + CheckSingleAnnotation("first_annotation", "first", file_content, annotations.annotation(0)); + CheckSingleAnnotation("first_path", + "test_generator: first_insert,\n foo.proto,\n " + "MockCodeGenerator_Annotate,\n foo.proto\n", + file_content, annotations.annotation(1)); + CheckSingleAnnotation("first_path", + "test_plugin: first_insert,\n foo.proto,\n " + "MockCodeGenerator_Annotate,\n foo.proto\n", + file_content, annotations.annotation(2)); CheckSingleAnnotation("second_annotation", "second", file_content, - annotations.annotation(1)); + annotations.annotation(3)); + // This annotated text has changed because it was inserted at an indented + // insertion point. + CheckSingleAnnotation("second_path", + "test_generator: second_insert,\n foo.proto,\n " + "MockCodeGenerator_Annotate,\n foo.proto\n", + file_content, annotations.annotation(4)); + CheckSingleAnnotation("second_path", + "test_plugin: second_insert,\n foo.proto,\n " + "MockCodeGenerator_Annotate,\n foo.proto\n", + file_content, annotations.annotation(5)); CheckSingleAnnotation("third_annotation", "third", file_content, - annotations.annotation(2)); + annotations.annotation(6)); } bool MockCodeGenerator::Generate(const FileDescriptor* file, @@ -229,18 +248,35 @@ bool MockCodeGenerator::Generate(const FileDescriptor* file, } } - if (HasPrefixString(parameter, "insert=")) { + bool insert_endlines = HasPrefixString(parameter, "insert_endlines="); + if (insert_endlines || HasPrefixString(parameter, "insert=")) { std::vector insert_into; - SplitStringUsing(StripPrefixString(parameter, "insert="), ",", - &insert_into); + + SplitStringUsing( + StripPrefixString( + parameter, insert_endlines ? "insert_endlines=" : "insert="), + ",", &insert_into); for (size_t i = 0; i < insert_into.size(); i++) { { - std::unique_ptr output(context->OpenForInsert( - GetOutputFileName(insert_into[i], file), kFirstInsertionPointName)); + google::protobuf::GeneratedCodeInfo info; + std::string content = + GetOutputFileContent(name_, "first_insert", file, context); + if (insert_endlines) { + GlobalReplaceSubstring(",", ",\n", &content); + } + if (annotate) { + auto* annotation = info.add_annotation(); + annotation->set_begin(0); + annotation->set_end(content.size()); + annotation->set_source_file("first_path"); + } + std::unique_ptr output( + context->OpenForInsertWithGeneratedCodeInfo( + GetOutputFileName(insert_into[i], file), + kFirstInsertionPointName, info)); io::Printer printer(output.get(), '$'); - printer.PrintRaw( - GetOutputFileContent(name_, "first_insert", file, context)); + printer.PrintRaw(content); if (printer.failed()) { *error = "MockCodeGenerator detected write error."; return false; @@ -248,12 +284,24 @@ bool MockCodeGenerator::Generate(const FileDescriptor* file, } { + google::protobuf::GeneratedCodeInfo info; + std::string content = + GetOutputFileContent(name_, "second_insert", file, context); + if (insert_endlines) { + GlobalReplaceSubstring(",", ",\n", &content); + } + if (annotate) { + auto* annotation = info.add_annotation(); + annotation->set_begin(0); + annotation->set_end(content.size()); + annotation->set_source_file("second_path"); + } std::unique_ptr output( - context->OpenForInsert(GetOutputFileName(insert_into[i], file), - kSecondInsertionPointName)); + context->OpenForInsertWithGeneratedCodeInfo( + GetOutputFileName(insert_into[i], file), + kSecondInsertionPointName, info)); io::Printer printer(output.get(), '$'); - printer.PrintRaw( - GetOutputFileContent(name_, "second_insert", file, context)); + printer.PrintRaw(content); if (printer.failed()) { *error = "MockCodeGenerator detected write error."; return false; @@ -272,17 +320,17 @@ bool MockCodeGenerator::Generate(const FileDescriptor* file, printer.PrintRaw(GetOutputFileContent(name_, parameter, file, context)); std::string annotate_suffix = "_annotation"; if (annotate) { - printer.Print("$p$", "p", "first"); + printer.Print("$p$\n", "p", "first"); printer.Annotate("p", "first" + annotate_suffix); } printer.PrintRaw(kFirstInsertionPoint); if (annotate) { - printer.Print("$p$", "p", "second"); + printer.Print("$p$\n", "p", "second"); printer.Annotate("p", "second" + annotate_suffix); } printer.PrintRaw(kSecondInsertionPoint); if (annotate) { - printer.Print("$p$", "p", "third"); + printer.Print("$p$\n", "p", "third"); printer.Annotate("p", "third" + annotate_suffix); } @@ -292,9 +340,9 @@ bool MockCodeGenerator::Generate(const FileDescriptor* file, } if (annotate) { std::unique_ptr meta_output( - context->Open(GetOutputFileName(name_, file) + ".meta")); + context->Open(GetOutputFileName(name_, file) + ".pb.meta")); if (!TextFormat::Print(annotations, meta_output.get())) { - *error = "MockCodeGenerator couldn't write .meta"; + *error = "MockCodeGenerator couldn't write .pb.meta"; return false; } } diff --git a/src/google/protobuf/compiler/mock_code_generator.h b/src/google/protobuf/compiler/mock_code_generator.h index 9a72258694..9677d1904d 100644 --- a/src/google/protobuf/compiler/mock_code_generator.h +++ b/src/google/protobuf/compiler/mock_code_generator.h @@ -56,7 +56,9 @@ namespace compiler { // If the parameter is "insert=NAMES", the MockCodeGenerator will insert lines // into the files generated by other MockCodeGenerators instead of creating // its own file. NAMES is a comma-separated list of the names of those other -// MockCodeGenerators. +// MockCodeGenerators. If the parameter is "insert_endlines=NAMES", the +// MockCodeGenerator will insert data guaranteed to contain more than one +// endline into the files generated by NAMES. // // MockCodeGenerator will also modify its behavior slightly if the input file // contains a message type with one of the following names: diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc index 58ca9c195b..ce4a12c987 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc @@ -421,7 +421,7 @@ void FileGenerator::GenerateSource(io::Printer *printer) { "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n"); if (includes_oneof) { // The generated code for oneof's uses direct ivar access, suppress the - // warning incase developer turn that on in the context they compile the + // warning in case developer turn that on in the context they compile the // generated code. printer->Print( "#pragma clang diagnostic ignored \"-Wdirect-ivar-access\"\n"); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc index 257e4f9abc..a1a6f529e4 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc @@ -29,12 +29,12 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include #include #include #include #include #include -#include namespace google { namespace protobuf { @@ -93,8 +93,11 @@ bool ObjectiveCGenerator::GenerateAll(const std::vector& // A semicolon delimited string that lists the paths of .proto files to // exclude from the package prefix validations (expected_prefixes_path). // This is provided as an "out", to skip some files being checked. - SplitStringUsing(options[i].second, ";", - &generation_options.expected_prefixes_suppressions); + for (StringPiece split_piece : Split( + options[i].second, ";", true)) { + generation_options.expected_prefixes_suppressions.push_back( + std::string(split_piece)); + } } else if (options[i].first == "generate_for_named_framework") { // The name of the framework that protos are being generated for. This // will cause the #import statements to be framework based using this @@ -120,7 +123,7 @@ bool ObjectiveCGenerator::GenerateAll(const std::vector& // Any number of files can be listed for a framework, just separate them // with commas. // - // There can be multiple lines listing the same frameworkName incase it + // There can be multiple lines listing the same frameworkName in case it // has a lot of proto files included in it; having multiple lines makes // things easier to read. If a proto file is not configured in the // mappings file, it will use the default framework name if one was passed diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc index 8b2b719e03..77fe084b73 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc @@ -78,7 +78,8 @@ Options::Options() { } const char* suppressions = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES_SUPPRESSIONS"); if (suppressions) { - SplitStringUsing(suppressions, ";", &expected_prefixes_suppressions); + expected_prefixes_suppressions = + Split(suppressions, ";", true); } } diff --git a/src/google/protobuf/compiler/php/php_generator.cc b/src/google/protobuf/compiler/php/php_generator.cc index 4a6206a0f2..365cb64e53 100644 --- a/src/google/protobuf/compiler/php/php_generator.cc +++ b/src/google/protobuf/compiler/php/php_generator.cc @@ -624,21 +624,17 @@ void GenerateField(const FieldDescriptor* field, io::Printer* printer, printer->Print( "private $^name^;\n", "name", field->name()); - } else if (field->containing_oneof()) { + } else if (field->real_containing_oneof()) { // Oneof fields are handled by GenerateOneofField. return; } else { + std::string initial_value = + field->has_presence() ? "null" : DefaultForField(field); GenerateFieldDocComment(printer, field, is_descriptor, kFieldProperty); printer->Print( - "protected $^name^ = ^default^;\n", + "protected $^name^ = ^initial_value^;\n", "name", field->name(), - "default", DefaultForField(field)); - } - - if (is_descriptor) { - printer->Print( - "private $has_^name^ = false;\n", - "name", field->name()); + "initial_value", initial_value); } } @@ -652,20 +648,41 @@ void GenerateOneofField(const OneofDescriptor* oneof, io::Printer* printer) { void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor, io::Printer* printer) { - const OneofDescriptor* oneof = field->containing_oneof(); + const OneofDescriptor* oneof = field->real_containing_oneof(); // Generate getter. + GenerateFieldDocComment(printer, field, is_descriptor, kFieldGetter); + if (oneof != NULL) { - GenerateFieldDocComment(printer, field, is_descriptor, kFieldGetter); printer->Print( "public function get^camel_name^()\n" "{\n" " return $this->readOneof(^number^);\n" + "}\n\n" + "public function has^camel_name^()\n" + "{\n" + " return $this->hasOneof(^number^);\n" "}\n\n", "camel_name", UnderscoresToCamelCase(field->name(), true), "number", IntToString(field->number())); + } else if (field->has_presence()) { + printer->Print( + "public function get^camel_name^()\n" + "{\n" + " return isset($this->^name^) ? $this->^name^ : ^default_value^;\n" + "}\n\n" + "public function has^camel_name^()\n" + "{\n" + " return isset($this->^name^);\n" + "}\n\n" + "public function clear^camel_name^()\n" + "{\n" + " unset($this->^name^);\n" + "}\n\n", + "camel_name", UnderscoresToCamelCase(field->name(), true), + "name", field->name(), + "default_value", DefaultForField(field)); } else { - GenerateFieldDocComment(printer, field, is_descriptor, kFieldGetter); printer->Print( "public function get^camel_name^()\n" "{\n" @@ -774,13 +791,6 @@ void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor, "name", field->name()); } - // Set has bit for proto2 only. - if (is_descriptor) { - printer->Print( - "$this->has_^field_name^ = true;\n", - "field_name", field->name()); - } - printer->Print("\nreturn $this;\n"); Outdent(printer); @@ -803,17 +813,6 @@ void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor, "camel_name", UnderscoresToCamelCase(field->name(), true), "field_name", field->name()); } - - // Generate has method for proto2 only. - if (is_descriptor) { - printer->Print( - "public function has^camel_name^()\n" - "{\n" - " return $this->has_^field_name^;\n" - "}\n\n", - "camel_name", UnderscoresToCamelCase(field->name(), true), - "field_name", field->name()); - } } void GenerateEnumToPool(const EnumDescriptor* en, io::Printer* printer) { @@ -878,7 +877,7 @@ void GenerateMessageToPool(const string& name_prefix, const Descriptor* message, "value", ToUpper(val->type_name()), "number", StrCat(field->number()), "other", EnumOrMessageSuffix(val, true)); - } else if (!field->containing_oneof()) { + } else if (!field->real_containing_oneof()) { printer->Print( "->^label^('^field^', " "\\Google\\Protobuf\\Internal\\GPBType::^type^, ^number^^other^)\n", @@ -891,7 +890,7 @@ void GenerateMessageToPool(const string& name_prefix, const Descriptor* message, } // oneofs. - for (int i = 0; i < message->oneof_decl_count(); i++) { + for (int i = 0; i < message->real_oneof_decl_count(); i++) { const OneofDescriptor* oneof = message->oneof_decl(i); printer->Print("->oneof(^name^)\n", "name", oneof->name()); @@ -1414,7 +1413,7 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message, const FieldDescriptor* field = message->field(i); GenerateField(field, &printer, is_descriptor); } - for (int i = 0; i < message->oneof_decl_count(); i++) { + for (int i = 0; i < message->real_oneof_decl_count(); i++) { const OneofDescriptor* oneof = message->oneof_decl(i); GenerateOneofField(oneof, &printer); } @@ -1443,7 +1442,7 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message, const FieldDescriptor* field = message->field(i); GenerateFieldAccessor(field, is_descriptor, &printer); } - for (int i = 0; i < message->oneof_decl_count(); i++) { + for (int i = 0; i < message->real_oneof_decl_count(); i++) { const OneofDescriptor* oneof = message->oneof_decl(i); printer.Print( "/**\n" diff --git a/src/google/protobuf/compiler/php/php_generator.h b/src/google/protobuf/compiler/php/php_generator.h index ca9d23a46a..f67bb40417 100644 --- a/src/google/protobuf/compiler/php/php_generator.h +++ b/src/google/protobuf/compiler/php/php_generator.h @@ -55,6 +55,11 @@ class PROTOC_EXPORT Generator : public CodeGenerator { const std::string& parameter, GeneratorContext* generator_context, std::string* error) const override; + + uint64_t GetSupportedFeatures() const override { + return FEATURE_PROTO3_OPTIONAL; + } + private: bool Generate( const FileDescriptor* file, diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc index 7306cf4449..cb7801d53c 100644 --- a/src/google/protobuf/compiler/plugin.cc +++ b/src/google/protobuf/compiler/plugin.cc @@ -86,6 +86,16 @@ class GeneratorResponseContext : public GeneratorContext { return new io::StringOutputStream(file->mutable_content()); } + virtual io::ZeroCopyOutputStream* OpenForInsertWithGeneratedCodeInfo( + const std::string& filename, const std::string& insertion_point, + const google::protobuf::GeneratedCodeInfo& info) { + CodeGeneratorResponse::File* file = response_->add_file(); + file->set_name(filename); + file->set_insertion_point(insertion_point); + *file->mutable_generated_code_info() = info; + return new io::StringOutputStream(file->mutable_content()); + } + void ListParsedFiles(std::vector* output) { *output = parsed_files_; } diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index c2e430acda..2b39bc40e3 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -15,7 +15,8 @@ // @@protoc_insertion_point(includes) #include 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_2fcompiler_2fplugin_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_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 { @@ -45,7 +46,6 @@ static void InitDefaultsscc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompil new (ptr) PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest::InitAsDefaultInstance(); } PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto = @@ -61,7 +61,6 @@ static void InitDefaultsscc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompi new (ptr) PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse::InitAsDefaultInstance(); } PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto = @@ -76,11 +75,11 @@ static void InitDefaultsscc_info_CodeGeneratorResponse_File_google_2fprotobuf_2f new (ptr) PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File::InitAsDefaultInstance(); } -PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto = - {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto}, {}}; +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; @@ -90,7 +89,6 @@ static void InitDefaultsscc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2 new (ptr) PROTOBUF_NAMESPACE_ID::compiler::Version(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::compiler::Version::InitAsDefaultInstance(); } PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto = @@ -135,9 +133,11 @@ const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fcompiler_2 PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, name_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, insertion_point_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, content_), + PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, generated_code_info_), 0, 1, 2, + 3, PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _has_bits_), PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _internal_metadata_), ~0u, // no _extensions_ @@ -153,8 +153,8 @@ const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fcompiler_2 static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { { 0, 9, sizeof(PROTOBUF_NAMESPACE_ID::compiler::Version)}, { 13, 22, sizeof(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest)}, - { 26, 34, sizeof(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File)}, - { 37, 45, sizeof(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse)}, + { 26, 35, sizeof(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File)}, + { 39, 47, sizeof(PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse)}, }; static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { @@ -174,15 +174,17 @@ const char descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2epro "\t\0228\n\nproto_file\030\017 \003(\0132$.google.protobuf." "FileDescriptorProto\022;\n\020compiler_version\030" "\003 \001(\0132!.google.protobuf.compiler.Version" - "\"\200\002\n\025CodeGeneratorResponse\022\r\n\005error\030\001 \001(" + "\"\301\002\n\025CodeGeneratorResponse\022\r\n\005error\030\001 \001(" "\t\022\032\n\022supported_features\030\002 \001(\004\022B\n\004file\030\017 " "\003(\01324.google.protobuf.compiler.CodeGener" - "atorResponse.File\032>\n\004File\022\014\n\004name\030\001 \001(\t\022" + "atorResponse.File\032\177\n\004File\022\014\n\004name\030\001 \001(\t\022" "\027\n\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(" - "\t\"8\n\007Feature\022\020\n\014FEATURE_NONE\020\000\022\033\n\027FEATUR" - "E_PROTO3_OPTIONAL\020\001BW\n\034com.google.protob" - "uf.compilerB\014PluginProtosZ)google.golang" - ".org/protobuf/types/pluginpb" + "\t\022\?\n\023generated_code_info\030\020 \001(\0132\".google." + "protobuf.GeneratedCodeInfo\"8\n\007Feature\022\020\n" + "\014FEATURE_NONE\020\000\022\033\n\027FEATURE_PROTO3_OPTION" + "AL\020\001BW\n\034com.google.protobuf.compilerB\014Pl" + "uginProtosZ)google.golang.org/protobuf/t" + "ypes/pluginpb" ; static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps[1] = { &::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, @@ -195,7 +197,7 @@ static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_goo }; 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", 708, + 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, 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, @@ -229,8 +231,6 @@ constexpr int CodeGeneratorResponse::Feature_ARRAYSIZE; // =================================================================== -void Version::InitAsDefaultInstance() { -} class Version::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -558,10 +558,6 @@ void Version::InternalSwap(Version* other) { // =================================================================== -void CodeGeneratorRequest::InitAsDefaultInstance() { - PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorRequest_default_instance_._instance.get_mutable()->compiler_version_ = const_cast< PROTOBUF_NAMESPACE_ID::compiler::Version*>( - PROTOBUF_NAMESPACE_ID::compiler::Version::internal_default_instance()); -} class CodeGeneratorRequest::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -912,8 +908,6 @@ void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) { // =================================================================== -void CodeGeneratorResponse_File::InitAsDefaultInstance() { -} class CodeGeneratorResponse_File::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -926,8 +920,20 @@ class CodeGeneratorResponse_File::_Internal { static void set_has_content(HasBits* has_bits) { (*has_bits)[0] |= 4u; } + static const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& generated_code_info(const CodeGeneratorResponse_File* msg); + static void set_has_generated_code_info(HasBits* has_bits) { + (*has_bits)[0] |= 8u; + } }; +const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& +CodeGeneratorResponse_File::_Internal::generated_code_info(const CodeGeneratorResponse_File* msg) { + return *msg->generated_code_info_; +} +void CodeGeneratorResponse_File::clear_generated_code_info() { + if (generated_code_info_ != nullptr) generated_code_info_->Clear(); + _has_bits_[0] &= ~0x00000008u; +} CodeGeneratorResponse_File::CodeGeneratorResponse_File(::PROTOBUF_NAMESPACE_ID::Arena* arena) : ::PROTOBUF_NAMESPACE_ID::Message(arena) { SharedCtor(); @@ -953,6 +959,11 @@ CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorRespon content_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_content(), GetArena()); } + if (from._internal_has_generated_code_info()) { + generated_code_info_ = new PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo(*from.generated_code_info_); + } else { + generated_code_info_ = nullptr; + } // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse.File) } @@ -961,6 +972,7 @@ void CodeGeneratorResponse_File::SharedCtor() { 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() { @@ -974,6 +986,7 @@ void CodeGeneratorResponse_File::SharedDtor() { name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); insertion_point_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); content_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (this != internal_default_instance()) delete generated_code_info_; } void CodeGeneratorResponse_File::ArenaDtor(void* object) { @@ -998,7 +1011,7 @@ void CodeGeneratorResponse_File::Clear() { (void) cached_has_bits; cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 0x00000007u) { + if (cached_has_bits & 0x0000000fu) { if (cached_has_bits & 0x00000001u) { name_.ClearNonDefaultToEmpty(); } @@ -1008,6 +1021,10 @@ void CodeGeneratorResponse_File::Clear() { if (cached_has_bits & 0x00000004u) { content_.ClearNonDefaultToEmpty(); } + if (cached_has_bits & 0x00000008u) { + GOOGLE_DCHECK(generated_code_info_ != nullptr); + generated_code_info_->Clear(); + } } _has_bits_.Clear(); _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); @@ -1055,6 +1072,13 @@ const char* CodeGeneratorResponse_File::_InternalParse(const char* ptr, ::PROTOB CHK_(ptr); } else goto handle_unusual; continue; + // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16; + case 16: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 130)) { + ptr = ctx->ParseMessage(_internal_mutable_generated_code_info(), ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; default: { handle_unusual: if ((tag & 7) == 4 || tag == 0) { @@ -1115,6 +1139,14 @@ failure: 15, this->_internal_content(), target); } + // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16; + if (cached_has_bits & 0x00000008u) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage( + 16, _Internal::generated_code_info(this), target, stream); + } + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); @@ -1132,7 +1164,7 @@ size_t CodeGeneratorResponse_File::ByteSizeLong() const { (void) cached_has_bits; cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 0x00000007u) { + if (cached_has_bits & 0x0000000fu) { // optional string name = 1; if (cached_has_bits & 0x00000001u) { total_size += 1 + @@ -1154,6 +1186,13 @@ size_t CodeGeneratorResponse_File::ByteSizeLong() const { this->_internal_content()); } + // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16; + if (cached_has_bits & 0x00000008u) { + total_size += 2 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *generated_code_info_); + } + } if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( @@ -1187,7 +1226,7 @@ void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& fro (void) cached_has_bits; cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 0x00000007u) { + if (cached_has_bits & 0x0000000fu) { if (cached_has_bits & 0x00000001u) { _internal_set_name(from._internal_name()); } @@ -1197,6 +1236,9 @@ void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& fro if (cached_has_bits & 0x00000004u) { _internal_set_content(from._internal_content()); } + if (cached_has_bits & 0x00000008u) { + _internal_mutable_generated_code_info()->PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo::MergeFrom(from._internal_generated_code_info()); + } } } @@ -1225,6 +1267,7 @@ void CodeGeneratorResponse_File::InternalSwap(CodeGeneratorResponse_File* other) name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); insertion_point_.Swap(&other->insertion_point_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); content_.Swap(&other->content_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + swap(generated_code_info_, other->generated_code_info_); } ::PROTOBUF_NAMESPACE_ID::Metadata CodeGeneratorResponse_File::GetMetadata() const { @@ -1234,8 +1277,6 @@ void CodeGeneratorResponse_File::InternalSwap(CodeGeneratorResponse_File* other) // =================================================================== -void CodeGeneratorResponse::InitAsDefaultInstance() { -} class CodeGeneratorResponse::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h index 77d45ebfad..8ee850de61 100644 --- a/src/google/protobuf/compiler/plugin.pb.h +++ b/src/google/protobuf/compiler/plugin.pb.h @@ -155,7 +155,6 @@ class PROTOC_EXPORT Version PROTOBUF_FINAL : } static const Version& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const Version* internal_default_instance() { return reinterpret_cast( &_Version_default_instance_); @@ -356,7 +355,6 @@ class PROTOC_EXPORT CodeGeneratorRequest PROTOBUF_FINAL : } static const CodeGeneratorRequest& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const CodeGeneratorRequest* internal_default_instance() { return reinterpret_cast( &_CodeGeneratorRequest_default_instance_); @@ -578,7 +576,6 @@ class PROTOC_EXPORT CodeGeneratorResponse_File PROTOBUF_FINAL : } static const CodeGeneratorResponse_File& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const CodeGeneratorResponse_File* internal_default_instance() { return reinterpret_cast( &_CodeGeneratorResponse_File_default_instance_); @@ -658,6 +655,7 @@ class PROTOC_EXPORT CodeGeneratorResponse_File PROTOBUF_FINAL : kNameFieldNumber = 1, kInsertionPointFieldNumber = 2, kContentFieldNumber = 15, + kGeneratedCodeInfoFieldNumber = 16, }; // optional string name = 1; bool has_name() const; @@ -719,6 +717,24 @@ class PROTOC_EXPORT CodeGeneratorResponse_File PROTOBUF_FINAL : std::string* _internal_mutable_content(); public: + // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16; + bool has_generated_code_info() const; + private: + bool _internal_has_generated_code_info() const; + public: + void clear_generated_code_info(); + const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& generated_code_info() const; + PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* release_generated_code_info(); + PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* mutable_generated_code_info(); + void set_allocated_generated_code_info(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info); + private: + const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& _internal_generated_code_info() const; + PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* _internal_mutable_generated_code_info(); + public: + void unsafe_arena_set_allocated_generated_code_info( + PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info); + PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* unsafe_arena_release_generated_code_info(); + // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File) private: class _Internal; @@ -731,6 +747,7 @@ class PROTOC_EXPORT CodeGeneratorResponse_File PROTOBUF_FINAL : ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr insertion_point_; ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr content_; + PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info_; friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto; }; // ------------------------------------------------------------------- @@ -778,7 +795,6 @@ class PROTOC_EXPORT CodeGeneratorResponse PROTOBUF_FINAL : } static const CodeGeneratorResponse& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const CodeGeneratorResponse* internal_default_instance() { return reinterpret_cast( &_CodeGeneratorResponse_default_instance_); @@ -1328,8 +1344,8 @@ inline void CodeGeneratorRequest::clear_compiler_version() { } inline const PROTOBUF_NAMESPACE_ID::compiler::Version& CodeGeneratorRequest::_internal_compiler_version() const { const PROTOBUF_NAMESPACE_ID::compiler::Version* p = compiler_version_; - return p != nullptr ? *p : *reinterpret_cast( - &PROTOBUF_NAMESPACE_ID::compiler::_Version_default_instance_); + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::compiler::_Version_default_instance_); } inline const PROTOBUF_NAMESPACE_ID::compiler::Version& CodeGeneratorRequest::compiler_version() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.compiler_version) @@ -1622,6 +1638,85 @@ inline void CodeGeneratorResponse_File::set_allocated_content(std::string* conte // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content) } +// optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16; +inline bool CodeGeneratorResponse_File::_internal_has_generated_code_info() const { + bool value = (_has_bits_[0] & 0x00000008u) != 0; + PROTOBUF_ASSUME(!value || generated_code_info_ != nullptr); + return value; +} +inline bool CodeGeneratorResponse_File::has_generated_code_info() const { + return _internal_has_generated_code_info(); +} +inline const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& CodeGeneratorResponse_File::_internal_generated_code_info() const { + const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* p = generated_code_info_; + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_GeneratedCodeInfo_default_instance_); +} +inline const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& CodeGeneratorResponse_File::generated_code_info() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info) + return _internal_generated_code_info(); +} +inline void CodeGeneratorResponse_File::unsafe_arena_set_allocated_generated_code_info( + PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info) { + if (GetArena() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(generated_code_info_); + } + generated_code_info_ = generated_code_info; + if (generated_code_info) { + _has_bits_[0] |= 0x00000008u; + } else { + _has_bits_[0] &= ~0x00000008u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info) +} +inline PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* CodeGeneratorResponse_File::release_generated_code_info() { + _has_bits_[0] &= ~0x00000008u; + PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* temp = generated_code_info_; + generated_code_info_ = nullptr; + if (GetArena() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } + return temp; +} +inline PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* CodeGeneratorResponse_File::unsafe_arena_release_generated_code_info() { + // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info) + _has_bits_[0] &= ~0x00000008u; + PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* temp = generated_code_info_; + generated_code_info_ = nullptr; + return temp; +} +inline PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* CodeGeneratorResponse_File::_internal_mutable_generated_code_info() { + _has_bits_[0] |= 0x00000008u; + if (generated_code_info_ == nullptr) { + auto* p = CreateMaybeMessage(GetArena()); + generated_code_info_ = p; + } + return generated_code_info_; +} +inline PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* CodeGeneratorResponse_File::mutable_generated_code_info() { + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info) + return _internal_mutable_generated_code_info(); +} +inline void CodeGeneratorResponse_File::set_allocated_generated_code_info(PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena(); + if (message_arena == nullptr) { + delete reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::MessageLite*>(generated_code_info_); + } + if (generated_code_info) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(generated_code_info)->GetArena(); + if (message_arena != submessage_arena) { + generated_code_info = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, generated_code_info, submessage_arena); + } + _has_bits_[0] |= 0x00000008u; + } else { + _has_bits_[0] &= ~0x00000008u; + } + generated_code_info_ = generated_code_info; + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info) +} + // ------------------------------------------------------------------- // CodeGeneratorResponse diff --git a/src/google/protobuf/compiler/plugin.proto b/src/google/protobuf/compiler/plugin.proto index 189db19429..9242aacc5b 100644 --- a/src/google/protobuf/compiler/plugin.proto +++ b/src/google/protobuf/compiler/plugin.proto @@ -173,6 +173,11 @@ message CodeGeneratorResponse { // The file contents. optional string content = 15; + + // Information describing the file content being inserted. If an insertion + // point is used, this information will be appropriately offset and inserted + // into the code generation metadata for the generated files. + optional GeneratedCodeInfo generated_code_info = 16; } repeated File file = 15; } diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc index cf61d9995a..ebc972c148 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -113,7 +113,7 @@ std::string TypeName(const FieldDescriptor* field) { } } -string StringifySyntax(FileDescriptor::Syntax syntax) { +std::string StringifySyntax(FileDescriptor::Syntax syntax) { switch (syntax) { case FileDescriptor::SYNTAX_PROTO2: return "proto2"; @@ -147,7 +147,7 @@ std::string DefaultValueForField(const FieldDescriptor* field) { return NumberToString(field->default_value_enum()->number()); case FieldDescriptor::CPPTYPE_STRING: { std::ostringstream os; - string default_str = field->default_value_string(); + std::string default_str = field->default_value_string(); if (field->type() == FieldDescriptor::TYPE_STRING) { os << "\"" << default_str << "\""; @@ -413,7 +413,7 @@ int GeneratePackageModules(const FileDescriptor* file, io::Printer* printer) { // If :: is in the package use the Ruby formatted name as-is // -> A::B::C - // otherwise, use the dot seperator + // otherwise, use the dot separator // -> A.B.C if (package_name.find("::") != std::string::npos) { need_change_to_module = false; @@ -426,14 +426,14 @@ int GeneratePackageModules(const FileDescriptor* file, io::Printer* printer) { } // Use the appropriate delimiter - string delimiter = need_change_to_module ? "." : "::"; + std::string delimiter = need_change_to_module ? "." : "::"; int delimiter_size = need_change_to_module ? 1 : 2; // Extract each module name and indent while (!package_name.empty()) { size_t dot_index = package_name.find(delimiter); - string component; - if (dot_index == string::npos) { + std::string component; + if (dot_index == std::string::npos) { component = package_name; package_name = ""; } else { @@ -462,7 +462,7 @@ void EndPackageModules(int levels, io::Printer* printer) { } bool UsesTypeFromFile(const Descriptor* message, const FileDescriptor* file, - string* error) { + std::string* error) { for (int i = 0; i < message->field_count(); i++) { const FieldDescriptor* field = message->field(i); if ((field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && @@ -499,7 +499,7 @@ bool UsesTypeFromFile(const Descriptor* message, const FileDescriptor* file, bool MaybeEmitDependency(const FileDescriptor* import, const FileDescriptor* from, io::Printer* printer, - string* error) { + std::string* error) { if (from->syntax() == FileDescriptor::SYNTAX_PROTO3 && import->syntax() == FileDescriptor::SYNTAX_PROTO2) { for (int i = 0; i < from->message_type_count(); i++) { @@ -524,7 +524,7 @@ bool MaybeEmitDependency(const FileDescriptor* import, } bool GenerateFile(const FileDescriptor* file, io::Printer* printer, - string* error) { + std::string* error) { printer->Print( "# Generated by the protocol buffer compiler. DO NOT EDIT!\n" "# source: $filename$\n" @@ -580,9 +580,9 @@ bool GenerateFile(const FileDescriptor* file, io::Printer* printer, bool Generator::Generate( const FileDescriptor* file, - const string& parameter, + const std::string& parameter, GeneratorContext* generator_context, - string* error) const { + std::string* error) const { if (file->syntax() != FileDescriptor::SYNTAX_PROTO3 && file->syntax() != FileDescriptor::SYNTAX_PROTO2) { diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.h b/src/google/protobuf/compiler/ruby/ruby_generator.h index b40fcd01dd..647bb83606 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.h +++ b/src/google/protobuf/compiler/ruby/ruby_generator.h @@ -49,9 +49,9 @@ namespace ruby { // Ruby output, you can do so by registering an instance of this // CodeGenerator with the CommandLineInterface in your main() function. class PROTOC_EXPORT Generator : public CodeGenerator { - bool Generate(const FileDescriptor* file, const string& parameter, + bool Generate(const FileDescriptor* file, const std::string& parameter, GeneratorContext* generator_context, - string* error) const override; + std::string* error) const override; uint64_t GetSupportedFeatures() const override { return FEATURE_PROTO3_OPTIONAL; } @@ -65,4 +65,3 @@ class PROTOC_EXPORT Generator : public CodeGenerator { #include #endif // GOOGLE_PROTOBUF_COMPILER_RUBY_GENERATOR_H__ - diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc index 9a448ffc80..8fb9671896 100644 --- a/src/google/protobuf/descriptor.cc +++ b/src/google/protobuf/descriptor.cc @@ -2723,7 +2723,7 @@ void FieldDescriptor::DebugString( if (has_json_name_) { if (!bracketed) { bracketed = true; - contents->append("["); + contents->append(" ["); } else { contents->append(", "); } @@ -4883,6 +4883,7 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, DescriptorPool::ErrorCollector::DEFAULT_VALUE, "Messages can't have default values."); result->has_default_value_ = false; + result->default_generated_instance_ = nullptr; break; } @@ -4929,6 +4930,7 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, result->default_value_string_ = &internal::GetEmptyString(); break; case FieldDescriptor::CPPTYPE_MESSAGE: + result->default_generated_instance_ = nullptr; break; } } diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h index 078f24a68b..5bfecf5089 100644 --- a/src/google/protobuf/descriptor.h +++ b/src/google/protobuf/descriptor.h @@ -54,6 +54,7 @@ #ifndef GOOGLE_PROTOBUF_DESCRIPTOR_H__ #define GOOGLE_PROTOBUF_DESCRIPTOR_H__ +#include #include #include #include @@ -839,6 +840,7 @@ class PROTOBUF_EXPORT FieldDescriptor { // Allows access to GetLocationPath for annotations. friend class io::Printer; friend class compiler::cpp::Formatter; + friend class Reflection; // Fill the json_name field of FieldDescriptorProto. void CopyJsonNameTo(FieldDescriptorProto* proto) const; @@ -906,6 +908,7 @@ class PROTOBUF_EXPORT FieldDescriptor { mutable const EnumValueDescriptor* default_value_enum_; const std::string* default_value_string_; + mutable std::atomic default_generated_instance_; }; static const CppType kTypeToCppTypeMap[MAX_TYPE + 1]; @@ -1235,6 +1238,7 @@ class PROTOBUF_EXPORT EnumValueDescriptor { friend class EnumDescriptor; friend class DescriptorPool; friend class FileDescriptorTables; + friend class Reflection; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumValueDescriptor); }; @@ -1857,7 +1861,7 @@ class PROTOBUF_EXPORT DescriptorPool { // Delay the building of dependencies of a file descriptor until absolutely // necessary, like when message_type() is called on a field that is defined // in that dependency's file. This will cause functional issues if a proto - // or one of it's dependencies has errors. Should only be enabled for the + // or one of its dependencies has errors. Should only be enabled for the // generated_pool_ (because no descriptor build errors are guaranteed by // the compilation generation process), testing, or if a lack of descriptor // build errors can be guaranteed for a pool. diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index c4e26b6c8c..e3eba97fcd 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -157,7 +157,6 @@ static void InitDefaultsscc_info_DescriptorProto_google_2fprotobuf_2fdescriptor_ new (ptr) PROTOBUF_NAMESPACE_ID::DescriptorProto(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::DescriptorProto::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<6> scc_info_DescriptorProto_google_2fprotobuf_2fdescriptor_2eproto = @@ -177,7 +176,6 @@ static void InitDefaultsscc_info_DescriptorProto_ExtensionRange_google_2fprotobu new (ptr) PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_DescriptorProto_ExtensionRange_google_2fprotobuf_2fdescriptor_2eproto = @@ -192,7 +190,6 @@ static void InitDefaultsscc_info_DescriptorProto_ReservedRange_google_2fprotobuf new (ptr) PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_DescriptorProto_ReservedRange_google_2fprotobuf_2fdescriptor_2eproto = @@ -206,7 +203,6 @@ static void InitDefaultsscc_info_EnumDescriptorProto_google_2fprotobuf_2fdescrip new (ptr) PROTOBUF_NAMESPACE_ID::EnumDescriptorProto(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::EnumDescriptorProto::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<3> scc_info_EnumDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto = @@ -223,7 +219,6 @@ static void InitDefaultsscc_info_EnumDescriptorProto_EnumReservedRange_google_2f new (ptr) PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_EnumDescriptorProto_EnumReservedRange_google_2fprotobuf_2fdescriptor_2eproto = @@ -237,7 +232,6 @@ static void InitDefaultsscc_info_EnumOptions_google_2fprotobuf_2fdescriptor_2epr new (ptr) PROTOBUF_NAMESPACE_ID::EnumOptions(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::EnumOptions::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_EnumOptions_google_2fprotobuf_2fdescriptor_2eproto = @@ -252,7 +246,6 @@ static void InitDefaultsscc_info_EnumValueDescriptorProto_google_2fprotobuf_2fde new (ptr) PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_EnumValueDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto = @@ -267,7 +260,6 @@ static void InitDefaultsscc_info_EnumValueOptions_google_2fprotobuf_2fdescriptor new (ptr) PROTOBUF_NAMESPACE_ID::EnumValueOptions(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::EnumValueOptions::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_EnumValueOptions_google_2fprotobuf_2fdescriptor_2eproto = @@ -282,7 +274,6 @@ static void InitDefaultsscc_info_ExtensionRangeOptions_google_2fprotobuf_2fdescr new (ptr) PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_ExtensionRangeOptions_google_2fprotobuf_2fdescriptor_2eproto = @@ -297,7 +288,6 @@ static void InitDefaultsscc_info_FieldDescriptorProto_google_2fprotobuf_2fdescri new (ptr) PROTOBUF_NAMESPACE_ID::FieldDescriptorProto(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::FieldDescriptorProto::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_FieldDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto = @@ -312,7 +302,6 @@ static void InitDefaultsscc_info_FieldOptions_google_2fprotobuf_2fdescriptor_2ep new (ptr) PROTOBUF_NAMESPACE_ID::FieldOptions(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::FieldOptions::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_FieldOptions_google_2fprotobuf_2fdescriptor_2eproto = @@ -327,7 +316,6 @@ static void InitDefaultsscc_info_FileDescriptorProto_google_2fprotobuf_2fdescrip new (ptr) PROTOBUF_NAMESPACE_ID::FileDescriptorProto(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::FileDescriptorProto::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<6> scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto = @@ -347,7 +335,6 @@ static void InitDefaultsscc_info_FileDescriptorSet_google_2fprotobuf_2fdescripto new (ptr) PROTOBUF_NAMESPACE_ID::FileDescriptorSet(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::FileDescriptorSet::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_FileDescriptorSet_google_2fprotobuf_2fdescriptor_2eproto = @@ -362,7 +349,6 @@ static void InitDefaultsscc_info_FileOptions_google_2fprotobuf_2fdescriptor_2epr new (ptr) PROTOBUF_NAMESPACE_ID::FileOptions(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::FileOptions::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_FileOptions_google_2fprotobuf_2fdescriptor_2eproto = @@ -377,7 +363,6 @@ static void InitDefaultsscc_info_GeneratedCodeInfo_google_2fprotobuf_2fdescripto new (ptr) PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_GeneratedCodeInfo_google_2fprotobuf_2fdescriptor_2eproto = @@ -392,7 +377,6 @@ static void InitDefaultsscc_info_GeneratedCodeInfo_Annotation_google_2fprotobuf_ new (ptr) PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_GeneratedCodeInfo_Annotation_google_2fprotobuf_2fdescriptor_2eproto = @@ -406,7 +390,6 @@ static void InitDefaultsscc_info_MessageOptions_google_2fprotobuf_2fdescriptor_2 new (ptr) PROTOBUF_NAMESPACE_ID::MessageOptions(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::MessageOptions::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_MessageOptions_google_2fprotobuf_2fdescriptor_2eproto = @@ -421,7 +404,6 @@ static void InitDefaultsscc_info_MethodDescriptorProto_google_2fprotobuf_2fdescr new (ptr) PROTOBUF_NAMESPACE_ID::MethodDescriptorProto(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::MethodDescriptorProto::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_MethodDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto = @@ -436,7 +418,6 @@ static void InitDefaultsscc_info_MethodOptions_google_2fprotobuf_2fdescriptor_2e new (ptr) PROTOBUF_NAMESPACE_ID::MethodOptions(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::MethodOptions::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_MethodOptions_google_2fprotobuf_2fdescriptor_2eproto = @@ -451,7 +432,6 @@ static void InitDefaultsscc_info_OneofDescriptorProto_google_2fprotobuf_2fdescri new (ptr) PROTOBUF_NAMESPACE_ID::OneofDescriptorProto(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::OneofDescriptorProto::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_OneofDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto = @@ -466,7 +446,6 @@ static void InitDefaultsscc_info_OneofOptions_google_2fprotobuf_2fdescriptor_2ep new (ptr) PROTOBUF_NAMESPACE_ID::OneofOptions(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::OneofOptions::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_OneofOptions_google_2fprotobuf_2fdescriptor_2eproto = @@ -481,7 +460,6 @@ static void InitDefaultsscc_info_ServiceDescriptorProto_google_2fprotobuf_2fdesc new (ptr) PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_ServiceDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto = @@ -497,7 +475,6 @@ static void InitDefaultsscc_info_ServiceOptions_google_2fprotobuf_2fdescriptor_2 new (ptr) PROTOBUF_NAMESPACE_ID::ServiceOptions(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::ServiceOptions::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_ServiceOptions_google_2fprotobuf_2fdescriptor_2eproto = @@ -512,7 +489,6 @@ static void InitDefaultsscc_info_SourceCodeInfo_google_2fprotobuf_2fdescriptor_2 new (ptr) PROTOBUF_NAMESPACE_ID::SourceCodeInfo(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::SourceCodeInfo::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_SourceCodeInfo_google_2fprotobuf_2fdescriptor_2eproto = @@ -527,7 +503,6 @@ static void InitDefaultsscc_info_SourceCodeInfo_Location_google_2fprotobuf_2fdes new (ptr) PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_SourceCodeInfo_Location_google_2fprotobuf_2fdescriptor_2eproto = @@ -541,7 +516,6 @@ static void InitDefaultsscc_info_UninterpretedOption_google_2fprotobuf_2fdescrip new (ptr) PROTOBUF_NAMESPACE_ID::UninterpretedOption(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::UninterpretedOption::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_UninterpretedOption_google_2fprotobuf_2fdescriptor_2eproto = @@ -556,7 +530,6 @@ static void InitDefaultsscc_info_UninterpretedOption_NamePart_google_2fprotobuf_ new (ptr) PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_UninterpretedOption_NamePart_google_2fprotobuf_2fdescriptor_2eproto = @@ -1374,8 +1347,6 @@ constexpr int MethodOptions::IdempotencyLevel_ARRAYSIZE; // =================================================================== -void FileDescriptorSet::InitAsDefaultInstance() { -} class FileDescriptorSet::_Internal { public: }; @@ -1578,12 +1549,6 @@ void FileDescriptorSet::InternalSwap(FileDescriptorSet* other) { // =================================================================== -void FileDescriptorProto::InitAsDefaultInstance() { - PROTOBUF_NAMESPACE_ID::_FileDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< PROTOBUF_NAMESPACE_ID::FileOptions*>( - PROTOBUF_NAMESPACE_ID::FileOptions::internal_default_instance()); - PROTOBUF_NAMESPACE_ID::_FileDescriptorProto_default_instance_._instance.get_mutable()->source_code_info_ = const_cast< PROTOBUF_NAMESPACE_ID::SourceCodeInfo*>( - PROTOBUF_NAMESPACE_ID::SourceCodeInfo::internal_default_instance()); -} class FileDescriptorProto::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -2243,10 +2208,6 @@ void FileDescriptorProto::InternalSwap(FileDescriptorProto* other) { // =================================================================== -void DescriptorProto_ExtensionRange::InitAsDefaultInstance() { - PROTOBUF_NAMESPACE_ID::_DescriptorProto_ExtensionRange_default_instance_._instance.get_mutable()->options_ = const_cast< PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions*>( - PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions::internal_default_instance()); -} class DescriptorProto_ExtensionRange::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -2548,8 +2509,6 @@ void DescriptorProto_ExtensionRange::InternalSwap(DescriptorProto_ExtensionRange // =================================================================== -void DescriptorProto_ReservedRange::InitAsDefaultInstance() { -} class DescriptorProto_ReservedRange::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -2804,10 +2763,6 @@ void DescriptorProto_ReservedRange::InternalSwap(DescriptorProto_ReservedRange* // =================================================================== -void DescriptorProto::InitAsDefaultInstance() { - PROTOBUF_NAMESPACE_ID::_DescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< PROTOBUF_NAMESPACE_ID::MessageOptions*>( - PROTOBUF_NAMESPACE_ID::MessageOptions::internal_default_instance()); -} class DescriptorProto::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -3355,8 +3310,6 @@ void DescriptorProto::InternalSwap(DescriptorProto* other) { // =================================================================== -void ExtensionRangeOptions::InitAsDefaultInstance() { -} class ExtensionRangeOptions::_Internal { public: }; @@ -3580,10 +3533,6 @@ void ExtensionRangeOptions::InternalSwap(ExtensionRangeOptions* other) { // =================================================================== -void FieldDescriptorProto::InitAsDefaultInstance() { - PROTOBUF_NAMESPACE_ID::_FieldDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< PROTOBUF_NAMESPACE_ID::FieldOptions*>( - PROTOBUF_NAMESPACE_ID::FieldOptions::internal_default_instance()); -} class FieldDescriptorProto::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -4213,10 +4162,6 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) { // =================================================================== -void OneofDescriptorProto::InitAsDefaultInstance() { - PROTOBUF_NAMESPACE_ID::_OneofDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< PROTOBUF_NAMESPACE_ID::OneofOptions*>( - PROTOBUF_NAMESPACE_ID::OneofOptions::internal_default_instance()); -} class OneofDescriptorProto::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -4495,8 +4440,6 @@ void OneofDescriptorProto::InternalSwap(OneofDescriptorProto* other) { // =================================================================== -void EnumDescriptorProto_EnumReservedRange::InitAsDefaultInstance() { -} class EnumDescriptorProto_EnumReservedRange::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -4751,10 +4694,6 @@ void EnumDescriptorProto_EnumReservedRange::InternalSwap(EnumDescriptorProto_Enu // =================================================================== -void EnumDescriptorProto::InitAsDefaultInstance() { - PROTOBUF_NAMESPACE_ID::_EnumDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< PROTOBUF_NAMESPACE_ID::EnumOptions*>( - PROTOBUF_NAMESPACE_ID::EnumOptions::internal_default_instance()); -} class EnumDescriptorProto::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -5137,10 +5076,6 @@ void EnumDescriptorProto::InternalSwap(EnumDescriptorProto* other) { // =================================================================== -void EnumValueDescriptorProto::InitAsDefaultInstance() { - PROTOBUF_NAMESPACE_ID::_EnumValueDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< PROTOBUF_NAMESPACE_ID::EnumValueOptions*>( - PROTOBUF_NAMESPACE_ID::EnumValueOptions::internal_default_instance()); -} class EnumValueDescriptorProto::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -5456,10 +5391,6 @@ void EnumValueDescriptorProto::InternalSwap(EnumValueDescriptorProto* other) { // =================================================================== -void ServiceDescriptorProto::InitAsDefaultInstance() { - PROTOBUF_NAMESPACE_ID::_ServiceDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< PROTOBUF_NAMESPACE_ID::ServiceOptions*>( - PROTOBUF_NAMESPACE_ID::ServiceOptions::internal_default_instance()); -} class ServiceDescriptorProto::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -5771,10 +5702,6 @@ void ServiceDescriptorProto::InternalSwap(ServiceDescriptorProto* other) { // =================================================================== -void MethodDescriptorProto::InitAsDefaultInstance() { - PROTOBUF_NAMESPACE_ID::_MethodDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< PROTOBUF_NAMESPACE_ID::MethodOptions*>( - PROTOBUF_NAMESPACE_ID::MethodOptions::internal_default_instance()); -} class MethodDescriptorProto::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -6207,8 +6134,6 @@ void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) { // =================================================================== -void FileOptions::InitAsDefaultInstance() { -} class FileOptions::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -7194,8 +7119,6 @@ void FileOptions::InternalSwap(FileOptions* other) { // =================================================================== -void MessageOptions::InitAsDefaultInstance() { -} class MessageOptions::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -7548,8 +7471,6 @@ void MessageOptions::InternalSwap(MessageOptions* other) { // =================================================================== -void FieldOptions::InitAsDefaultInstance() { -} class FieldOptions::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -7967,8 +7888,6 @@ void FieldOptions::InternalSwap(FieldOptions* other) { // =================================================================== -void OneofOptions::InitAsDefaultInstance() { -} class OneofOptions::_Internal { public: }; @@ -8192,8 +8111,6 @@ void OneofOptions::InternalSwap(OneofOptions* other) { // =================================================================== -void EnumOptions::InitAsDefaultInstance() { -} class EnumOptions::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -8496,8 +8413,6 @@ void EnumOptions::InternalSwap(EnumOptions* other) { // =================================================================== -void EnumValueOptions::InitAsDefaultInstance() { -} class EnumValueOptions::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -8758,8 +8673,6 @@ void EnumValueOptions::InternalSwap(EnumValueOptions* other) { // =================================================================== -void ServiceOptions::InitAsDefaultInstance() { -} class ServiceOptions::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -9020,8 +8933,6 @@ void ServiceOptions::InternalSwap(ServiceOptions* other) { // =================================================================== -void MethodOptions::InitAsDefaultInstance() { -} class MethodOptions::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -9333,8 +9244,6 @@ void MethodOptions::InternalSwap(MethodOptions* other) { // =================================================================== -void UninterpretedOption_NamePart::InitAsDefaultInstance() { -} class UninterpretedOption_NamePart::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -9612,8 +9521,6 @@ void UninterpretedOption_NamePart::InternalSwap(UninterpretedOption_NamePart* ot // =================================================================== -void UninterpretedOption::InitAsDefaultInstance() { -} class UninterpretedOption::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -10057,8 +9964,6 @@ void UninterpretedOption::InternalSwap(UninterpretedOption* other) { // =================================================================== -void SourceCodeInfo_Location::InitAsDefaultInstance() { -} class SourceCodeInfo_Location::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -10451,8 +10356,6 @@ void SourceCodeInfo_Location::InternalSwap(SourceCodeInfo_Location* other) { // =================================================================== -void SourceCodeInfo::InitAsDefaultInstance() { -} class SourceCodeInfo::_Internal { public: }; @@ -10654,8 +10557,6 @@ void SourceCodeInfo::InternalSwap(SourceCodeInfo* other) { // =================================================================== -void GeneratedCodeInfo_Annotation::InitAsDefaultInstance() { -} class GeneratedCodeInfo_Annotation::_Internal { public: using HasBits = decltype(std::declval()._has_bits_); @@ -10995,8 +10896,6 @@ void GeneratedCodeInfo_Annotation::InternalSwap(GeneratedCodeInfo_Annotation* ot // =================================================================== -void GeneratedCodeInfo::InitAsDefaultInstance() { -} class GeneratedCodeInfo::_Internal { public: }; diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h index b10c78b006..21e9b90ab9 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -373,7 +373,6 @@ class PROTOBUF_EXPORT FileDescriptorSet PROTOBUF_FINAL : } static const FileDescriptorSet& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const FileDescriptorSet* internal_default_instance() { return reinterpret_cast( &_FileDescriptorSet_default_instance_); @@ -526,7 +525,6 @@ class PROTOBUF_EXPORT FileDescriptorProto PROTOBUF_FINAL : } static const FileDescriptorProto& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const FileDescriptorProto* internal_default_instance() { return reinterpret_cast( &_FileDescriptorProto_default_instance_); @@ -920,7 +918,6 @@ class PROTOBUF_EXPORT DescriptorProto_ExtensionRange PROTOBUF_FINAL : } static const DescriptorProto_ExtensionRange& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const DescriptorProto_ExtensionRange* internal_default_instance() { return reinterpret_cast( &_DescriptorProto_ExtensionRange_default_instance_); @@ -1104,7 +1101,6 @@ class PROTOBUF_EXPORT DescriptorProto_ReservedRange PROTOBUF_FINAL : } static const DescriptorProto_ReservedRange& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const DescriptorProto_ReservedRange* internal_default_instance() { return reinterpret_cast( &_DescriptorProto_ReservedRange_default_instance_); @@ -1268,7 +1264,6 @@ class PROTOBUF_EXPORT DescriptorProto PROTOBUF_FINAL : } static const DescriptorProto& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const DescriptorProto* internal_default_instance() { return reinterpret_cast( &_DescriptorProto_default_instance_); @@ -1613,7 +1608,6 @@ class PROTOBUF_EXPORT ExtensionRangeOptions PROTOBUF_FINAL : } static const ExtensionRangeOptions& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const ExtensionRangeOptions* internal_default_instance() { return reinterpret_cast( &_ExtensionRangeOptions_default_instance_); @@ -1769,7 +1763,6 @@ class PROTOBUF_EXPORT FieldDescriptorProto PROTOBUF_FINAL : } static const FieldDescriptorProto& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const FieldDescriptorProto* internal_default_instance() { return reinterpret_cast( &_FieldDescriptorProto_default_instance_); @@ -2202,7 +2195,6 @@ class PROTOBUF_EXPORT OneofDescriptorProto PROTOBUF_FINAL : } static const OneofDescriptorProto& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const OneofDescriptorProto* internal_default_instance() { return reinterpret_cast( &_OneofDescriptorProto_default_instance_); @@ -2378,7 +2370,6 @@ class PROTOBUF_EXPORT EnumDescriptorProto_EnumReservedRange PROTOBUF_FINAL : } static const EnumDescriptorProto_EnumReservedRange& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const EnumDescriptorProto_EnumReservedRange* internal_default_instance() { return reinterpret_cast( &_EnumDescriptorProto_EnumReservedRange_default_instance_); @@ -2542,7 +2533,6 @@ class PROTOBUF_EXPORT EnumDescriptorProto PROTOBUF_FINAL : } static const EnumDescriptorProto& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const EnumDescriptorProto* internal_default_instance() { return reinterpret_cast( &_EnumDescriptorProto_default_instance_); @@ -2786,7 +2776,6 @@ class PROTOBUF_EXPORT EnumValueDescriptorProto PROTOBUF_FINAL : } static const EnumValueDescriptorProto& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const EnumValueDescriptorProto* internal_default_instance() { return reinterpret_cast( &_EnumValueDescriptorProto_default_instance_); @@ -2977,7 +2966,6 @@ class PROTOBUF_EXPORT ServiceDescriptorProto PROTOBUF_FINAL : } static const ServiceDescriptorProto& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const ServiceDescriptorProto* internal_default_instance() { return reinterpret_cast( &_ServiceDescriptorProto_default_instance_); @@ -3173,7 +3161,6 @@ class PROTOBUF_EXPORT MethodDescriptorProto PROTOBUF_FINAL : } static const MethodDescriptorProto& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const MethodDescriptorProto* internal_default_instance() { return reinterpret_cast( &_MethodDescriptorProto_default_instance_); @@ -3423,7 +3410,6 @@ class PROTOBUF_EXPORT FileOptions PROTOBUF_FINAL : } static const FileOptions& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const FileOptions* internal_default_instance() { return reinterpret_cast( &_FileOptions_default_instance_); @@ -3982,7 +3968,6 @@ class PROTOBUF_EXPORT MessageOptions PROTOBUF_FINAL : } static const MessageOptions& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const MessageOptions* internal_default_instance() { return reinterpret_cast( &_MessageOptions_default_instance_); @@ -4199,7 +4184,6 @@ class PROTOBUF_EXPORT FieldOptions PROTOBUF_FINAL : } static const FieldOptions& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const FieldOptions* internal_default_instance() { return reinterpret_cast( &_FieldOptions_default_instance_); @@ -4510,7 +4494,6 @@ class PROTOBUF_EXPORT OneofOptions PROTOBUF_FINAL : } static const OneofOptions& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const OneofOptions* internal_default_instance() { return reinterpret_cast( &_OneofOptions_default_instance_); @@ -4666,7 +4649,6 @@ class PROTOBUF_EXPORT EnumOptions PROTOBUF_FINAL : } static const EnumOptions& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const EnumOptions* internal_default_instance() { return reinterpret_cast( &_EnumOptions_default_instance_); @@ -4853,7 +4835,6 @@ class PROTOBUF_EXPORT EnumValueOptions PROTOBUF_FINAL : } static const EnumValueOptions& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const EnumValueOptions* internal_default_instance() { return reinterpret_cast( &_EnumValueOptions_default_instance_); @@ -5025,7 +5006,6 @@ class PROTOBUF_EXPORT ServiceOptions PROTOBUF_FINAL : } static const ServiceOptions& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const ServiceOptions* internal_default_instance() { return reinterpret_cast( &_ServiceOptions_default_instance_); @@ -5197,7 +5177,6 @@ class PROTOBUF_EXPORT MethodOptions PROTOBUF_FINAL : } static const MethodOptions& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const MethodOptions* internal_default_instance() { return reinterpret_cast( &_MethodOptions_default_instance_); @@ -5416,7 +5395,6 @@ class PROTOBUF_EXPORT UninterpretedOption_NamePart PROTOBUF_FINAL : } static const UninterpretedOption_NamePart& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const UninterpretedOption_NamePart* internal_default_instance() { return reinterpret_cast( &_UninterpretedOption_NamePart_default_instance_); @@ -5590,7 +5568,6 @@ class PROTOBUF_EXPORT UninterpretedOption PROTOBUF_FINAL : } static const UninterpretedOption& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const UninterpretedOption* internal_default_instance() { return reinterpret_cast( &_UninterpretedOption_default_instance_); @@ -5857,7 +5834,6 @@ class PROTOBUF_EXPORT SourceCodeInfo_Location PROTOBUF_FINAL : } static const SourceCodeInfo_Location& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const SourceCodeInfo_Location* internal_default_instance() { return reinterpret_cast( &_SourceCodeInfo_Location_default_instance_); @@ -6111,7 +6087,6 @@ class PROTOBUF_EXPORT SourceCodeInfo PROTOBUF_FINAL : } static const SourceCodeInfo& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const SourceCodeInfo* internal_default_instance() { return reinterpret_cast( &_SourceCodeInfo_default_instance_); @@ -6266,7 +6241,6 @@ class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation PROTOBUF_FINAL : } static const GeneratedCodeInfo_Annotation& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const GeneratedCodeInfo_Annotation* internal_default_instance() { return reinterpret_cast( &_GeneratedCodeInfo_Annotation_default_instance_); @@ -6477,7 +6451,6 @@ class PROTOBUF_EXPORT GeneratedCodeInfo PROTOBUF_FINAL : } static const GeneratedCodeInfo& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const GeneratedCodeInfo* internal_default_instance() { return reinterpret_cast( &_GeneratedCodeInfo_default_instance_); @@ -7128,8 +7101,8 @@ inline void FileDescriptorProto::clear_options() { } inline const PROTOBUF_NAMESPACE_ID::FileOptions& FileDescriptorProto::_internal_options() const { const PROTOBUF_NAMESPACE_ID::FileOptions* p = options_; - return p != nullptr ? *p : *reinterpret_cast( - &PROTOBUF_NAMESPACE_ID::_FileOptions_default_instance_); + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_FileOptions_default_instance_); } inline const PROTOBUF_NAMESPACE_ID::FileOptions& FileDescriptorProto::options() const { // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.options) @@ -7211,8 +7184,8 @@ inline void FileDescriptorProto::clear_source_code_info() { } inline const PROTOBUF_NAMESPACE_ID::SourceCodeInfo& FileDescriptorProto::_internal_source_code_info() const { const PROTOBUF_NAMESPACE_ID::SourceCodeInfo* p = source_code_info_; - return p != nullptr ? *p : *reinterpret_cast( - &PROTOBUF_NAMESPACE_ID::_SourceCodeInfo_default_instance_); + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_SourceCodeInfo_default_instance_); } inline const PROTOBUF_NAMESPACE_ID::SourceCodeInfo& FileDescriptorProto::source_code_info() const { // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.source_code_info) @@ -7428,8 +7401,8 @@ inline void DescriptorProto_ExtensionRange::clear_options() { } inline const PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions& DescriptorProto_ExtensionRange::_internal_options() const { const PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* p = options_; - return p != nullptr ? *p : *reinterpret_cast( - &PROTOBUF_NAMESPACE_ID::_ExtensionRangeOptions_default_instance_); + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_ExtensionRangeOptions_default_instance_); } inline const PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions& DescriptorProto_ExtensionRange::options() const { // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.options) @@ -7883,8 +7856,8 @@ inline void DescriptorProto::clear_options() { } inline const PROTOBUF_NAMESPACE_ID::MessageOptions& DescriptorProto::_internal_options() const { const PROTOBUF_NAMESPACE_ID::MessageOptions* p = options_; - return p != nullptr ? *p : *reinterpret_cast( - &PROTOBUF_NAMESPACE_ID::_MessageOptions_default_instance_); + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_MessageOptions_default_instance_); } inline const PROTOBUF_NAMESPACE_ID::MessageOptions& DescriptorProto::options() const { // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.options) @@ -8610,8 +8583,8 @@ inline void FieldDescriptorProto::clear_options() { } inline const PROTOBUF_NAMESPACE_ID::FieldOptions& FieldDescriptorProto::_internal_options() const { const PROTOBUF_NAMESPACE_ID::FieldOptions* p = options_; - return p != nullptr ? *p : *reinterpret_cast( - &PROTOBUF_NAMESPACE_ID::_FieldOptions_default_instance_); + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_FieldOptions_default_instance_); } inline const PROTOBUF_NAMESPACE_ID::FieldOptions& FieldDescriptorProto::options() const { // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.options) @@ -8799,8 +8772,8 @@ inline void OneofDescriptorProto::clear_options() { } inline const PROTOBUF_NAMESPACE_ID::OneofOptions& OneofDescriptorProto::_internal_options() const { const PROTOBUF_NAMESPACE_ID::OneofOptions* p = options_; - return p != nullptr ? *p : *reinterpret_cast( - &PROTOBUF_NAMESPACE_ID::_OneofOptions_default_instance_); + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_OneofOptions_default_instance_); } inline const PROTOBUF_NAMESPACE_ID::OneofOptions& OneofDescriptorProto::options() const { // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.options) @@ -9059,8 +9032,8 @@ inline void EnumDescriptorProto::clear_options() { } inline const PROTOBUF_NAMESPACE_ID::EnumOptions& EnumDescriptorProto::_internal_options() const { const PROTOBUF_NAMESPACE_ID::EnumOptions* p = options_; - return p != nullptr ? *p : *reinterpret_cast( - &PROTOBUF_NAMESPACE_ID::_EnumOptions_default_instance_); + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_EnumOptions_default_instance_); } inline const PROTOBUF_NAMESPACE_ID::EnumOptions& EnumDescriptorProto::options() const { // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.options) @@ -9361,8 +9334,8 @@ inline void EnumValueDescriptorProto::clear_options() { } inline const PROTOBUF_NAMESPACE_ID::EnumValueOptions& EnumValueDescriptorProto::_internal_options() const { const PROTOBUF_NAMESPACE_ID::EnumValueOptions* p = options_; - return p != nullptr ? *p : *reinterpret_cast( - &PROTOBUF_NAMESPACE_ID::_EnumValueOptions_default_instance_); + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_EnumValueOptions_default_instance_); } inline const PROTOBUF_NAMESPACE_ID::EnumValueOptions& EnumValueDescriptorProto::options() const { // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.options) @@ -9561,8 +9534,8 @@ inline void ServiceDescriptorProto::clear_options() { } inline const PROTOBUF_NAMESPACE_ID::ServiceOptions& ServiceDescriptorProto::_internal_options() const { const PROTOBUF_NAMESPACE_ID::ServiceOptions* p = options_; - return p != nullptr ? *p : *reinterpret_cast( - &PROTOBUF_NAMESPACE_ID::_ServiceOptions_default_instance_); + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_ServiceOptions_default_instance_); } inline const PROTOBUF_NAMESPACE_ID::ServiceOptions& ServiceDescriptorProto::options() const { // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.options) @@ -9870,8 +9843,8 @@ inline void MethodDescriptorProto::clear_options() { } inline const PROTOBUF_NAMESPACE_ID::MethodOptions& MethodDescriptorProto::_internal_options() const { const PROTOBUF_NAMESPACE_ID::MethodOptions* p = options_; - return p != nullptr ? *p : *reinterpret_cast( - &PROTOBUF_NAMESPACE_ID::_MethodOptions_default_instance_); + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_MethodOptions_default_instance_); } inline const PROTOBUF_NAMESPACE_ID::MethodOptions& MethodDescriptorProto::options() const { // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.options) diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc index 6085a122a8..6da6ba7a32 100644 --- a/src/google/protobuf/descriptor_unittest.cc +++ b/src/google/protobuf/descriptor_unittest.cc @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include @@ -58,6 +57,7 @@ #include #include #include +#include #include diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc index b8bceca6c6..2284cdc5f0 100644 --- a/src/google/protobuf/duration.pb.cc +++ b/src/google/protobuf/duration.pb.cc @@ -28,7 +28,6 @@ static void InitDefaultsscc_info_Duration_google_2fprotobuf_2fduration_2eproto() new (ptr) PROTOBUF_NAMESPACE_ID::Duration(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::Duration::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Duration_google_2fprotobuf_2fduration_2eproto = @@ -82,8 +81,6 @@ PROTOBUF_NAMESPACE_OPEN // =================================================================== -void Duration::InitAsDefaultInstance() { -} class Duration::_Internal { public: }; diff --git a/src/google/protobuf/duration.pb.h b/src/google/protobuf/duration.pb.h index a530f51544..60f4ee1dfd 100644 --- a/src/google/protobuf/duration.pb.h +++ b/src/google/protobuf/duration.pb.h @@ -102,7 +102,6 @@ class PROTOBUF_EXPORT Duration PROTOBUF_FINAL : } static const Duration& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const Duration* internal_default_instance() { return reinterpret_cast( &_Duration_default_instance_); diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc index 2af5109701..3d9adc200b 100644 --- a/src/google/protobuf/dynamic_message.cc +++ b/src/google/protobuf/dynamic_message.cc @@ -292,6 +292,13 @@ class DynamicMessage : public Message { ~DynamicMessage(); // Called on the prototype after construction to initialize message fields. + // Cross linking the default instances allows for fast reflection access of + // unset message fields. Without it we would have to go to the MessageFactory + // to get the prototype, which is a much more expensive operation. + // + // Generated messages do not cross-link to avoid dynamic initialization of the + // global instances. + // Instead, they keep the default instances in the FieldDescriptor objects. void CrossLinkPrototypes(); // implements Message ---------------------------------------------- diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc index 27f801fd9d..f30f2c97d2 100644 --- a/src/google/protobuf/empty.pb.cc +++ b/src/google/protobuf/empty.pb.cc @@ -28,7 +28,6 @@ static void InitDefaultsscc_info_Empty_google_2fprotobuf_2fempty_2eproto() { new (ptr) PROTOBUF_NAMESPACE_ID::Empty(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::Empty::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Empty_google_2fprotobuf_2fempty_2eproto = @@ -79,8 +78,6 @@ PROTOBUF_NAMESPACE_OPEN // =================================================================== -void Empty::InitAsDefaultInstance() { -} class Empty::_Internal { public: }; diff --git a/src/google/protobuf/empty.pb.h b/src/google/protobuf/empty.pb.h index 17fda949f4..c87709afa1 100644 --- a/src/google/protobuf/empty.pb.h +++ b/src/google/protobuf/empty.pb.h @@ -102,7 +102,6 @@ class PROTOBUF_EXPORT Empty PROTOBUF_FINAL : } static const Empty& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const Empty* internal_default_instance() { return reinterpret_cast( &_Empty_default_instance_); diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc index 3b1441e665..0dcabb0f47 100644 --- a/src/google/protobuf/extension_set.cc +++ b/src/google/protobuf/extension_set.cc @@ -1870,28 +1870,32 @@ void ExtensionSet::GrowCapacity(size_t minimum_new_capacity) { return; } - const auto old_flat_capacity = flat_capacity_; - + auto new_flat_capacity = flat_capacity_; do { - flat_capacity_ = flat_capacity_ == 0 ? 1 : flat_capacity_ * 4; - } while (flat_capacity_ < minimum_new_capacity); + new_flat_capacity = new_flat_capacity == 0 ? 1 : new_flat_capacity * 4; + } while (new_flat_capacity < minimum_new_capacity); const KeyValue* begin = flat_begin(); const KeyValue* end = flat_end(); - if (flat_capacity_ > kMaximumFlatCapacity) { - // Switch to LargeMap - map_.large = Arena::Create(arena_); - LargeMap::iterator hint = map_.large->begin(); + AllocatedData new_map; + if (new_flat_capacity > kMaximumFlatCapacity) { + new_map.large = Arena::Create(arena_); + LargeMap::iterator hint = new_map.large->begin(); for (const KeyValue* it = begin; it != end; ++it) { - hint = map_.large->insert(hint, {it->first, it->second}); + hint = new_map.large->insert(hint, {it->first, it->second}); } - flat_size_ = 0; } else { - map_.flat = Arena::CreateArray(arena_, flat_capacity_); - std::copy(begin, end, map_.flat); + new_map.flat = Arena::CreateArray(arena_, new_flat_capacity); + std::copy(begin, end, new_map.flat); } + if (arena_ == nullptr) { - DeleteFlatMap(begin, old_flat_capacity); + DeleteFlatMap(begin, flat_capacity_); + } + flat_capacity_ = new_flat_capacity; + map_ = new_map; + if (is_large()) { + flat_size_ = 0; } } diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc index e735b3ac66..4389093b6b 100644 --- a/src/google/protobuf/field_mask.pb.cc +++ b/src/google/protobuf/field_mask.pb.cc @@ -28,7 +28,6 @@ static void InitDefaultsscc_info_FieldMask_google_2fprotobuf_2ffield_5fmask_2epr new (ptr) PROTOBUF_NAMESPACE_ID::FieldMask(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::FieldMask::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_FieldMask_google_2fprotobuf_2ffield_5fmask_2eproto = @@ -81,8 +80,6 @@ PROTOBUF_NAMESPACE_OPEN // =================================================================== -void FieldMask::InitAsDefaultInstance() { -} class FieldMask::_Internal { public: }; diff --git a/src/google/protobuf/field_mask.pb.h b/src/google/protobuf/field_mask.pb.h index a493466136..cbea34b9a8 100644 --- a/src/google/protobuf/field_mask.pb.h +++ b/src/google/protobuf/field_mask.pb.h @@ -102,7 +102,6 @@ class PROTOBUF_EXPORT FieldMask PROTOBUF_FINAL : } static const FieldMask& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const FieldMask* internal_default_instance() { return reinterpret_cast( &_FieldMask_default_instance_); diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index d8397ed258..0db7dfc0e8 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc @@ -320,15 +320,16 @@ size_t Reflection::SpaceUsedLong(const Message& message) const { break; } - // Initially, the string points to the default value stored - // in the prototype. Only count the string if it has been - // changed from the default value. - const std::string* default_ptr = - &DefaultRaw(field).Get(); const std::string* ptr = &GetField(message, field).Get(); - if (ptr != default_ptr) { + // Initially, the string points to the default value stored + // in the prototype. Only count the string if it has been + // changed from the default value. + // Except oneof fields, those never point to a default instance, + // and there is no default instance to point to. + if (schema_.InRealOneof(field) || + ptr != &DefaultRaw(field).Get()) { // string fields are represented by just a pointer, so also // include sizeof(string) as well. total_size += @@ -359,8 +360,6 @@ size_t Reflection::SpaceUsedLong(const Message& message) const { void Reflection::SwapField(Message* message1, Message* message2, const FieldDescriptor* field) const { - CheckInvalidAccess(schema_, field); - if (field->is_repeated()) { switch (field->cpp_type()) { #define SWAP_ARRAYS(CPPTYPE, TYPE) \ @@ -1121,6 +1120,8 @@ void Reflection::ListFieldsOmitStripped( if (field->is_extension()) { \ return GetExtensionSet(message).Get##TYPENAME( \ field->number(), field->default_value_##PASSTYPE()); \ + } else if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { \ + return field->default_value_##PASSTYPE(); \ } else { \ return GetField(message, field); \ } \ @@ -1190,6 +1191,9 @@ std::string Reflection::GetString(const Message& message, return GetExtensionSet(message).GetString(field->number(), field->default_value_string()); } else { + if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { + return field->default_value_string(); + } switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { @@ -1211,6 +1215,9 @@ const std::string& Reflection::GetStringReference(const Message& message, return GetExtensionSet(message).GetString(field->number(), field->default_value_string()); } else { + if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { + return field->default_value_string(); + } switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { @@ -1241,16 +1248,21 @@ void Reflection::SetString(Message* message, const FieldDescriptor* field, break; } + // 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_ptr = - &DefaultRaw(field).Get(); + schema_.InRealOneof(field) + ? &GetEmptyString() + : &DefaultRaw(field).Get(); if (schema_.InRealOneof(field) && !HasOneofField(*message, field)) { ClearOneof(message, field->containing_oneof()); MutableField(message, field) ->UnsafeSetDefault(default_ptr); } MutableField(message, field) - ->Mutable(default_ptr, GetArena(message)) - ->assign(std::move(value)); + ->Set(default_ptr, std::move(value), GetArena(message)); break; } } @@ -1342,6 +1354,8 @@ int Reflection::GetEnumValue(const Message& message, if (field->is_extension()) { value = GetExtensionSet(message).GetEnum( field->number(), field->default_value_enum()->number()); + } else if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { + value = field->default_value_enum()->number(); } else { value = GetField(message, field); } @@ -1476,6 +1490,40 @@ void Reflection::AddEnumValueInternal(Message* message, // ------------------------------------------------------------------- +const Message* Reflection::GetDefaultMessageInstance( + const FieldDescriptor* field) const { + // If we are using the generated factory, we cache the prototype in the field + // descriptor for faster access. + // The default instances of generated messages are not cross-linked, which + // means they contain null pointers on their message fields and can't be used + // to get the default of submessages. + if (message_factory_ == MessageFactory::generated_factory()) { + auto& ptr = field->default_generated_instance_; + auto* res = ptr.load(std::memory_order_acquire); + if (res == nullptr) { + // First time asking for this field's default. Load it and cache it. + res = message_factory_->GetPrototype(field->message_type()); + ptr.store(res, std::memory_order_release); + } + return res; + } + + // For other factories, we try the default's object field. + // In particular, the DynamicMessageFactory will cross link the default + // instances to allow for this. But only do this for real fields. + // This is an optimization to avoid going to GetPrototype() below, as that + // requires a lock and a map lookup. + if (!field->is_extension() && !field->options().weak() && + !field->options().lazy() && !schema_.InRealOneof(field)) { + auto* res = DefaultRaw(field); + if (res != nullptr) { + return res; + } + } + // Otherwise, just go to the factory. + return message_factory_->GetPrototype(field->message_type()); +} + const Message& Reflection::GetMessage(const Message& message, const FieldDescriptor* field, MessageFactory* factory) const { @@ -1488,9 +1536,12 @@ const Message& Reflection::GetMessage(const Message& message, return static_cast(GetExtensionSet(message).GetMessage( field->number(), field->message_type(), factory)); } else { + if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { + return *GetDefaultMessageInstance(field); + } const Message* result = GetRaw(message, field); if (result == nullptr) { - result = DefaultRaw(field); + result = GetDefaultMessageInstance(field); } return *result; } @@ -1516,7 +1567,7 @@ Message* Reflection::MutableMessage(Message* message, if (!HasOneofField(*message, field)) { ClearOneof(message, field->containing_oneof()); result_holder = MutableField(message, field); - const Message* default_message = DefaultRaw(field); + const Message* default_message = GetDefaultMessageInstance(field); *result_holder = default_message->New(message->GetArena()); } } else { @@ -1524,7 +1575,7 @@ Message* Reflection::MutableMessage(Message* message, } if (*result_holder == nullptr) { - const Message* default_message = DefaultRaw(field); + const Message* default_message = GetDefaultMessageInstance(field); *result_holder = default_message->New(message->GetArena()); } result = *result_holder; @@ -1903,9 +1954,8 @@ Type* Reflection::MutableRawNonOneof(Message* message, template const Type& Reflection::GetRaw(const Message& message, const FieldDescriptor* field) const { - if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { - return DefaultRaw(field); - } + GOOGLE_DCHECK(!schema_.InRealOneof(field) || HasOneofField(message, field)) + << "Field = " << field->full_name(); return GetConstRefAtOffset(message, schema_.GetFieldOffset(field)); } @@ -2112,8 +2162,11 @@ void Reflection::ClearOneof(Message* message, switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { - const std::string* default_ptr = - &DefaultRaw(field).Get(); + // 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_ptr = &GetEmptyString(); MutableField(message, field) ->Destroy(default_ptr, GetArena(message)); break; diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h index cb2ae35e04..1c284959d0 100644 --- a/src/google/protobuf/generated_message_reflection.h +++ b/src/google/protobuf/generated_message_reflection.h @@ -212,6 +212,12 @@ struct ReflectionSchema { OffsetValue(offsets_[field->index()], field->type()); } + // Returns true if the field's accessor is called by any external code (aka, + // non proto library code). + bool IsFieldUsed(const FieldDescriptor* field) const { + return true; + } + bool IsFieldStripped(const FieldDescriptor* field) const { return false; } @@ -242,6 +248,7 @@ struct ReflectionSchema { // We tag offset values to provide additional data about fields (such as // inlined). static uint32 OffsetValue(uint32 v, FieldDescriptor::Type type) { + v &= 0x7FFFFFFFu; if (type == FieldDescriptor::TYPE_STRING || type == FieldDescriptor::TYPE_BYTES) { return v & ~1u; @@ -296,6 +303,13 @@ struct PROTOBUF_EXPORT DescriptorTable { const ServiceDescriptor** file_level_service_descriptors; }; +enum { + // Tag used on offsets for fields that don't have a real offset. + // For example, weak message fields go into the WeakFieldMap and not in an + // actual field. + kInvalidFieldOffsetTag = 0x40000000u, +}; + // AssignDescriptors() pulls the compiled FileDescriptor from the DescriptorPool // and uses it to populate all of the global variables which store pointers to // the descriptor objects. It also constructs the reflection objects. It is diff --git a/src/google/protobuf/generated_message_reflection_unittest.cc b/src/google/protobuf/generated_message_reflection_unittest.cc index 1c9d408db1..7234f5f932 100644 --- a/src/google/protobuf/generated_message_reflection_unittest.cc +++ b/src/google/protobuf/generated_message_reflection_unittest.cc @@ -486,6 +486,7 @@ TEST(GeneratedMessageReflectionTest, FindKnownExtensionByName) { ->FindKnownExtensionByName(extension1->full_name()) == NULL); } + TEST(GeneratedMessageReflectionTest, SetAllocatedMessageTest) { unittest::TestAllTypes from_message1; unittest::TestAllTypes from_message2; diff --git a/src/google/protobuf/io/zero_copy_stream_impl.h b/src/google/protobuf/io/zero_copy_stream_impl.h index b23a86d4f6..6e5cdebbf1 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl.h +++ b/src/google/protobuf/io/zero_copy_stream_impl.h @@ -48,7 +48,6 @@ #include #include - #include namespace google { diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc index 51cda2a88e..34bf45ff70 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc +++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc @@ -140,29 +140,25 @@ StringOutputStream::StringOutputStream(std::string* target) : target_(target) {} bool StringOutputStream::Next(void** data, int* size) { GOOGLE_CHECK(target_ != NULL); - int old_size = target_->size(); + size_t old_size = target_->size(); // Grow the string. + size_t new_size; if (old_size < target_->capacity()) { // Resize the string to match its capacity, since we can get away // without a memory allocation this way. - STLStringResizeUninitialized(target_, target_->capacity()); + new_size = target_->capacity(); } else { - // Size has reached capacity, try to double the size. - if (old_size > std::numeric_limits::max() / 2) { - // Can not double the size otherwise it is going to cause integer - // overflow in the expression below: old_size * 2 "; - GOOGLE_LOG(ERROR) << "Cannot allocate buffer larger than kint32max for " - << "StringOutputStream."; - return false; - } - // Double the size, also make sure that the new size is at least - // kMinimumSize. - STLStringResizeUninitialized( - target_, - std::max(old_size * 2, - kMinimumSize + 0)); // "+ 0" works around GCC4 weirdness. + // Size has reached capacity, try to double it. + new_size = old_size * 2; } + // Avoid integer overflow in returned '*size'. + new_size = std::min(new_size, old_size + std::numeric_limits::max()); + // Increase the size, also make sure that it is at least kMinimumSize. + STLStringResizeUninitialized( + target_, + std::max(new_size, + kMinimumSize + 0)); // "+ 0" works around GCC4 weirdness. *data = mutable_string_data(target_) + old_size; *size = target_->size() - old_size; diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.h b/src/google/protobuf/io/zero_copy_stream_impl_lite.h index 26572cc55c..2f0c662274 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h +++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h @@ -150,7 +150,7 @@ class PROTOBUF_EXPORT StringOutputStream : public ZeroCopyOutputStream { int64_t ByteCount() const override; private: - static const int kMinimumSize = 16; + static constexpr size_t kMinimumSize = 16; std::string* target_; diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc index bec9df0af6..b0f84fb913 100644 --- a/src/google/protobuf/io/zero_copy_stream_unittest.cc +++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc @@ -712,6 +712,21 @@ TEST_F(IoTest, StringIo) { } } +// Verifies that outputs up to kint32max can be created. +TEST_F(IoTest, LargeOutput) { + std::string str; + StringOutputStream output(&str); + void* unused_data; + int size; + // Repeatedly calling Next should eventually grow the buffer to kint32max. + do { + EXPECT_TRUE(output.Next(&unused_data, &size)); + } while (str.size() < std::numeric_limits::max()); + // Further increases should be possible. + output.Next(&unused_data, &size); + EXPECT_GT(size, 0); +} + // To test files, we create a temporary file, write, read, truncate, repeat. TEST_F(IoTest, FileIo) { diff --git a/src/google/protobuf/map.cc b/src/google/protobuf/map.cc new file mode 100644 index 0000000000..d60a9a285c --- /dev/null +++ b/src/google/protobuf/map.cc @@ -0,0 +1,41 @@ +// 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. + +#include + +namespace google { +namespace protobuf { +namespace internal { + +void* const kGlobalEmptyTable[kGlobalEmptyTableSize] = {nullptr}; + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h index c3cfb4318a..c25f334673 100644 --- a/src/google/protobuf/map.h +++ b/src/google/protobuf/map.h @@ -182,7 +182,7 @@ class MapAllocator { private: using DestructorSkippable_ = void; - Arena* const arena_; + Arena* arena_; }; template @@ -280,6 +280,9 @@ size_t MapValueSpaceUsedExcludingSelfLong(const T& message) { return message.SpaceUsedLong() - sizeof(T); } +constexpr size_t kGlobalEmptyTableSize = 1; +PROTOBUF_EXPORT extern void* const kGlobalEmptyTable[kGlobalEmptyTableSize]; + // Space used for the table, trees, and nodes. // Does not include the indirect space used. Eg the data of a std::string. template @@ -377,24 +380,22 @@ class Map { using size_type = size_t; using hasher = typename internal::TransparentSupport::hash; - Map() : arena_(nullptr) { Init(); } - explicit Map(Arena* arena) : arena_(arena) { Init(); } + Map() : elements_(nullptr) {} + explicit Map(Arena* arena) : elements_(arena) {} - Map(const Map& other) : arena_(nullptr) { - Init(); - insert(other.begin(), other.end()); - } + Map(const Map& other) : Map() { insert(other.begin(), other.end()); } Map(Map&& other) noexcept : Map() { - if (other.arena_) { + if (other.arena() != nullptr) { *this = other; } else { swap(other); } } + Map& operator=(Map&& other) noexcept { if (this != &other) { - if (arena_ != other.arena_) { + if (arena() != other.arena()) { *this = other; } else { swap(other); @@ -404,21 +405,13 @@ class Map { } template - Map(const InputIt& first, const InputIt& last) : arena_(nullptr) { - Init(); + Map(const InputIt& first, const InputIt& last) : Map() { insert(first, last); } - ~Map() { - if (arena_ == nullptr) { - clear(); - delete elements_; - } - } + ~Map() {} private: - void Init() { elements_ = Arena::CreateMessage(arena_, 0); } - using Allocator = internal::MapAllocator; // InnerMap is a generic hash-based map. It doesn't contain any @@ -455,20 +448,18 @@ class Map { // otherwise. This avoids unncessary copies of string keys, for example. class InnerMap : private hasher { public: - explicit InnerMap(size_type n) : InnerMap(nullptr, n) {} - InnerMap(Arena* arena, size_type n) + explicit InnerMap(Arena* arena) : hasher(), num_elements_(0), + num_buckets_(internal::kGlobalEmptyTableSize), seed_(Seed()), - table_(nullptr), - alloc_(arena) { - n = TableSize(n); - table_ = CreateEmptyTable(n); - num_buckets_ = index_of_first_non_null_ = n; - } + index_of_first_non_null_(num_buckets_), + table_(const_cast(internal::kGlobalEmptyTable)), + alloc_(arena) {} ~InnerMap() { - if (table_ != nullptr) { + if (alloc_.arena() == nullptr && + num_buckets_ != internal::kGlobalEmptyTableSize) { clear(); Dealloc(table_, num_buckets_); } @@ -627,6 +618,17 @@ class Map { using iterator = iterator_base; using const_iterator = iterator_base; + Arena* arena() const { return alloc_.arena(); } + + void Swap(InnerMap* other) { + std::swap(num_elements_, other->num_elements_); + std::swap(num_buckets_, other->num_buckets_); + std::swap(seed_, other->seed_); + std::swap(index_of_first_non_null_, other->index_of_first_non_null_); + std::swap(table_, other->table_); + std::swap(alloc_, other->alloc_); + } + iterator begin() { return iterator(this); } iterator end() { return iterator(); } const_iterator begin() const { return const_iterator(this); } @@ -676,6 +678,11 @@ class Map { return iterator(FindHelper(k).first); } + template + const_iterator find(const K& k) const { + return FindHelper(k).first; + } + // Insert the key into the map, if not present. In that case, the value will // be value initialized. std::pair insert(const Key& k) { @@ -895,6 +902,14 @@ class Map { // Resize to the given number of buckets. void Resize(size_t new_num_buckets) { + if (num_buckets_ == internal::kGlobalEmptyTableSize) { + // This is the global empty array. + // Just overwrite with a new one. No need to transfer or free anything. + num_buckets_ = index_of_first_non_null_ = kMinTableSize; + table_ = CreateEmptyTable(num_buckets_); + return; + } + GOOGLE_DCHECK_GE(new_num_buckets, kMinTableSize); void** const old_table = table_; const size_type old_table_size = num_buckets_; @@ -1057,7 +1072,7 @@ class Map { #if defined(__x86_64__) && defined(__GNUC__) && \ !defined(GOOGLE_PROTOBUF_NO_RDTSC) uint32 hi, lo; - asm("rdtsc" : "=a"(lo), "=d"(hi)); + asm volatile("rdtsc" : "=a"(lo), "=d"(hi)); s += ((static_cast(hi) << 32) | lo); #endif return s; @@ -1155,23 +1170,19 @@ class Map { InnerIt it_; }; - iterator begin() { return iterator(elements_->begin()); } - iterator end() { return iterator(elements_->end()); } - const_iterator begin() const { - return const_iterator(iterator(elements_->begin())); - } - const_iterator end() const { - return const_iterator(iterator(elements_->end())); - } + iterator begin() { return iterator(elements_.begin()); } + iterator end() { return iterator(elements_.end()); } + const_iterator begin() const { return const_iterator(elements_.begin()); } + const_iterator end() const { return const_iterator(elements_.end()); } const_iterator cbegin() const { return begin(); } const_iterator cend() const { return end(); } // Capacity - size_type size() const { return elements_->size(); } + size_type size() const { return elements_.size(); } bool empty() const { return size() == 0; } // Element access - T& operator[](const key_type& key) { return (*elements_)[key].second; } + T& operator[](const key_type& key) { return elements_[key].second; } template const T& at(const key_arg& key) const { @@ -1195,11 +1206,11 @@ class Map { template const_iterator find(const key_arg& key) const { - return const_iterator(iterator(elements_->find(key))); + return const_iterator(elements_.find(key)); } template iterator find(const key_arg& key) { - return iterator(elements_->find(key)); + return iterator(elements_.find(key)); } template @@ -1233,7 +1244,7 @@ class Map { // insert std::pair insert(const value_type& value) { std::pair p = - elements_->insert(value.first); + elements_.insert(value.first); if (p.second) { p.first->second = value.second; } @@ -1265,7 +1276,7 @@ class Map { } iterator erase(iterator pos) { iterator i = pos++; - elements_->erase(i.it_); + elements_.erase(i.it_); return pos; } void erase(iterator first, iterator last) { @@ -1273,7 +1284,7 @@ class Map { first = erase(first); } } - void clear() { elements_->clear(); } + void clear() { elements_.clear(); } // Assign Map& operator=(const Map& other) { @@ -1285,8 +1296,8 @@ class Map { } void swap(Map& other) { - if (arena_ == other.arena_) { - std::swap(elements_, other.elements_); + if (arena() == other.arena()) { + elements_.Swap(&other.elements_); } else { // TODO(zuguang): optimize this. The temporary copy can be allocated // in the same arena as the other message, and the "other = copy" can @@ -1299,16 +1310,16 @@ class Map { // Access to hasher. Currently this returns a copy, but it may // be modified to return a const reference in the future. - hasher hash_function() const { return elements_->hash_function(); } + hasher hash_function() const { return elements_.hash_function(); } size_t SpaceUsedExcludingSelfLong() const { - return sizeof(InnerMap) + elements_->SpaceUsedInternal() + - internal::SpaceUsedInValues(this); + if (empty()) return 0; + return elements_.SpaceUsedInternal() + internal::SpaceUsedInValues(this); } private: - Arena* arena_; - InnerMap* elements_; + Arena* arena() const { return elements_.arena(); } + InnerMap elements_; friend class Arena; using InternalArenaConstructable_ = void; diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h index 6b5d4e8fdf..92cb4ac4d1 100644 --- a/src/google/protobuf/map_entry_lite.h +++ b/src/google/protobuf/map_entry_lite.h @@ -206,8 +206,7 @@ class MapEntryImpl : public Base { return KeyTypeHandler::GetExternalReference(key_); } virtual inline const ValueMapEntryAccessorType& value() const { - return ValueTypeHandler::DefaultIfNotInitialized( - value_, Derived::internal_default_instance()->value_); + return ValueTypeHandler::DefaultIfNotInitialized(value_); } inline KeyMapEntryAccessorType* mutable_key() { set_has_key(); @@ -323,12 +322,6 @@ class MapEntryImpl : public Base { clear_has_value(); } - static void InitAsDefaultInstance() { - Derived* d = const_cast(Derived::internal_default_instance()); - KeyTypeHandler::AssignDefaultValue(&d->key_); - ValueTypeHandler::AssignDefaultValue(&d->value_); - } - // Parsing using MergePartialFromCodedStream, above, is not as // efficient as it could be. This helper class provides a speedier way. template diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h index efca5ee83c..6a28b6ec07 100644 --- a/src/google/protobuf/map_field.h +++ b/src/google/protobuf/map_field.h @@ -264,6 +264,53 @@ class PROTOBUF_EXPORT MapKey { int type_; }; +} // namespace protobuf +} // namespace google +namespace std { +template <> +struct hash<::PROTOBUF_NAMESPACE_ID::MapKey> { + size_t operator()(const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key) const { + switch (map_key.type()) { + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_DOUBLE: + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_FLOAT: + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_ENUM: + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Unsupported"; + break; + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_STRING: + return hash()(map_key.GetStringValue()); + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT64: { + auto value = map_key.GetInt64Value(); + return hash()(value); + } + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT32: { + auto value = map_key.GetInt32Value(); + return hash()(map_key.GetInt32Value()); + } + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT64: { + auto value = map_key.GetUInt64Value(); + return hash()(map_key.GetUInt64Value()); + } + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT32: { + auto value = map_key.GetUInt32Value(); + return hash()(map_key.GetUInt32Value()); + } + case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_BOOL: { + return hash()(map_key.GetBoolValue()); + } + } + GOOGLE_LOG(FATAL) << "Can't get here."; + return 0; + } + bool operator()(const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key1, + const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key2) const { + return map_key1 < map_key2; + } +}; +} // namespace std + +namespace google { +namespace protobuf { namespace internal { class ContendedMapCleanTest; @@ -791,48 +838,6 @@ class PROTOBUF_EXPORT MapIterator { } // namespace protobuf } // namespace google -namespace std { -template <> -struct hash<::PROTOBUF_NAMESPACE_ID::MapKey> { - size_t operator()(const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key) const { - switch (map_key.type()) { - case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_DOUBLE: - case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_FLOAT: - case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_ENUM: - case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_MESSAGE: - GOOGLE_LOG(FATAL) << "Unsupported"; - break; - case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_STRING: - return hash()(map_key.GetStringValue()); - case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT64: { - auto value = map_key.GetInt64Value(); - return hash()(value); - } - case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT32: { - auto value = map_key.GetInt32Value(); - return hash()(map_key.GetInt32Value()); - } - case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT64: { - auto value = map_key.GetUInt64Value(); - return hash()(map_key.GetUInt64Value()); - } - case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT32: { - auto value = map_key.GetUInt32Value(); - return hash()(map_key.GetUInt32Value()); - } - case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_BOOL: { - return hash()(map_key.GetBoolValue()); - } - } - GOOGLE_LOG(FATAL) << "Can't get here."; - return 0; - } - bool operator()(const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key1, - const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key2) const { - return map_key1 < map_key2; - } -}; -} // namespace std #include #endif // GOOGLE_PROTOBUF_MAP_FIELD_H__ diff --git a/src/google/protobuf/map_field_lite.h b/src/google/protobuf/map_field_lite.h index db0ddc9446..240903be9c 100644 --- a/src/google/protobuf/map_field_lite.h +++ b/src/google/protobuf/map_field_lite.h @@ -85,7 +85,7 @@ class MapFieldLite { // Used in the implementation of parsing. Caller should take the ownership iff // arena_ is NULL. EntryType* NewEntry() const { - return Arena::CreateMessage(map_.arena_); + return Arena::CreateMessage(map_.arena()); } // Used in the implementation of serializing enum value type. Caller should // take the ownership iff arena_ is NULL. diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc index 9256f0e97f..3eb46a0f57 100644 --- a/src/google/protobuf/map_test.cc +++ b/src/google/protobuf/map_test.cc @@ -982,13 +982,10 @@ TEST_F(MapImplTest, CopyAssignMapIterator) { TEST_F(MapImplTest, SpaceUsed) { constexpr size_t kMinCap = 8; - constexpr size_t kInnerMapOverhead = sizeof(size_t) * 4 + sizeof(void*) * 2; Map m; - // To check the current overhead of an empty map. - // Ideally this should be zero. - EXPECT_EQ(m.SpaceUsedExcludingSelfLong(), - sizeof(void*) * kMinCap + kInnerMapOverhead); + // An newly constructed map should have no space used. + EXPECT_EQ(m.SpaceUsedExcludingSelfLong(), 0); size_t capacity = kMinCap; for (int i = 0; i < 100; ++i) { @@ -998,7 +995,7 @@ TEST_F(MapImplTest, SpaceUsed) { capacity *= 2; } EXPECT_EQ(m.SpaceUsedExcludingSelfLong(), - sizeof(void*) * capacity + kInnerMapOverhead + + sizeof(void*) * capacity + m.size() * sizeof(std::pair, void*>)); } @@ -1007,7 +1004,7 @@ TEST_F(MapImplTest, SpaceUsed) { std::string str = "Some arbitrarily large string"; m2[str] = 1; EXPECT_EQ(m2.SpaceUsedExcludingSelfLong(), - sizeof(void*) * kMinCap + kInnerMapOverhead + + sizeof(void*) * kMinCap + sizeof(std::pair, void*>) + internal::StringSpaceUsedExcludingSelfLong(str)); @@ -1015,7 +1012,7 @@ TEST_F(MapImplTest, SpaceUsed) { Map m3; m3[0].set_optional_string(str); EXPECT_EQ(m3.SpaceUsedExcludingSelfLong(), - sizeof(void*) * kMinCap + kInnerMapOverhead + + sizeof(void*) * kMinCap + sizeof(std::pair, void*>) + m3[0].SpaceUsedLong() - sizeof(m3[0])); } diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h index aba35becc7..7908544286 100644 --- a/src/google/protobuf/map_type_handler.h +++ b/src/google/protobuf/map_type_handler.h @@ -163,12 +163,9 @@ class MapTypeHandler { // SpaceUsedInMapEntry: Return bytes used by value in MapEntry, excluding // those already calculate in sizeof(MapField). static inline size_t SpaceUsedInMapEntryLong(const Type* value); - // Assign default value to given instance. - static inline void AssignDefaultValue(Type** value); // Return default instance if value is not initialized when calling const // reference accessor. - static inline const Type& DefaultIfNotInitialized(const Type* value, - const Type* default_value); + static inline const Type& DefaultIfNotInitialized(const Type* value); // Check if all required fields have values set. static inline bool IsInitialized(Type* value); }; @@ -206,9 +203,8 @@ class MapTypeHandler { TypeOnMemory* to, Arena* arena); \ static inline void Clear(TypeOnMemory* value, Arena* arena); \ static inline size_t SpaceUsedInMapEntryLong(const TypeOnMemory& value); \ - static inline void AssignDefaultValue(TypeOnMemory* value); \ static inline const MapEntryAccessorType& DefaultIfNotInitialized( \ - const TypeOnMemory& value, const TypeOnMemory& default_value); \ + const TypeOnMemory& value); \ static inline bool IsInitialized(const TypeOnMemory& value); \ static void DeleteNoArena(TypeOnMemory& value); \ static inline void Initialize(TypeOnMemory* value, Arena* arena); \ @@ -525,12 +521,6 @@ void MapTypeHandler::DeleteNoArena( delete ptr; } -template -inline void MapTypeHandler::AssignDefaultValue(Type** value) { - *value = const_cast(Type::internal_default_instance()); -} - template inline void MapTypeHandler::Initialize( Type** x, Arena* /* arena */) { @@ -551,8 +541,8 @@ inline Type* MapTypeHandler::EnsureMutable( template inline const Type& MapTypeHandler::DefaultIfNotInitialized( - const Type* value, const Type* default_value) { - return value != NULL ? *value : *default_value; + const Type* value) { + return value != NULL ? *value : *Type::internal_default_instance(); } template @@ -594,10 +584,6 @@ inline bool MapTypeHandler::IsInitialized( } \ template \ inline void \ - MapTypeHandler::AssignDefaultValue( \ - TypeOnMemory* /* value */) {} \ - template \ - inline void \ MapTypeHandler::Initialize( \ TypeOnMemory* value, Arena* /* arena */) { \ value->UnsafeSetDefault(&internal::GetEmptyStringAlreadyInited()); \ @@ -612,9 +598,8 @@ inline bool MapTypeHandler::IsInitialized( template \ inline const typename MapTypeHandler::MapEntryAccessorType& \ - MapTypeHandler:: \ - DefaultIfNotInitialized(const TypeOnMemory& value, \ - const TypeOnMemory& /* default_value */) { \ + MapTypeHandler::DefaultIfNotInitialized(const TypeOnMemory& value) { \ return value.Get(); \ } \ template \ @@ -627,63 +612,58 @@ STRING_OR_BYTES_HANDLER_FUNCTIONS(STRING) STRING_OR_BYTES_HANDLER_FUNCTIONS(BYTES) #undef STRING_OR_BYTES_HANDLER_FUNCTIONS -#define PRIMITIVE_HANDLER_FUNCTIONS(FieldType) \ - template \ - inline const typename MapTypeHandler::MapEntryAccessorType& \ - MapTypeHandler::GetExternalReference(const TypeOnMemory& value) { \ - return value; \ - } \ - template \ - inline size_t MapTypeHandler:: \ - SpaceUsedInMapEntryLong(const TypeOnMemory& /* value */) { \ - return 0; \ - } \ - template \ - inline void MapTypeHandler::Clear( \ - TypeOnMemory* value, Arena* /* arena */) { \ - *value = 0; \ - } \ - template \ - inline void MapTypeHandler::Merge( \ - const MapEntryAccessorType& from, TypeOnMemory* to, \ - Arena* /* arena */) { \ - *to = from; \ - } \ - template \ - inline void MapTypeHandler::DeleteNoArena(TypeOnMemory& /* x */) {} \ - template \ - inline void \ - MapTypeHandler::AssignDefaultValue( \ - TypeOnMemory* /* value */) {} \ - template \ - inline void \ - MapTypeHandler::Initialize( \ - TypeOnMemory* value, Arena* /* arena */) { \ - *value = 0; \ - } \ - template \ - inline typename MapTypeHandler::MapEntryAccessorType* \ - MapTypeHandler::EnsureMutable( \ - TypeOnMemory* value, Arena* /* arena */) { \ - return value; \ - } \ - template \ - inline const typename MapTypeHandler::MapEntryAccessorType& \ - MapTypeHandler:: \ - DefaultIfNotInitialized(const TypeOnMemory& value, \ - const TypeOnMemory& /* default_value */) { \ - return value; \ - } \ - template \ - inline bool \ - MapTypeHandler::IsInitialized( \ - const TypeOnMemory& /* value */) { \ - return true; \ +#define PRIMITIVE_HANDLER_FUNCTIONS(FieldType) \ + template \ + inline const typename MapTypeHandler::MapEntryAccessorType& \ + MapTypeHandler::GetExternalReference(const TypeOnMemory& value) { \ + return value; \ + } \ + template \ + inline size_t MapTypeHandler:: \ + SpaceUsedInMapEntryLong(const TypeOnMemory& /* value */) { \ + return 0; \ + } \ + template \ + inline void MapTypeHandler::Clear( \ + TypeOnMemory* value, Arena* /* arena */) { \ + *value = 0; \ + } \ + template \ + inline void MapTypeHandler::Merge( \ + const MapEntryAccessorType& from, TypeOnMemory* to, \ + Arena* /* arena */) { \ + *to = from; \ + } \ + template \ + inline void MapTypeHandler::DeleteNoArena(TypeOnMemory& /* x */) {} \ + template \ + inline void \ + MapTypeHandler::Initialize( \ + TypeOnMemory* value, Arena* /* arena */) { \ + *value = 0; \ + } \ + template \ + inline typename MapTypeHandler::MapEntryAccessorType* \ + MapTypeHandler::EnsureMutable( \ + TypeOnMemory* value, Arena* /* arena */) { \ + return value; \ + } \ + template \ + inline const typename MapTypeHandler::MapEntryAccessorType& \ + MapTypeHandler::DefaultIfNotInitialized(const TypeOnMemory& value) { \ + return value; \ + } \ + template \ + inline bool \ + MapTypeHandler::IsInitialized( \ + const TypeOnMemory& /* value */) { \ + return true; \ } PRIMITIVE_HANDLER_FUNCTIONS(INT64) PRIMITIVE_HANDLER_FUNCTIONS(UINT64) diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc index cfea396a4b..fde10cf617 100644 --- a/src/google/protobuf/message.cc +++ b/src/google/protobuf/message.cc @@ -162,6 +162,10 @@ size_t Message::SpaceUsedLong() const { return GetReflection()->SpaceUsedLong(*this); } +size_t Message::GetInvariantPerBuild(size_t salt) { + return salt; +} + // ============================================================================= // MessageFactory diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index 24b48debd1..d0ca0366a5 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -170,6 +170,9 @@ class CelMapReflectionFriend; // field_backed_map_impl.cc namespace internal { class MapFieldPrinterHelper; // text_format.cc } +namespace util { +class MessageDifferencer; +} namespace internal { @@ -362,6 +365,9 @@ class PROTOBUF_EXPORT Message : public MessageLite { inline explicit Message(Arena* arena) : MessageLite(arena) {} + protected: + static size_t GetInvariantPerBuild(size_t salt); + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Message); }; @@ -945,6 +951,7 @@ class PROTOBUF_EXPORT Reflection final { friend class ::PROTOBUF_NAMESPACE_ID::AssignDescriptorsHelper; friend class DynamicMessageFactory; friend class python::MapReflectionFriend; + friend class util::MessageDifferencer; #define GOOGLE_PROTOBUF_HAS_CEL_MAP_REFLECTION_FRIEND friend class expr::CelMapReflectionFriend; friend class internal::MapFieldReflectionTest; @@ -1020,6 +1027,8 @@ class PROTOBUF_EXPORT Reflection final { template const Type& DefaultRaw(const FieldDescriptor* field) const; + const Message* GetDefaultMessageInstance(const FieldDescriptor* field) const; + inline const uint32* GetHasBits(const Message& message) const; inline uint32* MutableHasBits(Message* message) const; inline uint32 GetOneofCase(const Message& message, diff --git a/src/google/protobuf/message_unittest.inc b/src/google/protobuf/message_unittest.inc index 4b950439a1..1b0aa333a4 100644 --- a/src/google/protobuf/message_unittest.inc +++ b/src/google/protobuf/message_unittest.inc @@ -48,7 +48,6 @@ #include #include -#include #include #include #include @@ -59,6 +58,7 @@ #include #include #include +#include #include diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index 07800f5554..c1c4774685 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -334,13 +334,12 @@ class RepeatedField final { int total_size_; struct Rep { Arena* arena; - Element elements[1]; + // Here we declare a huge array as a way of approximating C's "flexible + // array member" feature without relying on undefined behavior. + Element elements[(std::numeric_limits::max() - 2 * sizeof(Arena*)) / + sizeof(Element)]; }; - // We can not use sizeof(Rep) - sizeof(Element) due to the trailing padding on - // the struct. We can not use sizeof(Arena*) as well because there might be - // a "gap" after the field arena and before the field elements (e.g., when - // Element is double and pointer is 32bit). - static const size_t kRepHeaderSize; + static constexpr size_t kRepHeaderSize = offsetof(Rep, elements); // If total_size_ == 0 this points to an Arena otherwise it points to the // elements member of a Rep struct. Using this invariant allows the storage of @@ -381,14 +380,14 @@ class RepeatedField final { void CopyArray(Element* to, const Element* from, int size); // Internal helper to delete all elements and deallocate the storage. - // If Element has a trivial destructor (for example, if it's a fundamental - // type, like int32), the loop will be removed by the optimizer. void InternalDeallocate(Rep* rep, int size) { if (rep != NULL) { Element* e = &rep->elements[0]; - Element* limit = &rep->elements[size]; - for (; e < limit; e++) { - e->~Element(); + if (!std::is_trivial::value) { + Element* limit = &rep->elements[size]; + for (; e < limit; e++) { + e->~Element(); + } } if (rep->arena == NULL) { #if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation) @@ -487,10 +486,6 @@ class RepeatedField final { friend class ::google::protobuf::internal::ParseContext; }; -template -const size_t RepeatedField::kRepHeaderSize = - reinterpret_cast(&reinterpret_cast(16)->elements[0]) - 16; - namespace internal { template class RepeatedPtrIterator; @@ -741,9 +736,12 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { int total_size_; struct Rep { int allocated_size; - void* elements[1]; + // Here we declare a huge array as a way of approximating C's "flexible + // array member" feature without relying on undefined behavior. + void* elements[(std::numeric_limits::max() - 2 * sizeof(int)) / + sizeof(void*)]; }; - static constexpr size_t kRepHeaderSize = sizeof(Rep) - sizeof(void*); + static constexpr size_t kRepHeaderSize = offsetof(Rep, elements); Rep* rep_; template diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc index 26b2384729..8de9504dc0 100644 --- a/src/google/protobuf/repeated_field_unittest.cc +++ b/src/google/protobuf/repeated_field_unittest.cc @@ -328,10 +328,18 @@ TEST(RepeatedField, ReserveHuge) { EXPECT_GE(huge_field.Capacity(), min_clamping_size); ASSERT_LT(huge_field.Capacity(), std::numeric_limits::max() - 1); +#ifndef ADDRESS_SANITIZER + // The array containing all the fields is, in theory, up to MAXINT-1 in size. + // However, some compilers can't handle a struct whose size is larger + // than 2GB, and the protocol buffer format doesn't handle more than 2GB of + // data at once, either. So we limit it, but the code below accesses beyond + // that limit. + // Allocation may return more memory than we requested. However, the updated // size must still be clamped to a valid range. huge_field.Reserve(huge_field.Capacity() + 1); EXPECT_EQ(huge_field.Capacity(), std::numeric_limits::max()); +#endif #endif // PROTOBUF_TEST_ALLOW_LARGE_ALLOC } diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc index 059456f287..925686972a 100644 --- a/src/google/protobuf/source_context.pb.cc +++ b/src/google/protobuf/source_context.pb.cc @@ -28,7 +28,6 @@ static void InitDefaultsscc_info_SourceContext_google_2fprotobuf_2fsource_5fcont new (ptr) PROTOBUF_NAMESPACE_ID::SourceContext(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::SourceContext::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_SourceContext_google_2fprotobuf_2fsource_5fcontext_2eproto = @@ -81,8 +80,6 @@ PROTOBUF_NAMESPACE_OPEN // =================================================================== -void SourceContext::InitAsDefaultInstance() { -} class SourceContext::_Internal { public: }; diff --git a/src/google/protobuf/source_context.pb.h b/src/google/protobuf/source_context.pb.h index 6ebb809d8e..a565129e5f 100644 --- a/src/google/protobuf/source_context.pb.h +++ b/src/google/protobuf/source_context.pb.h @@ -102,7 +102,6 @@ class PROTOBUF_EXPORT SourceContext PROTOBUF_FINAL : } static const SourceContext& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const SourceContext* internal_default_instance() { return reinterpret_cast( &_SourceContext_default_instance_); diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc index 54c928342b..d94b86d2c7 100644 --- a/src/google/protobuf/struct.pb.cc +++ b/src/google/protobuf/struct.pb.cc @@ -27,12 +27,6 @@ class StructDefaultTypeInternal { class ValueDefaultTypeInternal { public: ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; - int null_value_; - double number_value_; - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr string_value_; - bool bool_value_; - const PROTOBUF_NAMESPACE_ID::Struct* struct_value_; - const PROTOBUF_NAMESPACE_ID::ListValue* list_value_; } _Value_default_instance_; class ListValueDefaultTypeInternal { public: @@ -61,10 +55,6 @@ static void InitDefaultsscc_info_ListValue_google_2fprotobuf_2fstruct_2eproto() new (ptr) PROTOBUF_NAMESPACE_ID::ListValue(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse::InitAsDefaultInstance(); - PROTOBUF_NAMESPACE_ID::Struct::InitAsDefaultInstance(); - PROTOBUF_NAMESPACE_ID::Value::InitAsDefaultInstance(); - PROTOBUF_NAMESPACE_ID::ListValue::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_ListValue_google_2fprotobuf_2fstruct_2eproto = @@ -95,12 +85,12 @@ const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_google_2fprotobuf_2fstruct_2ep ~0u, // no _extensions_ PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Value, _oneof_case_[0]), ~0u, // no _weak_field_map_ - offsetof(PROTOBUF_NAMESPACE_ID::ValueDefaultTypeInternal, null_value_), - offsetof(PROTOBUF_NAMESPACE_ID::ValueDefaultTypeInternal, number_value_), - offsetof(PROTOBUF_NAMESPACE_ID::ValueDefaultTypeInternal, string_value_), - offsetof(PROTOBUF_NAMESPACE_ID::ValueDefaultTypeInternal, bool_value_), - offsetof(PROTOBUF_NAMESPACE_ID::ValueDefaultTypeInternal, struct_value_), - offsetof(PROTOBUF_NAMESPACE_ID::ValueDefaultTypeInternal, list_value_), + ::PROTOBUF_NAMESPACE_ID::internal::kInvalidFieldOffsetTag, + ::PROTOBUF_NAMESPACE_ID::internal::kInvalidFieldOffsetTag, + ::PROTOBUF_NAMESPACE_ID::internal::kInvalidFieldOffsetTag, + ::PROTOBUF_NAMESPACE_ID::internal::kInvalidFieldOffsetTag, + ::PROTOBUF_NAMESPACE_ID::internal::kInvalidFieldOffsetTag, + ::PROTOBUF_NAMESPACE_ID::internal::kInvalidFieldOffsetTag, PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::Value, kind_), ~0u, // no _has_bits_ PROTOBUF_FIELD_OFFSET(PROTOBUF_NAMESPACE_ID::ListValue, _internal_metadata_), @@ -190,8 +180,6 @@ void Struct_FieldsEntry_DoNotUse::MergeFrom( // =================================================================== -void Struct::InitAsDefaultInstance() { -} class Struct::_Internal { public: }; @@ -428,17 +416,6 @@ void Struct::InternalSwap(Struct* other) { // =================================================================== -void Value::InitAsDefaultInstance() { - PROTOBUF_NAMESPACE_ID::_Value_default_instance_.null_value_ = 0; - PROTOBUF_NAMESPACE_ID::_Value_default_instance_.number_value_ = 0; - PROTOBUF_NAMESPACE_ID::_Value_default_instance_.string_value_.UnsafeSetDefault( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); - PROTOBUF_NAMESPACE_ID::_Value_default_instance_.bool_value_ = false; - PROTOBUF_NAMESPACE_ID::_Value_default_instance_.struct_value_ = const_cast< PROTOBUF_NAMESPACE_ID::Struct*>( - PROTOBUF_NAMESPACE_ID::Struct::internal_default_instance()); - PROTOBUF_NAMESPACE_ID::_Value_default_instance_.list_value_ = const_cast< PROTOBUF_NAMESPACE_ID::ListValue*>( - PROTOBUF_NAMESPACE_ID::ListValue::internal_default_instance()); -} class Value::_Internal { public: static const PROTOBUF_NAMESPACE_ID::Struct& struct_value(const Value* msg); @@ -885,8 +862,6 @@ void Value::InternalSwap(Value* other) { // =================================================================== -void ListValue::InitAsDefaultInstance() { -} class ListValue::_Internal { public: }; diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h index 772f1a4da0..b065bd2064 100644 --- a/src/google/protobuf/struct.pb.h +++ b/src/google/protobuf/struct.pb.h @@ -172,7 +172,6 @@ class PROTOBUF_EXPORT Struct PROTOBUF_FINAL : } static const Struct& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const Struct* internal_default_instance() { return reinterpret_cast( &_Struct_default_instance_); @@ -332,7 +331,6 @@ class PROTOBUF_EXPORT Value PROTOBUF_FINAL : KIND_NOT_SET = 0, }; - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const Value* internal_default_instance() { return reinterpret_cast( &_Value_default_instance_); @@ -577,7 +575,6 @@ class PROTOBUF_EXPORT ListValue PROTOBUF_FINAL : } static const ListValue& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const ListValue* internal_default_instance() { return reinterpret_cast( &_ListValue_default_instance_); @@ -977,7 +974,7 @@ inline PROTOBUF_NAMESPACE_ID::Struct* Value::release_struct_value() { inline const PROTOBUF_NAMESPACE_ID::Struct& Value::_internal_struct_value() const { return _internal_has_struct_value() ? *kind_.struct_value_ - : *reinterpret_cast< PROTOBUF_NAMESPACE_ID::Struct*>(&PROTOBUF_NAMESPACE_ID::_Struct_default_instance_); + : reinterpret_cast< PROTOBUF_NAMESPACE_ID::Struct&>(PROTOBUF_NAMESPACE_ID::_Struct_default_instance_); } inline const PROTOBUF_NAMESPACE_ID::Struct& Value::struct_value() const { // @@protoc_insertion_point(field_get:google.protobuf.Value.struct_value) @@ -1050,7 +1047,7 @@ inline PROTOBUF_NAMESPACE_ID::ListValue* Value::release_list_value() { inline const PROTOBUF_NAMESPACE_ID::ListValue& Value::_internal_list_value() const { return _internal_has_list_value() ? *kind_.list_value_ - : *reinterpret_cast< PROTOBUF_NAMESPACE_ID::ListValue*>(&PROTOBUF_NAMESPACE_ID::_ListValue_default_instance_); + : reinterpret_cast< PROTOBUF_NAMESPACE_ID::ListValue&>(PROTOBUF_NAMESPACE_ID::_ListValue_default_instance_); } inline const PROTOBUF_NAMESPACE_ID::ListValue& Value::list_value() const { // @@protoc_insertion_point(field_get:google.protobuf.Value.list_value) diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc index 58ed5a4717..11e9b0001f 100644 --- a/src/google/protobuf/text_format.cc +++ b/src/google/protobuf/text_format.cc @@ -286,6 +286,15 @@ class TextFormat::Parser::ParserImpl { // Consume fields until we cannot do so anymore. while (true) { if (LookingAtType(io::Tokenizer::TYPE_END)) { + // Ensures recursion limit properly unwinded, but only for success + // cases. This implicitly avoids the check when `Parse` returns false + // via `DO(...)`. + GOOGLE_DCHECK(had_errors_ || recursion_limit_ == initial_recursion_limit_) + << "Recursion limit at end of parse should be " + << initial_recursion_limit_ << ", but was " << recursion_limit_ + << ". Difference of " << initial_recursion_limit_ - recursion_limit_ + << " stack frames not accounted for stack unwind."; + return !had_errors_; } @@ -832,10 +841,19 @@ class TextFormat::Parser::ParserImpl { } bool SkipFieldValue() { + if (--recursion_limit_ < 0) { + ReportError( + StrCat("Message is too deep, the parser exceeded the " + "configured recursion limit of ", + initial_recursion_limit_, ".")); + return false; + } + if (LookingAtType(io::Tokenizer::TYPE_STRING)) { while (LookingAtType(io::Tokenizer::TYPE_STRING)) { tokenizer_.Next(); } + ++recursion_limit_; return true; } if (TryConsume("[")) { @@ -850,6 +868,7 @@ class TextFormat::Parser::ParserImpl { } DO(Consume(",")); } + ++recursion_limit_; return true; } // Possible field values other than string: @@ -879,6 +898,7 @@ class TextFormat::Parser::ParserImpl { !LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { std::string text = tokenizer_.current().text; ReportError("Cannot skip field value, unexpected token: " + text); + ++recursion_limit_; return false; } // Combination of '-' and TYPE_IDENTIFIER may result in an invalid field @@ -893,10 +913,12 @@ class TextFormat::Parser::ParserImpl { if (text != "inf" && text != "infinity" && text != "nan") { ReportError("Invalid float number: " + text); + ++recursion_limit_; return false; } } tokenizer_.Next(); + ++recursion_limit_; return true; } @@ -1432,7 +1454,7 @@ bool TextFormat::Parser::Parse(io::ZeroCopyInputStream* input, return MergeUsingImpl(input, output, &parser); } -bool TextFormat::Parser::ParseFromString(const std::string& input, +bool TextFormat::Parser::ParseFromString(ConstStringParam input, Message* output) { DO(CheckParseInputSize(input, error_collector_)); io::ArrayInputStream input_stream(input.data(), input.size()); @@ -1497,7 +1519,7 @@ bool TextFormat::Parser::ParseFieldValueFromString(const std::string& input, return Parser().Merge(input, output); } -/* static */ bool TextFormat::ParseFromString(const std::string& input, +/* static */ bool TextFormat::ParseFromString(ConstStringParam input, Message* output) { return Parser().ParseFromString(input, output); } @@ -1525,9 +1547,9 @@ class StringBaseTextGenerator : public TextFormat::BaseTextGenerator { // Some compilers do not support ref-qualifiers even in C++11 mode. // Disable the optimization for now and revisit it later. -#if 0 // LANG_CXX11 +#if 0 // LANG_CXX11 std::string Consume() && { return std::move(output_); } -#else // !LANG_CXX11 +#else // !LANG_CXX11 const std::string& Get() { return output_; } #endif // LANG_CXX11 diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h index 9eb2eebf08..e4b32557f4 100644 --- a/src/google/protobuf/text_format.h +++ b/src/google/protobuf/text_format.h @@ -454,7 +454,7 @@ class PROTOBUF_EXPORT TextFormat { // google::protobuf::MessageLite::ParseFromString(). static bool Parse(io::ZeroCopyInputStream* input, Message* output); // Like Parse(), but reads directly from a string. - static bool ParseFromString(const std::string& input, Message* output); + static bool ParseFromString(ConstStringParam input, Message* output); // Like Parse(), but the data is merged into the given message, as if // using Message::MergeFrom(). @@ -531,7 +531,7 @@ class PROTOBUF_EXPORT TextFormat { // Like TextFormat::Parse(). bool Parse(io::ZeroCopyInputStream* input, Message* output); // Like TextFormat::ParseFromString(). - bool ParseFromString(const std::string& input, Message* output); + bool ParseFromString(ConstStringParam input, Message* output); // Like TextFormat::Merge(). bool Merge(io::ZeroCopyInputStream* input, Message* output); // Like TextFormat::MergeFromString(). diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc index 0ae2def2dc..e0e4177143 100644 --- a/src/google/protobuf/text_format_unittest.cc +++ b/src/google/protobuf/text_format_unittest.cc @@ -42,7 +42,6 @@ #include #include -#include #include #include #include @@ -58,6 +57,7 @@ #include #include #include +#include #include @@ -1409,9 +1409,8 @@ class TextFormatParserTest : public testing::Test { parser_.RecordErrorsTo(&error_collector); EXPECT_EQ(expected_result, parser_.ParseFromString(input, proto)) << input << " -> " << proto->DebugString(); - EXPECT_EQ( - StrCat(line) + ":" + StrCat(col) + ": " + message + "\n", - error_collector.text_); + EXPECT_EQ(StrCat(line, ":", col, ": ", message, "\n"), + error_collector.text_); parser_.RecordErrorsTo(nullptr); } @@ -1920,18 +1919,43 @@ TEST_F(TextFormatParserTest, SetRecursionLimit) { ExpectSuccessAndTree(input, &message, nullptr); } -TEST_F(TextFormatParserTest, SetRecursionLimitUnknownField) { +TEST_F(TextFormatParserTest, SetRecursionLimitUnknownFieldValue) { + const char* format = "[$0]"; + std::string input = "\"test_value\""; + for (int i = 0; i < 99; ++i) input = strings::Substitute(format, input); + std::string not_deep_input = StrCat("unknown_nested_array: ", input); + + parser_.AllowUnknownField(true); + parser_.SetRecursionLimit(100); + + unittest::NestedTestAllTypes message; + ExpectSuccessAndTree(not_deep_input, &message, nullptr); + + input = strings::Substitute(format, input); + std::string deep_input = StrCat("unknown_nested_array: ", input); + ExpectMessage( + deep_input, + "WARNING:Message type \"protobuf_unittest.NestedTestAllTypes\" has no " + "field named \"unknown_nested_array\".\n1:123: Message is too deep, the " + "parser exceeded the configured recursion limit of 100.", + 1, 21, &message, false); + + parser_.SetRecursionLimit(101); + ExpectSuccessAndTree(deep_input, &message, nullptr); +} + +TEST_F(TextFormatParserTest, SetRecursionLimitUnknownFieldMessage) { const char* format = "unknown_child: { $0 }"; std::string input; for (int i = 0; i < 100; ++i) input = strings::Substitute(format, input); parser_.AllowUnknownField(true); + parser_.SetRecursionLimit(100); unittest::NestedTestAllTypes message; ExpectSuccessAndTree(input, &message, nullptr); input = strings::Substitute(format, input); - parser_.SetRecursionLimit(100); ExpectMessage( input, "WARNING:Message type \"protobuf_unittest.NestedTestAllTypes\" has no " diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc index 1458bc000a..65c8d5469a 100644 --- a/src/google/protobuf/timestamp.pb.cc +++ b/src/google/protobuf/timestamp.pb.cc @@ -28,7 +28,6 @@ static void InitDefaultsscc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto new (ptr) PROTOBUF_NAMESPACE_ID::Timestamp(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::Timestamp::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto = @@ -82,8 +81,6 @@ PROTOBUF_NAMESPACE_OPEN // =================================================================== -void Timestamp::InitAsDefaultInstance() { -} class Timestamp::_Internal { public: }; diff --git a/src/google/protobuf/timestamp.pb.h b/src/google/protobuf/timestamp.pb.h index 3429d7617b..e8476f6095 100644 --- a/src/google/protobuf/timestamp.pb.h +++ b/src/google/protobuf/timestamp.pb.h @@ -102,7 +102,6 @@ class PROTOBUF_EXPORT Timestamp PROTOBUF_FINAL : } static const Timestamp& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const Timestamp* internal_default_instance() { return reinterpret_cast( &_Timestamp_default_instance_); diff --git a/src/google/protobuf/timestamp.proto b/src/google/protobuf/timestamp.proto index a343d81928..3b2df6d911 100644 --- a/src/google/protobuf/timestamp.proto +++ b/src/google/protobuf/timestamp.proto @@ -91,7 +91,16 @@ option objc_class_prefix = "GPB"; // .setNanos((int) ((millis % 1000) * 1000000)).build(); // // -// Example 5: Compute Timestamp from current time in Python. +// Example 5: Compute Timestamp from Java `Instant.now()`. +// +// Instant now = Instant.now(); +// +// Timestamp timestamp = +// Timestamp.newBuilder().setSeconds(now.getEpochSecond()) +// .setNanos(now.getNano()).build(); +// +// +// Example 6: Compute Timestamp from current time in Python. // // timestamp = Timestamp() // timestamp.GetCurrentTime() diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc index 8da9559110..01a79f976b 100644 --- a/src/google/protobuf/type.pb.cc +++ b/src/google/protobuf/type.pb.cc @@ -49,7 +49,6 @@ static void InitDefaultsscc_info_Enum_google_2fprotobuf_2ftype_2eproto() { new (ptr) PROTOBUF_NAMESPACE_ID::Enum(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::Enum::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<3> scc_info_Enum_google_2fprotobuf_2ftype_2eproto = @@ -66,7 +65,6 @@ static void InitDefaultsscc_info_EnumValue_google_2fprotobuf_2ftype_2eproto() { new (ptr) PROTOBUF_NAMESPACE_ID::EnumValue(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::EnumValue::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_EnumValue_google_2fprotobuf_2ftype_2eproto = @@ -81,7 +79,6 @@ static void InitDefaultsscc_info_Field_google_2fprotobuf_2ftype_2eproto() { new (ptr) PROTOBUF_NAMESPACE_ID::Field(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::Field::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Field_google_2fprotobuf_2ftype_2eproto = @@ -96,7 +93,6 @@ static void InitDefaultsscc_info_Option_google_2fprotobuf_2ftype_2eproto() { new (ptr) PROTOBUF_NAMESPACE_ID::Option(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::Option::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Option_google_2fprotobuf_2ftype_2eproto = @@ -111,7 +107,6 @@ static void InitDefaultsscc_info_Type_google_2fprotobuf_2ftype_2eproto() { new (ptr) PROTOBUF_NAMESPACE_ID::Type(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::Type::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<3> scc_info_Type_google_2fprotobuf_2ftype_2eproto = @@ -354,10 +349,6 @@ bool Syntax_IsValid(int value) { // =================================================================== -void Type::InitAsDefaultInstance() { - PROTOBUF_NAMESPACE_ID::_Type_default_instance_._instance.get_mutable()->source_context_ = const_cast< PROTOBUF_NAMESPACE_ID::SourceContext*>( - PROTOBUF_NAMESPACE_ID::SourceContext::internal_default_instance()); -} class Type::_Internal { public: static const PROTOBUF_NAMESPACE_ID::SourceContext& source_context(const Type* msg); @@ -747,8 +738,6 @@ void Type::InternalSwap(Type* other) { // =================================================================== -void Field::InitAsDefaultInstance() { -} class Field::_Internal { public: }; @@ -1232,10 +1221,6 @@ void Field::InternalSwap(Field* other) { // =================================================================== -void Enum::InitAsDefaultInstance() { - PROTOBUF_NAMESPACE_ID::_Enum_default_instance_._instance.get_mutable()->source_context_ = const_cast< PROTOBUF_NAMESPACE_ID::SourceContext*>( - PROTOBUF_NAMESPACE_ID::SourceContext::internal_default_instance()); -} class Enum::_Internal { public: static const PROTOBUF_NAMESPACE_ID::SourceContext& source_context(const Enum* msg); @@ -1588,8 +1573,6 @@ void Enum::InternalSwap(Enum* other) { // =================================================================== -void EnumValue::InitAsDefaultInstance() { -} class EnumValue::_Internal { public: }; @@ -1856,10 +1839,6 @@ void EnumValue::InternalSwap(EnumValue* other) { // =================================================================== -void Option::InitAsDefaultInstance() { - PROTOBUF_NAMESPACE_ID::_Option_default_instance_._instance.get_mutable()->value_ = const_cast< PROTOBUF_NAMESPACE_ID::Any*>( - PROTOBUF_NAMESPACE_ID::Any::internal_default_instance()); -} class Option::_Internal { public: static const PROTOBUF_NAMESPACE_ID::Any& value(const Option* msg); diff --git a/src/google/protobuf/type.pb.h b/src/google/protobuf/type.pb.h index c843794555..443aeb472a 100644 --- a/src/google/protobuf/type.pb.h +++ b/src/google/protobuf/type.pb.h @@ -215,7 +215,6 @@ class PROTOBUF_EXPORT Type PROTOBUF_FINAL : } static const Type& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const Type* internal_default_instance() { return reinterpret_cast( &_Type_default_instance_); @@ -456,7 +455,6 @@ class PROTOBUF_EXPORT Field PROTOBUF_FINAL : } static const Field& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const Field* internal_default_instance() { return reinterpret_cast( &_Field_default_instance_); @@ -827,7 +825,6 @@ class PROTOBUF_EXPORT Enum PROTOBUF_FINAL : } static const Enum& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const Enum* internal_default_instance() { return reinterpret_cast( &_Enum_default_instance_); @@ -1042,7 +1039,6 @@ class PROTOBUF_EXPORT EnumValue PROTOBUF_FINAL : } static const EnumValue& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const EnumValue* internal_default_instance() { return reinterpret_cast( &_EnumValue_default_instance_); @@ -1217,7 +1213,6 @@ class PROTOBUF_EXPORT Option PROTOBUF_FINAL : } static const Option& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const Option* internal_default_instance() { return reinterpret_cast( &_Option_default_instance_); @@ -1577,8 +1572,8 @@ inline bool Type::has_source_context() const { } inline const PROTOBUF_NAMESPACE_ID::SourceContext& Type::_internal_source_context() const { const PROTOBUF_NAMESPACE_ID::SourceContext* p = source_context_; - return p != nullptr ? *p : *reinterpret_cast( - &PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_); + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_); } inline const PROTOBUF_NAMESPACE_ID::SourceContext& Type::source_context() const { // @@protoc_insertion_point(field_get:google.protobuf.Type.source_context) @@ -2209,8 +2204,8 @@ inline bool Enum::has_source_context() const { } inline const PROTOBUF_NAMESPACE_ID::SourceContext& Enum::_internal_source_context() const { const PROTOBUF_NAMESPACE_ID::SourceContext* p = source_context_; - return p != nullptr ? *p : *reinterpret_cast( - &PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_); + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_); } inline const PROTOBUF_NAMESPACE_ID::SourceContext& Enum::source_context() const { // @@protoc_insertion_point(field_get:google.protobuf.Enum.source_context) @@ -2497,8 +2492,8 @@ inline bool Option::has_value() const { } inline const PROTOBUF_NAMESPACE_ID::Any& Option::_internal_value() const { const PROTOBUF_NAMESPACE_ID::Any* p = value_; - return p != nullptr ? *p : *reinterpret_cast( - &PROTOBUF_NAMESPACE_ID::_Any_default_instance_); + return p != nullptr ? *p : reinterpret_cast( + PROTOBUF_NAMESPACE_ID::_Any_default_instance_); } inline const PROTOBUF_NAMESPACE_ID::Any& Option::value() const { // @@protoc_insertion_point(field_get:google.protobuf.Option.value) diff --git a/src/google/protobuf/unittest_lite.proto b/src/google/protobuf/unittest_lite.proto index 652966bb83..f501f509d1 100644 --- a/src/google/protobuf/unittest_lite.proto +++ b/src/google/protobuf/unittest_lite.proto @@ -49,6 +49,10 @@ message TestAllTypesLite { optional int64 cc = 2; } + message NestedMessage2 { + optional int32 dd = 1; + } + enum NestedEnum { FOO = 1; BAR = 2; @@ -163,6 +167,7 @@ message TestAllTypesLite { string oneof_string = 113; bytes oneof_bytes = 114; NestedMessage oneof_lazy_nested_message = 115 [lazy = true]; + NestedMessage2 oneof_nested_message2 = 117; } // Tests toString for non-repeated fields with a list suffix diff --git a/src/google/protobuf/util/field_comparator.h b/src/google/protobuf/util/field_comparator.h index 7b5ce52b82..9058bbef15 100644 --- a/src/google/protobuf/util/field_comparator.h +++ b/src/google/protobuf/util/field_comparator.h @@ -170,6 +170,7 @@ class PROTOBUF_EXPORT DefaultFieldComparator : public FieldComparator { // Defines the map to store the tolerances for floating point comparison. typedef std::map ToleranceMap; + friend class MessageDifferencer; // The following methods get executed when CompareFields is called for the // basic types (instead of submessages). They return true on success. One // can use ResultFromBoolean() to convert that boolean to a ComparisonResult diff --git a/src/google/protobuf/util/field_mask_util_test.cc b/src/google/protobuf/util/field_mask_util_test.cc index 9ed35e643b..f639b32678 100644 --- a/src/google/protobuf/util/field_mask_util_test.cc +++ b/src/google/protobuf/util/field_mask_util_test.cc @@ -33,12 +33,12 @@ #include #include -#include -#include #include #include #include #include +#include +#include namespace google { namespace protobuf { diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc index 71e2d2ea8f..1a9cc9bf41 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource.cc +++ b/src/google/protobuf/util/internal/protostream_objectsource.cc @@ -810,8 +810,8 @@ Status ProtoStreamObjectSource::RenderNonMessageField( const google::protobuf::Field* field, StringPiece field_name, ObjectWriter* ow) const { // Temporary buffers of different types. - uint32 buffer32; - uint64 buffer64; + uint32 buffer32 = 0; + uint64 buffer64 = 0; std::string strbuffer; switch (field->kind()) { case google::protobuf::Field::TYPE_BOOL: { diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc index 70861634d7..817109b02d 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter.cc +++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc @@ -588,6 +588,38 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject( if (field == nullptr) return this; + // Legacy JSON map is a list of key value pairs. Starts a map entry object. + if (options_.use_legacy_json_map_format && name.empty()) { + Push(name, IsAny(*field) ? Item::ANY : Item::MESSAGE, false, false); + return this; + } + + if (IsMap(*field)) { + // Begin a map. A map is triggered by a StartObject() call if the current + // field has a map type. + // A map type is always repeated, hence set is_list to true. + // Render + // "": [ + Push(name, Item::MAP, false, true); + return this; + } + + if (options_.disable_implicit_message_list) { + // If the incoming object is repeated, the top-level object on stack should + // be list. Report an error otherwise. + if (IsRepeated(*field) && !current_->is_list()) { + IncrementInvalidDepth(); + + if (!options_.suppress_implicit_message_list_error) { + InvalidValue( + field->name(), + "Starting an object in a repeated field but the parent object " + "is not a list"); + } + return this; + } + } + if (IsStruct(*field)) { // Start a struct object. // Render @@ -611,22 +643,6 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject( return this; } - // Legacy JSON map is a list of key value pairs. Starts a map entry object. - if (options_.use_legacy_json_map_format && name.empty()) { - Push(name, IsAny(*field) ? Item::ANY : Item::MESSAGE, false, false); - return this; - } - - if (IsMap(*field)) { - // Begin a map. A map is triggered by a StartObject() call if the current - // field has a map type. - // A map type is always repeated, hence set is_list to true. - // Render - // "": [ - Push(name, Item::MAP, false, true); - return this; - } - // A regular message type. Pass it directly to ProtoWriter. // Render // "": { diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h index f3aeb61f11..cc68c6b1b4 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter.h +++ b/src/google/protobuf/util/internal/protostream_objectwriter.h @@ -100,6 +100,13 @@ class PROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { // If true, accepts repeated key/value pair for a map proto field. bool use_legacy_json_map_format; + // If true, disable implicitly creating message list. + bool disable_implicit_message_list; + + // If true, suppress the error of implicitly creating message list when it + // is disabled. + bool suppress_implicit_message_list_error; + Options() : struct_integers_as_strings(false), ignore_unknown_fields(false), @@ -107,7 +114,9 @@ class PROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { use_lower_camel_for_enums(false), case_insensitive_enum_parsing(false), ignore_null_value_map_entry(false), - use_legacy_json_map_format(false) {} + use_legacy_json_map_format(false), + disable_implicit_message_list(false), + suppress_implicit_message_list_error(false) {} // Default instance of Options with all options set to defaults. static const Options& Defaults() { diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc index f5e0860c1c..829a18aae6 100644 --- a/src/google/protobuf/util/message_differencer.cc +++ b/src/google/protobuf/util/message_differencer.cc @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -916,6 +917,76 @@ bool MessageDifferencer::IsMatch( return match; } +bool MessageDifferencer::CompareMapFieldByMapReflection( + const Message& message1, const Message& message2, + const FieldDescriptor* map_field) { + const Reflection* reflection1 = message1.GetReflection(); + const Reflection* reflection2 = message2.GetReflection(); + const int count1 = reflection1->MapSize(message1, map_field); + const int count2 = reflection2->MapSize(message2, map_field); + const bool treated_as_subset = IsTreatedAsSubset(map_field); + if (count1 != count2 && !treated_as_subset) { + return false; + } + if (count1 > count2) { + return false; + } + const FieldDescriptor* val_des = map_field->message_type()->map_value(); + switch (val_des->cpp_type()) { +#define HANDLE_TYPE(CPPTYPE, METHOD, COMPAREMETHOD) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: { \ + for (MapIterator it = reflection1->MapBegin( \ + const_cast(&message1), map_field); \ + it != \ + reflection1->MapEnd(const_cast(&message1), map_field); \ + ++it) { \ + if (!reflection2->ContainsMapKey(message2, map_field, it.GetKey())) { \ + return false; \ + } \ + MapValueRef value2; \ + reflection2->InsertOrLookupMapValue(const_cast(&message2), \ + map_field, it.GetKey(), &value2); \ + if (!default_field_comparator_.Compare##COMPAREMETHOD( \ + *val_des, it.GetValueRef().Get##METHOD(), \ + value2.Get##METHOD())) { \ + return false; \ + } \ + } \ + break; \ + } + HANDLE_TYPE(INT32, Int32Value, Int32); + HANDLE_TYPE(INT64, Int64Value, Int64); + HANDLE_TYPE(UINT32, UInt32Value, UInt32); + HANDLE_TYPE(UINT64, UInt64Value, UInt64); + HANDLE_TYPE(DOUBLE, DoubleValue, Double); + HANDLE_TYPE(FLOAT, FloatValue, Float); + HANDLE_TYPE(BOOL, BoolValue, Bool); + HANDLE_TYPE(STRING, StringValue, String); + HANDLE_TYPE(ENUM, EnumValue, Int32); +#undef HANDLE_TYPE + case FieldDescriptor::CPPTYPE_MESSAGE: { + for (MapIterator it = reflection1->MapBegin( + const_cast(&message1), map_field); + it != + reflection1->MapEnd(const_cast(&message1), map_field); + ++it) { + if (!reflection2->ContainsMapKey(message2, map_field, it.GetKey())) { + return false; + } + MapValueRef value2; + reflection2->InsertOrLookupMapValue(const_cast(&message2), + map_field, it.GetKey(), &value2); + if (!Compare(it.GetValueRef().GetMessageValue(), + value2.GetMessageValue())) { + return false; + } + } + break; + } + } + return true; +} + bool MessageDifferencer::CompareRepeatedField( const Message& message1, const Message& message2, const FieldDescriptor* repeated_field, @@ -923,6 +994,25 @@ bool MessageDifferencer::CompareRepeatedField( // the input FieldDescriptor is guaranteed to be repeated field. const Reflection* reflection1 = message1.GetReflection(); const Reflection* reflection2 = message2.GetReflection(); + + // When both map fields are on map, do not sync to repeated field. + // TODO(jieluo): Add support for reporter + if (repeated_field->is_map() && reporter_ == nullptr && + field_comparator_ == nullptr) { + const FieldDescriptor* key_des = repeated_field->message_type()->map_key(); + const FieldDescriptor* val_des = + repeated_field->message_type()->map_value(); + const internal::MapFieldBase* map_field1 = + reflection1->GetMapData(message1, repeated_field); + const internal::MapFieldBase* map_field2 = + reflection2->GetMapData(message2, repeated_field); + if (map_field1->IsMapValid() && map_field2->IsMapValid() && + ignored_fields_.find(key_des) == ignored_fields_.end() && + ignored_fields_.find(val_des) == ignored_fields_.end()) { + return CompareMapFieldByMapReflection(message1, message2, repeated_field); + } + } + const int count1 = reflection1->FieldSize(message1, repeated_field); const int count2 = reflection2->FieldSize(message2, repeated_field); const bool treated_as_subset = IsTreatedAsSubset(repeated_field); diff --git a/src/google/protobuf/util/message_differencer.h b/src/google/protobuf/util/message_differencer.h index f7317c80fe..35a04afbcb 100644 --- a/src/google/protobuf/util/message_differencer.h +++ b/src/google/protobuf/util/message_differencer.h @@ -177,43 +177,33 @@ class PROTOBUF_EXPORT MessageDifferencer { // For known fields, "field" is filled in and "unknown_field_number" is -1. // For unknown fields, "field" is NULL, "unknown_field_number" is the field // number, and "unknown_field_type" is its type. - const FieldDescriptor* field; - int unknown_field_number; - UnknownField::Type unknown_field_type; + const FieldDescriptor* field = nullptr; + int unknown_field_number = -1; + UnknownField::Type unknown_field_type = UnknownField::Type::TYPE_VARINT; // If this a repeated field, "index" is the index within it. For unknown // fields, this is the index of the field among all unknown fields of the // same field number and type. - int index; + int index = -1; // If "field" is a repeated field which is being treated as a map or // a set (see TreatAsMap() and TreatAsSet(), below), new_index indicates // the index the position to which the element has moved. If the element // has not moved, "new_index" will have the same value as "index". - int new_index; + int new_index = -1; // For unknown fields, these are the pointers to the UnknownFieldSet // containing the unknown fields. In certain cases (e.g. proto1's // MessageSet, or nested groups of unknown fields), these may differ from // the messages' internal UnknownFieldSets. - const UnknownFieldSet* unknown_field_set1; - const UnknownFieldSet* unknown_field_set2; + const UnknownFieldSet* unknown_field_set1 = nullptr; + const UnknownFieldSet* unknown_field_set2 = nullptr; // For unknown fields, these are the index of the field within the // UnknownFieldSets. One or the other will be -1 when // reporting an addition or deletion. - int unknown_field_index1; - int unknown_field_index2; - - SpecificField() - : field(NULL), - unknown_field_number(-1), - index(-1), - new_index(-1), - unknown_field_set1(NULL), - unknown_field_set2(NULL), - unknown_field_index1(-1), - unknown_field_index2(-1) {} + int unknown_field_index1 = -1; + int unknown_field_index2 = -1; }; // Abstract base class from which all MessageDifferencer @@ -767,6 +757,11 @@ class PROTOBUF_EXPORT MessageDifferencer { const FieldDescriptor* field, std::vector* parent_fields); + // Compare the map fields using map reflection instead of sync to repeated. + bool CompareMapFieldByMapReflection(const Message& message1, + const Message& message2, + const FieldDescriptor* field); + // Shorthand for CompareFieldValueUsingParentFields with NULL parent_fields. bool CompareFieldValue(const Message& message1, const Message& message2, const FieldDescriptor* field, int index1, int index2); diff --git a/src/google/protobuf/util/message_differencer_unittest.cc b/src/google/protobuf/util/message_differencer_unittest.cc index 2f6be98ccd..3d36e8593c 100644 --- a/src/google/protobuf/util/message_differencer_unittest.cc +++ b/src/google/protobuf/util/message_differencer_unittest.cc @@ -160,6 +160,29 @@ TEST(MessageDifferencerTest, MapFieldEqualityTest) { // Compare EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2)); + + // Get map entries by index will sync map to repeated field + MapTestUtil::GetMapEntries(msg1, 0); + EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2)); + + // Compare values not match + (*msg1.mutable_map_int32_int32())[1] = 2; + (*msg2.mutable_map_int32_int32())[1] = 3; + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); + + // Compare keys not match + msg1.Clear(); + msg2.Clear(); + (*msg1.mutable_map_string_string())["1"] = ""; + (*msg2.mutable_map_string_string())["2"] = ""; + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); + + // Compare message values not match + msg1.Clear(); + msg2.Clear(); + (*msg1.mutable_map_int32_foreign_message())[1].set_c(1); + (*msg2.mutable_map_int32_foreign_message())[1].set_c(2); + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); } TEST(MessageDifferencerTest, BasicPartialEqualityTest) { diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc index fc9e6a5e6f..e3463e3512 100644 --- a/src/google/protobuf/wire_format_unittest.cc +++ b/src/google/protobuf/wire_format_unittest.cc @@ -36,7 +36,6 @@ #include #include -#include #include #include #include @@ -49,6 +48,7 @@ #include #include #include +#include #include #include #include diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc index e9f53a53d1..21debfcb80 100644 --- a/src/google/protobuf/wrappers.pb.cc +++ b/src/google/protobuf/wrappers.pb.cc @@ -60,7 +60,6 @@ static void InitDefaultsscc_info_BoolValue_google_2fprotobuf_2fwrappers_2eproto( new (ptr) PROTOBUF_NAMESPACE_ID::BoolValue(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::BoolValue::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_BoolValue_google_2fprotobuf_2fwrappers_2eproto = @@ -74,7 +73,6 @@ static void InitDefaultsscc_info_BytesValue_google_2fprotobuf_2fwrappers_2eproto new (ptr) PROTOBUF_NAMESPACE_ID::BytesValue(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::BytesValue::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_BytesValue_google_2fprotobuf_2fwrappers_2eproto = @@ -88,7 +86,6 @@ static void InitDefaultsscc_info_DoubleValue_google_2fprotobuf_2fwrappers_2eprot new (ptr) PROTOBUF_NAMESPACE_ID::DoubleValue(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::DoubleValue::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_DoubleValue_google_2fprotobuf_2fwrappers_2eproto = @@ -102,7 +99,6 @@ static void InitDefaultsscc_info_FloatValue_google_2fprotobuf_2fwrappers_2eproto new (ptr) PROTOBUF_NAMESPACE_ID::FloatValue(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::FloatValue::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_FloatValue_google_2fprotobuf_2fwrappers_2eproto = @@ -116,7 +112,6 @@ static void InitDefaultsscc_info_Int32Value_google_2fprotobuf_2fwrappers_2eproto new (ptr) PROTOBUF_NAMESPACE_ID::Int32Value(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::Int32Value::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Int32Value_google_2fprotobuf_2fwrappers_2eproto = @@ -130,7 +125,6 @@ static void InitDefaultsscc_info_Int64Value_google_2fprotobuf_2fwrappers_2eproto new (ptr) PROTOBUF_NAMESPACE_ID::Int64Value(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::Int64Value::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Int64Value_google_2fprotobuf_2fwrappers_2eproto = @@ -144,7 +138,6 @@ static void InitDefaultsscc_info_StringValue_google_2fprotobuf_2fwrappers_2eprot new (ptr) PROTOBUF_NAMESPACE_ID::StringValue(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::StringValue::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_StringValue_google_2fprotobuf_2fwrappers_2eproto = @@ -158,7 +151,6 @@ static void InitDefaultsscc_info_UInt32Value_google_2fprotobuf_2fwrappers_2eprot new (ptr) PROTOBUF_NAMESPACE_ID::UInt32Value(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::UInt32Value::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_UInt32Value_google_2fprotobuf_2fwrappers_2eproto = @@ -172,7 +164,6 @@ static void InitDefaultsscc_info_UInt64Value_google_2fprotobuf_2fwrappers_2eprot new (ptr) PROTOBUF_NAMESPACE_ID::UInt64Value(); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); } - PROTOBUF_NAMESPACE_ID::UInt64Value::InitAsDefaultInstance(); } PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_UInt64Value_google_2fprotobuf_2fwrappers_2eproto = @@ -303,8 +294,6 @@ PROTOBUF_NAMESPACE_OPEN // =================================================================== -void DoubleValue::InitAsDefaultInstance() { -} class DoubleValue::_Internal { public: }; @@ -498,8 +487,6 @@ void DoubleValue::InternalSwap(DoubleValue* other) { // =================================================================== -void FloatValue::InitAsDefaultInstance() { -} class FloatValue::_Internal { public: }; @@ -693,8 +680,6 @@ void FloatValue::InternalSwap(FloatValue* other) { // =================================================================== -void Int64Value::InitAsDefaultInstance() { -} class Int64Value::_Internal { public: }; @@ -890,8 +875,6 @@ void Int64Value::InternalSwap(Int64Value* other) { // =================================================================== -void UInt64Value::InitAsDefaultInstance() { -} class UInt64Value::_Internal { public: }; @@ -1087,8 +1070,6 @@ void UInt64Value::InternalSwap(UInt64Value* other) { // =================================================================== -void Int32Value::InitAsDefaultInstance() { -} class Int32Value::_Internal { public: }; @@ -1284,8 +1265,6 @@ void Int32Value::InternalSwap(Int32Value* other) { // =================================================================== -void UInt32Value::InitAsDefaultInstance() { -} class UInt32Value::_Internal { public: }; @@ -1481,8 +1460,6 @@ void UInt32Value::InternalSwap(UInt32Value* other) { // =================================================================== -void BoolValue::InitAsDefaultInstance() { -} class BoolValue::_Internal { public: }; @@ -1676,8 +1653,6 @@ void BoolValue::InternalSwap(BoolValue* other) { // =================================================================== -void StringValue::InitAsDefaultInstance() { -} class StringValue::_Internal { public: }; @@ -1885,8 +1860,6 @@ void StringValue::InternalSwap(StringValue* other) { // =================================================================== -void BytesValue::InitAsDefaultInstance() { -} class BytesValue::_Internal { public: }; diff --git a/src/google/protobuf/wrappers.pb.h b/src/google/protobuf/wrappers.pb.h index c55e9a348f..455a50f4e9 100644 --- a/src/google/protobuf/wrappers.pb.h +++ b/src/google/protobuf/wrappers.pb.h @@ -134,7 +134,6 @@ class PROTOBUF_EXPORT DoubleValue PROTOBUF_FINAL : } static const DoubleValue& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const DoubleValue* internal_default_instance() { return reinterpret_cast( &_DoubleValue_default_instance_); @@ -271,7 +270,6 @@ class PROTOBUF_EXPORT FloatValue PROTOBUF_FINAL : } static const FloatValue& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const FloatValue* internal_default_instance() { return reinterpret_cast( &_FloatValue_default_instance_); @@ -408,7 +406,6 @@ class PROTOBUF_EXPORT Int64Value PROTOBUF_FINAL : } static const Int64Value& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const Int64Value* internal_default_instance() { return reinterpret_cast( &_Int64Value_default_instance_); @@ -545,7 +542,6 @@ class PROTOBUF_EXPORT UInt64Value PROTOBUF_FINAL : } static const UInt64Value& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const UInt64Value* internal_default_instance() { return reinterpret_cast( &_UInt64Value_default_instance_); @@ -682,7 +678,6 @@ class PROTOBUF_EXPORT Int32Value PROTOBUF_FINAL : } static const Int32Value& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const Int32Value* internal_default_instance() { return reinterpret_cast( &_Int32Value_default_instance_); @@ -819,7 +814,6 @@ class PROTOBUF_EXPORT UInt32Value PROTOBUF_FINAL : } static const UInt32Value& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const UInt32Value* internal_default_instance() { return reinterpret_cast( &_UInt32Value_default_instance_); @@ -956,7 +950,6 @@ class PROTOBUF_EXPORT BoolValue PROTOBUF_FINAL : } static const BoolValue& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const BoolValue* internal_default_instance() { return reinterpret_cast( &_BoolValue_default_instance_); @@ -1093,7 +1086,6 @@ class PROTOBUF_EXPORT StringValue PROTOBUF_FINAL : } static const StringValue& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const StringValue* internal_default_instance() { return reinterpret_cast( &_StringValue_default_instance_); @@ -1237,7 +1229,6 @@ class PROTOBUF_EXPORT BytesValue PROTOBUF_FINAL : } static const BytesValue& default_instance(); - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY static inline const BytesValue* internal_default_instance() { return reinterpret_cast( &_BytesValue_default_instance_); diff --git a/tests.sh b/tests.sh index 52b9cf127b..3d47b6cbf2 100755 --- a/tests.sh +++ b/tests.sh @@ -314,7 +314,7 @@ build_python() { if [ $(uname -s) == "Linux" ]; then envlist=py\{27,33,34,35,36\}-python else - envlist=py27-python + envlist=py\{27,36\}-python fi tox -e $envlist cd .. @@ -364,7 +364,7 @@ build_python_cpp() { if [ $(uname -s) == "Linux" ]; then envlist=py\{27,33,34,35,36\}-cpp else - envlist=py27-cpp + envlist=py\{27,36\}-cpp fi tox -e $envlist cd .. @@ -701,6 +701,51 @@ build_php7.4_zts_c() { popd } +build_php8.0() { + use_php 8.0 + pushd php + rm -rf vendor + composer update + composer test + popd + (cd conformance && make test_php) +} + +build_php8.0_c() { + IS_64BIT=$1 + use_php 8.0 + php/tests/test.sh + pushd conformance + if [ "$IS_64BIT" = "true" ] + then + make test_php_c + else + make test_php_c_32 + fi + popd +} + +build_php8.0_c_64() { + build_php8.0_c true +} + +build_php8.0_mixed() { + use_php 8.0 + pushd php + rm -rf vendor + composer update + tests/compile_extension.sh + tests/generate_protos.sh + php -dextension=./ext/google/protobuf/modules/protobuf.so ./vendor/bin/phpunit + popd +} + +build_php8.0_all() { + build_php8.0 + build_php8.0_c_64 + build_php8.0_mixed +} + build_php_all_32() { build_php5.5 build_php5.6 From 2b3a79735b243f19f4fa90a267ec856db7c60c73 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Mon, 17 Aug 2020 16:18:11 -0700 Subject: [PATCH 4/8] Added changelog entries for the sync. --- CHANGES.txt | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 76910c4d0c..8c1bc2fc08 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,38 @@ +Unreleased Changes + + Protocol Compiler + * The proto compiler no longer requires a .proto filename when it is not + generating code. + + C++ + * Arenas are now unconditionally enabled. cc_enable_arenas no longer has + any effect. + * Fix a memory corruption bug in reflection when mixing optional and + non-optional fields. + * Make SpaceUsed() calculation more thorough for map fields. + * Add stack overflow protection for text format with unknown field values. + * FieldPath::FollowAll() now returns a bool to signal if an out-of-bounds + error was encountered. + * Performance improvements for Map. + * Minor formatting fix when dumping a descriptor to .proto format with + DebugString. + * UBSAN fix in RepeatedField (#2073). + * When running under ASAN, skip a test that makes huge allocations. + * Fixed a crash that could happen when creating more than 256 extensions in + a single message. + + Java + * Bugfix in mergeFrom() when a oneof has multiple message fields. + + Python + * Print google.protobuf.NullValue as null instead of "NULL_VALUE" when it is + used outside WKT Value/Struct. + * Fix bug occurring when attempting to deep copy an enum type in python 3. + + Go: + * Update go_package options to reference google.golang.org/protobuf module. + + 2020-07-14 version 3.13.0-rc1 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript) C++: From 82bad2e1ebfc3db34a839fb1a681974996d16741 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Mon, 17 Aug 2020 17:09:56 -0700 Subject: [PATCH 5/8] Fixed uninitialized variable warning. Unfortunately there's not an easy way to annotate that the "unexpected mode" case is unreachable (even GOOGLE_LOG(FATAL) in a default: case doesn't do it). --- src/google/protobuf/compiler/command_line_interface.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 859eb8b831..3d5c9dee56 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -1531,7 +1531,7 @@ CommandLineInterface::ParseArgumentStatus CommandLineInterface::ParseArguments( } // Check error cases that span multiple flag values. - bool missing_proto_definitions; + bool missing_proto_definitions = false; switch (mode_) { case MODE_COMPILE: missing_proto_definitions = input_files_.empty(); @@ -1555,6 +1555,9 @@ CommandLineInterface::ParseArgumentStatus CommandLineInterface::ParseArguments( case MODE_PRINT: missing_proto_definitions = input_files_.empty() && descriptor_set_in_names_.empty(); + break; + default: + GOOGLE_LOG(FATAL) << "Unexpected mode: " << mode_; } if (missing_proto_definitions) { std::cerr << "Missing input file." << std::endl; From b3cdd40ef03e7b0c393675b36e53f69b46b1d3e5 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Mon, 17 Aug 2020 17:12:44 -0700 Subject: [PATCH 6/8] Added new map.cc file to Bazel BUILD file. --- BUILD | 1 + 1 file changed, 1 insertion(+) diff --git a/BUILD b/BUILD index f3fd3f4606..5d4541dc77 100644 --- a/BUILD +++ b/BUILD @@ -175,6 +175,7 @@ cc_library( "src/google/protobuf/io/zero_copy_stream.cc", "src/google/protobuf/io/zero_copy_stream_impl.cc", "src/google/protobuf/io/zero_copy_stream_impl_lite.cc", + "src/google/protobuf/map.cc", "src/google/protobuf/message_lite.cc", "src/google/protobuf/parse_context.cc", "src/google/protobuf/repeated_field.cc", From 492d0b543e259e5c5b6765ef657a4d13a0f82a0a Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Mon, 17 Aug 2020 17:15:34 -0700 Subject: [PATCH 7/8] Added new failing conformance tests to failure list. --- conformance/failure_list_php_c_32.txt | 2 ++ conformance/failure_list_ruby.txt | 3 +++ 2 files changed, 5 insertions(+) diff --git a/conformance/failure_list_php_c_32.txt b/conformance/failure_list_php_c_32.txt index 63c7e8a024..2fc03dee73 100644 --- a/conformance/failure_list_php_c_32.txt +++ b/conformance/failure_list_php_c_32.txt @@ -1,2 +1,4 @@ Recommended.Proto2.JsonInput.FieldNameExtension.Validator +Recommended.Proto3.JsonInput.NullValueInOtherOneofNewFormat.Validator +Recommended.Proto3.JsonInput.NullValueInOtherOneofOldFormat.Validator Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator diff --git a/conformance/failure_list_ruby.txt b/conformance/failure_list_ruby.txt index ff206dc55f..1aea14560c 100644 --- a/conformance/failure_list_ruby.txt +++ b/conformance/failure_list_ruby.txt @@ -8,6 +8,9 @@ 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 From 59d3966b1fb4dedbfe8af5bdecd303bbac7319bf Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Mon, 17 Aug 2020 17:55:16 -0700 Subject: [PATCH 8/8] Updated failure list for the PHP C implementation. --- conformance/failure_list_php_c.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/conformance/failure_list_php_c.txt b/conformance/failure_list_php_c.txt index 63c7e8a024..2fc03dee73 100644 --- a/conformance/failure_list_php_c.txt +++ b/conformance/failure_list_php_c.txt @@ -1,2 +1,4 @@ Recommended.Proto2.JsonInput.FieldNameExtension.Validator +Recommended.Proto3.JsonInput.NullValueInOtherOneofNewFormat.Validator +Recommended.Proto3.JsonInput.NullValueInOtherOneofOldFormat.Validator Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator