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 089ef7512a..f7313edc83 100644 Binary files a/csharp/src/Google.Protobuf.Test/testprotos.pb and b/csharp/src/Google.Protobuf.Test/testprotos.pb differ diff --git a/csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs b/csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs index aa7932470b..cb923549d4 100644 --- a/csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs +++ b/csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs @@ -132,7 +132,7 @@ namespace Google.Protobuf /// 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 |