diff --git a/Makefile.am b/Makefile.am index 0c7476d12916..b87344661115 100644 --- a/Makefile.am +++ b/Makefile.am @@ -90,8 +90,8 @@ csharp_EXTRA_DIST= \ csharp/src/Google.Protobuf.Benchmarks/Benchmarks.cs \ csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj \ csharp/src/Google.Protobuf.Benchmarks/GoogleMessageBenchmark.cs \ - csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs \ csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs \ + csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs \ csharp/src/Google.Protobuf.Benchmarks/Program.cs \ csharp/src/Google.Protobuf.Benchmarks/wrapper_benchmark_messages.proto \ csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs \ @@ -122,7 +122,10 @@ csharp_EXTRA_DIST= \ csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs \ csharp/src/Google.Protobuf.Test/JsonParserTest.cs \ csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs \ + csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs \ + csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs \ csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs \ + csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs \ csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs \ csharp/src/Google.Protobuf.Test/Reflection/DescriptorDeclarationTest.cs \ csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs \ @@ -182,6 +185,7 @@ csharp_EXTRA_DIST= \ csharp/src/Google.Protobuf/FieldMaskTree.cs \ csharp/src/Google.Protobuf/FrameworkPortability.cs \ csharp/src/Google.Protobuf/Google.Protobuf.csproj \ + csharp/src/Google.Protobuf/IBufferMessage.cs \ csharp/src/Google.Protobuf/ICustomDiagnosticMessage.cs \ csharp/src/Google.Protobuf/IDeepCloneable.cs \ csharp/src/Google.Protobuf/IExtendableMessage.cs \ @@ -196,7 +200,13 @@ csharp_EXTRA_DIST= \ csharp/src/Google.Protobuf/MessageExtensions.cs \ csharp/src/Google.Protobuf/MessageParser.cs \ csharp/src/Google.Protobuf/ObjectIntPair.cs \ + csharp/src/Google.Protobuf/ParseContext.cs \ + csharp/src/Google.Protobuf/ParserInternalState.cs \ + csharp/src/Google.Protobuf/ParsingPrimitives.cs \ + csharp/src/Google.Protobuf/ParsingPrimitivesMessages.cs \ + csharp/src/Google.Protobuf/ParsingPrimitivesWrappers.cs \ csharp/src/Google.Protobuf/ProtoPreconditions.cs \ + csharp/src/Google.Protobuf/SegmentedBufferHelper.cs \ csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs \ csharp/src/Google.Protobuf/Reflection/CustomOptions.cs \ csharp/src/Google.Protobuf/Reflection/Descriptor.cs \ diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedInputStreamTest.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedInputStreamTest.cs index 73a578d2b5a9..11d06f1d7b43 100644 --- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedInputStreamTest.cs +++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedInputStreamTest.cs @@ -201,29 +201,29 @@ public void ReadLittleEndian() [Test] public void DecodeZigZag32() { - Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(0)); - Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(1)); - Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(2)); - Assert.AreEqual(-2, CodedInputStream.DecodeZigZag32(3)); - Assert.AreEqual(0x3FFFFFFF, CodedInputStream.DecodeZigZag32(0x7FFFFFFE)); - Assert.AreEqual(unchecked((int) 0xC0000000), CodedInputStream.DecodeZigZag32(0x7FFFFFFF)); - Assert.AreEqual(0x7FFFFFFF, CodedInputStream.DecodeZigZag32(0xFFFFFFFE)); - Assert.AreEqual(unchecked((int) 0x80000000), CodedInputStream.DecodeZigZag32(0xFFFFFFFF)); + Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag32(0)); + Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag32(1)); + Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag32(2)); + Assert.AreEqual(-2, ParsingPrimitives.DecodeZigZag32(3)); + Assert.AreEqual(0x3FFFFFFF, ParsingPrimitives.DecodeZigZag32(0x7FFFFFFE)); + Assert.AreEqual(unchecked((int) 0xC0000000), ParsingPrimitives.DecodeZigZag32(0x7FFFFFFF)); + Assert.AreEqual(0x7FFFFFFF, ParsingPrimitives.DecodeZigZag32(0xFFFFFFFE)); + Assert.AreEqual(unchecked((int) 0x80000000), ParsingPrimitives.DecodeZigZag32(0xFFFFFFFF)); } [Test] public void DecodeZigZag64() { - Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(0)); - Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(1)); - Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(2)); - Assert.AreEqual(-2, CodedInputStream.DecodeZigZag64(3)); - Assert.AreEqual(0x000000003FFFFFFFL, CodedInputStream.DecodeZigZag64(0x000000007FFFFFFEL)); - Assert.AreEqual(unchecked((long) 0xFFFFFFFFC0000000L), CodedInputStream.DecodeZigZag64(0x000000007FFFFFFFL)); - Assert.AreEqual(0x000000007FFFFFFFL, CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFEL)); - Assert.AreEqual(unchecked((long) 0xFFFFFFFF80000000L), CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFFL)); - Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL)); - Assert.AreEqual(unchecked((long) 0x8000000000000000L), CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL)); + Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag64(0)); + Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag64(1)); + Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag64(2)); + Assert.AreEqual(-2, ParsingPrimitives.DecodeZigZag64(3)); + Assert.AreEqual(0x000000003FFFFFFFL, ParsingPrimitives.DecodeZigZag64(0x000000007FFFFFFEL)); + Assert.AreEqual(unchecked((long) 0xFFFFFFFFC0000000L), ParsingPrimitives.DecodeZigZag64(0x000000007FFFFFFFL)); + Assert.AreEqual(0x000000007FFFFFFFL, ParsingPrimitives.DecodeZigZag64(0x00000000FFFFFFFEL)); + Assert.AreEqual(unchecked((long) 0xFFFFFFFF80000000L), ParsingPrimitives.DecodeZigZag64(0x00000000FFFFFFFFL)); + Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, ParsingPrimitives.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL)); + Assert.AreEqual(unchecked((long) 0x8000000000000000L), ParsingPrimitives.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL)); } [Test] 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 01bd3218f337..f25e14e96836 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 @@ -247,26 +247,26 @@ public void RoundTripZigZag32() { // Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1) // were chosen semi-randomly via keyboard bashing. - Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(0))); - Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(1))); - Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-1))); - Assert.AreEqual(14927, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(14927))); - Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-3612))); + 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))); } [Test] public void RoundTripZigZag64() { - Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(0))); - Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(1))); - Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-1))); - Assert.AreEqual(14927, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(14927))); - Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-3612))); + 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(856912304801416L, - CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(856912304801416L))); + ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(856912304801416L))); Assert.AreEqual(-75123905439571256L, - CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-75123905439571256L))); + ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-75123905439571256L))); } [Test] 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 390766682797..a5825a070801 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 @@ -128,7 +128,7 @@ public void TestRoundTripRaw() codedOutput.Flush(); stream.Position = 0; var codedInput = new CodedInputStream(stream); - Assert.AreEqual(sampleValue, codec.ValueReader(codedInput)); + Assert.AreEqual(sampleValue, codec.Read(codedInput)); Assert.IsTrue(codedInput.IsAtEnd); } @@ -178,7 +178,7 @@ public void TestDefaultValue() Assert.AreEqual(stream.Position, codec.ValueSizeCalculator(codec.DefaultValue)); stream.Position = 0; var codedInput = new CodedInputStream(stream); - Assert.AreEqual(codec.DefaultValue, codec.ValueReader(codedInput)); + Assert.AreEqual(codec.DefaultValue, codec.Read(codedInput)); } } diff --git a/csharp/src/AddressBook/Addressbook.cs b/csharp/src/AddressBook/Addressbook.cs index cbd977269620..3b1da4d613a3 100644 --- a/csharp/src/AddressBook/Addressbook.cs +++ b/csharp/src/AddressBook/Addressbook.cs @@ -49,7 +49,7 @@ public static partial class AddressbookReflection { /// /// [START messages] /// - public sealed partial class Person : pb::IMessage { + public sealed partial class Person : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Person()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -256,11 +256,16 @@ public sealed partial class Person : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Name = input.ReadString(); @@ -275,7 +280,7 @@ public sealed partial class Person : pb::IMessage { break; } case 34: { - phones_.AddEntriesFrom(input, _repeated_phones_codec); + phones_.AddEntriesFrom(ref input, _repeated_phones_codec); break; } case 42: { @@ -299,7 +304,7 @@ public enum PhoneType { [pbr::OriginalName("WORK")] Work = 2, } - public sealed partial class PhoneNumber : pb::IMessage { + public sealed partial class PhoneNumber : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new PhoneNumber()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -436,11 +441,16 @@ public sealed partial class PhoneNumber : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Number = input.ReadString(); @@ -464,7 +474,7 @@ public sealed partial class PhoneNumber : pb::IMessage { /// /// Our address book file is just one of these. /// - public sealed partial class AddressBook : pb::IMessage { + public sealed partial class AddressBook : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new AddressBook()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -569,14 +579,19 @@ public sealed partial class AddressBook : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { - people_.AddEntriesFrom(input, _repeated_people_codec); + people_.AddEntriesFrom(ref input, _repeated_people_codec); break; } } diff --git a/csharp/src/Google.Protobuf.Benchmarks/BenchmarkMessage1Proto3.cs b/csharp/src/Google.Protobuf.Benchmarks/BenchmarkMessage1Proto3.cs index 9e8c330a2b63..291a585ca865 100644 --- a/csharp/src/Google.Protobuf.Benchmarks/BenchmarkMessage1Proto3.cs +++ b/csharp/src/Google.Protobuf.Benchmarks/BenchmarkMessage1Proto3.cs @@ -64,7 +64,7 @@ public static partial class BenchmarkMessage1Proto3Reflection { } #region Messages - public sealed partial class GoogleMessage1 : pb::IMessage { + public sealed partial class GoogleMessage1 : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new GoogleMessage1()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1132,11 +1132,16 @@ public sealed partial class GoogleMessage1 : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Field1 = input.ReadString(); @@ -1156,7 +1161,7 @@ public sealed partial class GoogleMessage1 : pb::IMessage { } case 42: case 41: { - field5_.AddEntriesFrom(input, _repeated_field5_codec); + field5_.AddEntriesFrom(ref input, _repeated_field5_codec); break; } case 48: { @@ -1312,7 +1317,7 @@ public sealed partial class GoogleMessage1 : pb::IMessage { } - public sealed partial class GoogleMessage1SubMessage : pb::IMessage { + public sealed partial class GoogleMessage1SubMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new GoogleMessage1SubMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1881,11 +1886,16 @@ public sealed partial class GoogleMessage1SubMessage : pb::IMessage { + public sealed partial class BenchmarkDataset : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BenchmarkDataset()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -219,11 +219,16 @@ public sealed partial class BenchmarkDataset : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Name = input.ReadString(); @@ -234,7 +239,7 @@ public sealed partial class BenchmarkDataset : pb::IMessage { break; } case 26: { - payload_.AddEntriesFrom(input, _repeated_payload_codec); + payload_.AddEntriesFrom(ref input, _repeated_payload_codec); break; } } diff --git a/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj b/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj index ecc064ea7d09..7432168210e2 100644 --- a/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj +++ b/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj @@ -3,6 +3,9 @@ Exe netcoreapp2.1 + ../../keys/Google.Protobuf.snk + true + true False diff --git a/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs index cbc47328fa1b..30f3e9ef378b 100644 --- a/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs +++ b/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs @@ -65,18 +65,36 @@ public IMessage ManyWrapperFieldsMessage_ParseFromByteArray() return manyWrapperFieldsTest.ParseFromByteArray(); } + [Benchmark] + public IMessage ManyWrapperFieldsMessage_ParseFromReadOnlySequence() + { + return manyWrapperFieldsTest.ParseFromReadOnlySequence(); + } + [Benchmark] public IMessage ManyPrimitiveFieldsMessage_ParseFromByteArray() { return manyPrimitiveFieldsTest.ParseFromByteArray(); } + [Benchmark] + public IMessage ManyPrimitiveFieldsMessage_ParseFromReadOnlySequence() + { + return manyPrimitiveFieldsTest.ParseFromReadOnlySequence(); + } + [Benchmark] public IMessage EmptyMessage_ParseFromByteArray() { return emptyMessageTest.ParseFromByteArray(); } + [Benchmark] + public IMessage EmptyMessage_ParseFromReadOnlySequence() + { + return emptyMessageTest.ParseFromReadOnlySequence(); + } + [Benchmark] [ArgumentsSource(nameof(MessageCountValues))] public void ManyWrapperFieldsMessage_ParseDelimitedMessagesFromByteArray(int messageCount) @@ -84,6 +102,13 @@ public void ManyWrapperFieldsMessage_ParseDelimitedMessagesFromByteArray(int mes manyWrapperFieldsTest.ParseDelimitedMessagesFromByteArray(messageCount); } + [Benchmark] + [ArgumentsSource(nameof(MessageCountValues))] + public void ManyWrapperFieldsMessage_ParseDelimitedMessagesFromReadOnlySequence(int messageCount) + { + manyWrapperFieldsTest.ParseDelimitedMessagesFromReadOnlySequence(messageCount); + } + [Benchmark] [ArgumentsSource(nameof(MessageCountValues))] public void ManyPrimitiveFieldsMessage_ParseDelimitedMessagesFromByteArray(int messageCount) @@ -91,6 +116,13 @@ public void ManyPrimitiveFieldsMessage_ParseDelimitedMessagesFromByteArray(int m manyPrimitiveFieldsTest.ParseDelimitedMessagesFromByteArray(messageCount); } + [Benchmark] + [ArgumentsSource(nameof(MessageCountValues))] + public void ManyPrimitiveFieldsMessage_ParseDelimitedMessagesFromReadOnlySequence(int messageCount) + { + manyPrimitiveFieldsTest.ParseDelimitedMessagesFromReadOnlySequence(messageCount); + } + private static ManyWrapperFieldsMessage CreateManyWrapperFieldsMessage() { // Example data match data of an internal benchmarks @@ -133,6 +165,9 @@ private class SubTest private readonly byte[] data; private readonly byte[] multipleMessagesData; + private ReadOnlySequence dataSequence; + private ReadOnlySequence multipleMessagesDataSequence; + public SubTest(IMessage message, MessageParser parser, Func factory, int maxMessageCount) { this.message = message; @@ -140,10 +175,14 @@ public SubTest(IMessage message, MessageParser parser, Func factory, i this.factory = factory; this.data = message.ToByteArray(); this.multipleMessagesData = CreateBufferWithMultipleMessages(message, maxMessageCount); + this.dataSequence = new ReadOnlySequence(this.data); + this.multipleMessagesDataSequence = new ReadOnlySequence(this.multipleMessagesData); } public IMessage ParseFromByteArray() => parser.ParseFrom(data); + public IMessage ParseFromReadOnlySequence() => parser.ParseFrom(dataSequence); + public void ParseDelimitedMessagesFromByteArray(int messageCount) { var input = new CodedInputStream(multipleMessagesData); @@ -154,6 +193,16 @@ public void ParseDelimitedMessagesFromByteArray(int messageCount) } } + public void ParseDelimitedMessagesFromReadOnlySequence(int messageCount) + { + ParseContext.Initialize(multipleMessagesDataSequence, out ParseContext ctx); + for (int i = 0; i < messageCount; i++) + { + var msg = factory(); + ctx.ReadMessage(msg); + } + } + private static byte[] CreateBufferWithMultipleMessages(IMessage msg, int msgCount) { var ms = new MemoryStream(); diff --git a/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs index 44dde2ff8ce4..863e74dc49d6 100644 --- a/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs +++ b/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs @@ -35,6 +35,7 @@ using System.Buffers.Binary; using System.Collections.Generic; using System.IO; +using System.Buffers; namespace Google.Protobuf.Benchmarks { @@ -51,8 +52,13 @@ public class ParseRawPrimitivesBenchmark byte[] floatInputBuffer; byte[] fixedIntInputBuffer; + // key is the encodedSize of string values + Dictionary stringInputBuffers; + Random random = new Random(417384220); // random but deterministic seed + public IEnumerable StringEncodedSizes => new[] { 1, 4, 10, 105, 10080 }; + [GlobalSetup] public void GlobalSetup() { @@ -70,6 +76,13 @@ public void GlobalSetup() doubleInputBuffer = CreateBufferWithRandomDoubles(random, BytesToParse / sizeof(double), paddingValueCount); floatInputBuffer = CreateBufferWithRandomFloats(random, BytesToParse / sizeof(float), paddingValueCount); fixedIntInputBuffer = CreateBufferWithRandomData(random, BytesToParse / sizeof(long), sizeof(long), paddingValueCount); + + stringInputBuffers = new Dictionary(); + foreach(var encodedSize in StringEncodedSizes) + { + byte[] buffer = CreateBufferWithStrings(BytesToParse / encodedSize, encodedSize, encodedSize < 10 ? 10 : 1 ); + stringInputBuffers.Add(encodedSize, buffer); + } } // Total number of bytes that each benchmark will parse. @@ -85,7 +98,7 @@ public void GlobalSetup() [Arguments(3)] [Arguments(4)] [Arguments(5)] - public int ParseRawVarint32(int encodedSize) + public int ParseRawVarint32_CodedInputStream(int encodedSize) { CodedInputStream cis = new CodedInputStream(varintInputBuffers[encodedSize]); int sum = 0; @@ -96,6 +109,23 @@ public int ParseRawVarint32(int encodedSize) return sum; } + [Benchmark] + [Arguments(1)] + [Arguments(2)] + [Arguments(3)] + [Arguments(4)] + [Arguments(5)] + public int ParseRawVarint32_ParseContext(int encodedSize) + { + InitializeParseContext(varintInputBuffers[encodedSize], out ParseContext ctx); + int sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += ctx.ReadInt32(); + } + return sum; + } + [Benchmark] [Arguments(1)] [Arguments(2)] @@ -107,7 +137,7 @@ public int ParseRawVarint32(int encodedSize) [Arguments(8)] [Arguments(9)] [Arguments(10)] - public long ParseRawVarint64(int encodedSize) + public long ParseRawVarint64_CodedInputStream(int encodedSize) { CodedInputStream cis = new CodedInputStream(varintInputBuffers[encodedSize]); long sum = 0; @@ -119,7 +149,29 @@ public long ParseRawVarint64(int encodedSize) } [Benchmark] - public uint ParseFixed32() + [Arguments(1)] + [Arguments(2)] + [Arguments(3)] + [Arguments(4)] + [Arguments(5)] + [Arguments(6)] + [Arguments(7)] + [Arguments(8)] + [Arguments(9)] + [Arguments(10)] + public long ParseRawVarint64_ParseContext(int encodedSize) + { + InitializeParseContext(varintInputBuffers[encodedSize], out ParseContext ctx); + long sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += ctx.ReadInt64(); + } + return sum; + } + + [Benchmark] + public uint ParseFixed32_CodedInputStream() { const int encodedSize = sizeof(uint); CodedInputStream cis = new CodedInputStream(fixedIntInputBuffer); @@ -132,7 +184,20 @@ public uint ParseFixed32() } [Benchmark] - public ulong ParseFixed64() + public uint ParseFixed32_ParseContext() + { + const int encodedSize = sizeof(uint); + InitializeParseContext(fixedIntInputBuffer, out ParseContext ctx); + uint sum = 0; + for (uint i = 0; i < BytesToParse / encodedSize; i++) + { + sum += ctx.ReadFixed32(); + } + return sum; + } + + [Benchmark] + public ulong ParseFixed64_CodedInputStream() { const int encodedSize = sizeof(ulong); CodedInputStream cis = new CodedInputStream(fixedIntInputBuffer); @@ -145,7 +210,20 @@ public ulong ParseFixed64() } [Benchmark] - public float ParseRawFloat() + public ulong ParseFixed64_ParseContext() + { + const int encodedSize = sizeof(ulong); + InitializeParseContext(fixedIntInputBuffer, out ParseContext ctx); + ulong sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += ctx.ReadFixed64(); + } + return sum; + } + + [Benchmark] + public float ParseRawFloat_CodedInputStream() { const int encodedSize = sizeof(float); CodedInputStream cis = new CodedInputStream(floatInputBuffer); @@ -158,7 +236,20 @@ public float ParseRawFloat() } [Benchmark] - public double ParseRawDouble() + public float ParseRawFloat_ParseContext() + { + const int encodedSize = sizeof(float); + InitializeParseContext(floatInputBuffer, out ParseContext ctx); + float sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += ctx.ReadFloat(); + } + return sum; + } + + [Benchmark] + public double ParseRawDouble_CodedInputStream() { const int encodedSize = sizeof(double); CodedInputStream cis = new CodedInputStream(doubleInputBuffer); @@ -170,6 +261,76 @@ public double ParseRawDouble() return sum; } + [Benchmark] + public double ParseRawDouble_ParseContext() + { + const int encodedSize = sizeof(double); + InitializeParseContext(doubleInputBuffer, out ParseContext ctx); + double sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += ctx.ReadDouble(); + } + return sum; + } + + [Benchmark] + [ArgumentsSource(nameof(StringEncodedSizes))] + public int ParseString_CodedInputStream(int encodedSize) + { + CodedInputStream cis = new CodedInputStream(stringInputBuffers[encodedSize]); + int sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += cis.ReadString().Length; + } + return sum; + } + + [Benchmark] + [ArgumentsSource(nameof(StringEncodedSizes))] + public int ParseString_ParseContext(int encodedSize) + { + InitializeParseContext(stringInputBuffers[encodedSize], out ParseContext ctx); + int sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += ctx.ReadString().Length; + } + return sum; + } + + [Benchmark] + [ArgumentsSource(nameof(StringEncodedSizes))] + public int ParseBytes_CodedInputStream(int encodedSize) + { + CodedInputStream cis = new CodedInputStream(stringInputBuffers[encodedSize]); + int sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += cis.ReadBytes().Length; + } + return sum; + } + + [Benchmark] + [ArgumentsSource(nameof(StringEncodedSizes))] + public int ParseBytes_ParseContext(int encodedSize) + { + InitializeParseContext(stringInputBuffers[encodedSize], out ParseContext ctx); + int sum = 0; + for (int i = 0; i < BytesToParse / encodedSize; i++) + { + sum += ctx.ReadBytes().Length; + } + return sum; + } + + private static void InitializeParseContext(byte[] buffer, out ParseContext ctx) + { + ParseContext.Initialize(new ReadOnlySequence(buffer), out ctx); + } + private static byte[] CreateBufferWithRandomVarints(Random random, int valueCount, int encodedSize, int paddingValueCount) { MemoryStream ms = new MemoryStream(); @@ -261,5 +422,40 @@ private static ulong RandomUnsignedVarint(Random random, int encodedSize) } return result; } + + private static byte[] CreateBufferWithStrings(int valueCount, int encodedSize, int paddingValueCount) + { + var str = CreateStringWithEncodedSize(encodedSize); + + MemoryStream ms = new MemoryStream(); + CodedOutputStream cos = new CodedOutputStream(ms); + for (int i = 0; i < valueCount + paddingValueCount; i++) + { + cos.WriteString(str); + } + cos.Flush(); + var buffer = ms.ToArray(); + + if (buffer.Length != encodedSize * (valueCount + paddingValueCount)) + { + throw new InvalidOperationException($"Unexpected output buffer length {buffer.Length}"); + } + return buffer; + } + + private static string CreateStringWithEncodedSize(int encodedSize) + { + var str = new string('a', encodedSize); + while (CodedOutputStream.ComputeStringSize(str) > encodedSize) + { + str = str.Substring(1); + } + + 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 0cc86e2ad406..76e95d6edfcf 100644 --- a/csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs +++ b/csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs @@ -237,7 +237,7 @@ public static partial class WrapperBenchmarkMessagesReflection { /// a message that has a large number of wrapper fields /// obfuscated version of an internal message /// - public sealed partial class ManyWrapperFieldsMessage : pb::IMessage { + public sealed partial class ManyWrapperFieldsMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ManyWrapperFieldsMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -3303,434 +3303,439 @@ public sealed partial class ManyWrapperFieldsMessage : pb::IMessage - public sealed partial class ManyPrimitiveFieldsMessage : pb::IMessage { + public sealed partial class ManyPrimitiveFieldsMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ManyPrimitiveFieldsMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -6830,11 +6835,16 @@ public sealed partial class ManyPrimitiveFieldsMessage : pb::IMessage - public sealed partial class FailureSet : pb::IMessage { + public sealed partial class FailureSet : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FailureSet()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -212,14 +212,19 @@ public sealed partial class FailureSet : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { - failure_.AddEntriesFrom(input, _repeated_failure_codec); + failure_.AddEntriesFrom(ref input, _repeated_failure_codec); break; } } @@ -235,7 +240,7 @@ public sealed partial class FailureSet : pb::IMessage { /// 2. parse the protobuf or JSON payload in "payload" (which may fail) /// 3. if the parse succeeded, serialize the message in the requested format. /// - public sealed partial class ConformanceRequest : pb::IMessage { + public sealed partial class ConformanceRequest : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ConformanceRequest()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -603,11 +608,16 @@ public enum PayloadOneofCase { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { ProtobufPayload = input.ReadBytes(); @@ -657,7 +667,7 @@ public enum PayloadOneofCase { /// /// Represents a single test case's output. /// - public sealed partial class ConformanceResponse : pb::IMessage { + public sealed partial class ConformanceResponse : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ConformanceResponse()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1025,11 +1035,16 @@ public enum ResultOneofCase { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { ParseError = input.ReadString(); @@ -1072,7 +1087,7 @@ public enum ResultOneofCase { /// /// Encoding options for jspb format. /// - public sealed partial class JspbEncodingConfig : pb::IMessage { + public sealed partial class JspbEncodingConfig : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new JspbEncodingConfig()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1188,11 +1203,16 @@ public sealed partial class JspbEncodingConfig : pb::IMessage - net45;netstandard1.0;netstandard2.0 + net45;netstandard1.1;netstandard2.0 3.0 ../../keys/Google.Protobuf.snk true diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs index 197b197d0ea4..8d2060593d3c 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs @@ -176,7 +176,7 @@ public enum MapEnum { /// /// Tests maps. /// - public sealed partial class TestMap : pb::IMessage { + public sealed partial class TestMap : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMap()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -537,78 +537,83 @@ public sealed partial class TestMap : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { - mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec); + mapInt32Int32_.AddEntriesFrom(ref input, _map_mapInt32Int32_codec); break; } case 18: { - mapInt64Int64_.AddEntriesFrom(input, _map_mapInt64Int64_codec); + mapInt64Int64_.AddEntriesFrom(ref input, _map_mapInt64Int64_codec); break; } case 26: { - mapUint32Uint32_.AddEntriesFrom(input, _map_mapUint32Uint32_codec); + mapUint32Uint32_.AddEntriesFrom(ref input, _map_mapUint32Uint32_codec); break; } case 34: { - mapUint64Uint64_.AddEntriesFrom(input, _map_mapUint64Uint64_codec); + mapUint64Uint64_.AddEntriesFrom(ref input, _map_mapUint64Uint64_codec); break; } case 42: { - mapSint32Sint32_.AddEntriesFrom(input, _map_mapSint32Sint32_codec); + mapSint32Sint32_.AddEntriesFrom(ref input, _map_mapSint32Sint32_codec); break; } case 50: { - mapSint64Sint64_.AddEntriesFrom(input, _map_mapSint64Sint64_codec); + mapSint64Sint64_.AddEntriesFrom(ref input, _map_mapSint64Sint64_codec); break; } case 58: { - mapFixed32Fixed32_.AddEntriesFrom(input, _map_mapFixed32Fixed32_codec); + mapFixed32Fixed32_.AddEntriesFrom(ref input, _map_mapFixed32Fixed32_codec); break; } case 66: { - mapFixed64Fixed64_.AddEntriesFrom(input, _map_mapFixed64Fixed64_codec); + mapFixed64Fixed64_.AddEntriesFrom(ref input, _map_mapFixed64Fixed64_codec); break; } case 74: { - mapSfixed32Sfixed32_.AddEntriesFrom(input, _map_mapSfixed32Sfixed32_codec); + mapSfixed32Sfixed32_.AddEntriesFrom(ref input, _map_mapSfixed32Sfixed32_codec); break; } case 82: { - mapSfixed64Sfixed64_.AddEntriesFrom(input, _map_mapSfixed64Sfixed64_codec); + mapSfixed64Sfixed64_.AddEntriesFrom(ref input, _map_mapSfixed64Sfixed64_codec); break; } case 90: { - mapInt32Float_.AddEntriesFrom(input, _map_mapInt32Float_codec); + mapInt32Float_.AddEntriesFrom(ref input, _map_mapInt32Float_codec); break; } case 98: { - mapInt32Double_.AddEntriesFrom(input, _map_mapInt32Double_codec); + mapInt32Double_.AddEntriesFrom(ref input, _map_mapInt32Double_codec); break; } case 106: { - mapBoolBool_.AddEntriesFrom(input, _map_mapBoolBool_codec); + mapBoolBool_.AddEntriesFrom(ref input, _map_mapBoolBool_codec); break; } case 114: { - mapStringString_.AddEntriesFrom(input, _map_mapStringString_codec); + mapStringString_.AddEntriesFrom(ref input, _map_mapStringString_codec); break; } case 122: { - mapInt32Bytes_.AddEntriesFrom(input, _map_mapInt32Bytes_codec); + mapInt32Bytes_.AddEntriesFrom(ref input, _map_mapInt32Bytes_codec); break; } case 130: { - mapInt32Enum_.AddEntriesFrom(input, _map_mapInt32Enum_codec); + mapInt32Enum_.AddEntriesFrom(ref input, _map_mapInt32Enum_codec); break; } case 138: { - mapInt32ForeignMessage_.AddEntriesFrom(input, _map_mapInt32ForeignMessage_codec); + mapInt32ForeignMessage_.AddEntriesFrom(ref input, _map_mapInt32ForeignMessage_codec); break; } } @@ -617,7 +622,7 @@ public sealed partial class TestMap : pb::IMessage { } - public sealed partial class TestMapSubmessage : pb::IMessage { + public sealed partial class TestMapSubmessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMapSubmessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -733,11 +738,16 @@ public sealed partial class TestMapSubmessage : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { if (testMap_ == null) { @@ -752,7 +762,7 @@ public sealed partial class TestMapSubmessage : pb::IMessage } - public sealed partial class TestMessageMap : pb::IMessage { + public sealed partial class TestMessageMap : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMessageMap()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -857,14 +867,19 @@ public sealed partial class TestMessageMap : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { - mapInt32Message_.AddEntriesFrom(input, _map_mapInt32Message_codec); + mapInt32Message_.AddEntriesFrom(ref input, _map_mapInt32Message_codec); break; } } @@ -876,7 +891,7 @@ public sealed partial class TestMessageMap : pb::IMessage { /// /// Two map fields share the same entry default instance. /// - public sealed partial class TestSameTypeMap : pb::IMessage { + public sealed partial class TestSameTypeMap : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestSameTypeMap()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -997,18 +1012,23 @@ public sealed partial class TestSameTypeMap : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { - map1_.AddEntriesFrom(input, _map_map1_codec); + map1_.AddEntriesFrom(ref input, _map_map1_codec); break; } case 18: { - map2_.AddEntriesFrom(input, _map_map2_codec); + map2_.AddEntriesFrom(ref input, _map_map2_codec); break; } } @@ -1017,7 +1037,7 @@ public sealed partial class TestSameTypeMap : pb::IMessage { } - public sealed partial class TestArenaMap : pb::IMessage { + public sealed partial class TestArenaMap : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestArenaMap()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1346,70 +1366,75 @@ public sealed partial class TestArenaMap : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { - mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec); + mapInt32Int32_.AddEntriesFrom(ref input, _map_mapInt32Int32_codec); break; } case 18: { - mapInt64Int64_.AddEntriesFrom(input, _map_mapInt64Int64_codec); + mapInt64Int64_.AddEntriesFrom(ref input, _map_mapInt64Int64_codec); break; } case 26: { - mapUint32Uint32_.AddEntriesFrom(input, _map_mapUint32Uint32_codec); + mapUint32Uint32_.AddEntriesFrom(ref input, _map_mapUint32Uint32_codec); break; } case 34: { - mapUint64Uint64_.AddEntriesFrom(input, _map_mapUint64Uint64_codec); + mapUint64Uint64_.AddEntriesFrom(ref input, _map_mapUint64Uint64_codec); break; } case 42: { - mapSint32Sint32_.AddEntriesFrom(input, _map_mapSint32Sint32_codec); + mapSint32Sint32_.AddEntriesFrom(ref input, _map_mapSint32Sint32_codec); break; } case 50: { - mapSint64Sint64_.AddEntriesFrom(input, _map_mapSint64Sint64_codec); + mapSint64Sint64_.AddEntriesFrom(ref input, _map_mapSint64Sint64_codec); break; } case 58: { - mapFixed32Fixed32_.AddEntriesFrom(input, _map_mapFixed32Fixed32_codec); + mapFixed32Fixed32_.AddEntriesFrom(ref input, _map_mapFixed32Fixed32_codec); break; } case 66: { - mapFixed64Fixed64_.AddEntriesFrom(input, _map_mapFixed64Fixed64_codec); + mapFixed64Fixed64_.AddEntriesFrom(ref input, _map_mapFixed64Fixed64_codec); break; } case 74: { - mapSfixed32Sfixed32_.AddEntriesFrom(input, _map_mapSfixed32Sfixed32_codec); + mapSfixed32Sfixed32_.AddEntriesFrom(ref input, _map_mapSfixed32Sfixed32_codec); break; } case 82: { - mapSfixed64Sfixed64_.AddEntriesFrom(input, _map_mapSfixed64Sfixed64_codec); + mapSfixed64Sfixed64_.AddEntriesFrom(ref input, _map_mapSfixed64Sfixed64_codec); break; } case 90: { - mapInt32Float_.AddEntriesFrom(input, _map_mapInt32Float_codec); + mapInt32Float_.AddEntriesFrom(ref input, _map_mapInt32Float_codec); break; } case 98: { - mapInt32Double_.AddEntriesFrom(input, _map_mapInt32Double_codec); + mapInt32Double_.AddEntriesFrom(ref input, _map_mapInt32Double_codec); break; } case 106: { - mapBoolBool_.AddEntriesFrom(input, _map_mapBoolBool_codec); + mapBoolBool_.AddEntriesFrom(ref input, _map_mapBoolBool_codec); break; } case 114: { - mapInt32Enum_.AddEntriesFrom(input, _map_mapInt32Enum_codec); + mapInt32Enum_.AddEntriesFrom(ref input, _map_mapInt32Enum_codec); break; } case 122: { - mapInt32ForeignMessage_.AddEntriesFrom(input, _map_mapInt32ForeignMessage_codec); + mapInt32ForeignMessage_.AddEntriesFrom(ref input, _map_mapInt32ForeignMessage_codec); break; } } @@ -1422,7 +1447,7 @@ public sealed partial class TestArenaMap : pb::IMessage { /// Previously, message containing enum called Type cannot be used as value of /// map field. /// - public sealed partial class MessageContainingEnumCalledType : pb::IMessage { + public sealed partial class MessageContainingEnumCalledType : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MessageContainingEnumCalledType()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1527,14 +1552,19 @@ public sealed partial class MessageContainingEnumCalledType : pb::IMessage /// Previously, message cannot contain map field called "entry". /// - public sealed partial class MessageContainingMapCalledEntry : pb::IMessage { + public sealed partial class MessageContainingMapCalledEntry : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MessageContainingMapCalledEntry()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1662,14 +1692,19 @@ public sealed partial class MessageContainingMapCalledEntry : pb::IMessage - public sealed partial class TestAllTypesProto2 : pb::IExtendableMessage { + public sealed partial class TestAllTypesProto2 : pb::IExtendableMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestAllTypesProto2()); private pb::UnknownFieldSet _unknownFields; private pb::ExtensionSet _extensions; @@ -3353,12 +3353,17 @@ public enum OneofFieldOneofCase { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); } break; case 8: { @@ -3460,317 +3465,317 @@ public enum OneofFieldOneofCase { } case 250: case 248: { - repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec); + repeatedInt32_.AddEntriesFrom(ref input, _repeated_repeatedInt32_codec); break; } case 258: case 256: { - repeatedInt64_.AddEntriesFrom(input, _repeated_repeatedInt64_codec); + repeatedInt64_.AddEntriesFrom(ref input, _repeated_repeatedInt64_codec); break; } case 266: case 264: { - repeatedUint32_.AddEntriesFrom(input, _repeated_repeatedUint32_codec); + repeatedUint32_.AddEntriesFrom(ref input, _repeated_repeatedUint32_codec); break; } case 274: case 272: { - repeatedUint64_.AddEntriesFrom(input, _repeated_repeatedUint64_codec); + repeatedUint64_.AddEntriesFrom(ref input, _repeated_repeatedUint64_codec); break; } case 282: case 280: { - repeatedSint32_.AddEntriesFrom(input, _repeated_repeatedSint32_codec); + repeatedSint32_.AddEntriesFrom(ref input, _repeated_repeatedSint32_codec); break; } case 290: case 288: { - repeatedSint64_.AddEntriesFrom(input, _repeated_repeatedSint64_codec); + repeatedSint64_.AddEntriesFrom(ref input, _repeated_repeatedSint64_codec); break; } case 298: case 301: { - repeatedFixed32_.AddEntriesFrom(input, _repeated_repeatedFixed32_codec); + repeatedFixed32_.AddEntriesFrom(ref input, _repeated_repeatedFixed32_codec); break; } case 306: case 305: { - repeatedFixed64_.AddEntriesFrom(input, _repeated_repeatedFixed64_codec); + repeatedFixed64_.AddEntriesFrom(ref input, _repeated_repeatedFixed64_codec); break; } case 314: case 317: { - repeatedSfixed32_.AddEntriesFrom(input, _repeated_repeatedSfixed32_codec); + repeatedSfixed32_.AddEntriesFrom(ref input, _repeated_repeatedSfixed32_codec); break; } case 322: case 321: { - repeatedSfixed64_.AddEntriesFrom(input, _repeated_repeatedSfixed64_codec); + repeatedSfixed64_.AddEntriesFrom(ref input, _repeated_repeatedSfixed64_codec); break; } case 330: case 333: { - repeatedFloat_.AddEntriesFrom(input, _repeated_repeatedFloat_codec); + repeatedFloat_.AddEntriesFrom(ref input, _repeated_repeatedFloat_codec); break; } case 338: case 337: { - repeatedDouble_.AddEntriesFrom(input, _repeated_repeatedDouble_codec); + repeatedDouble_.AddEntriesFrom(ref input, _repeated_repeatedDouble_codec); break; } case 346: case 344: { - repeatedBool_.AddEntriesFrom(input, _repeated_repeatedBool_codec); + repeatedBool_.AddEntriesFrom(ref input, _repeated_repeatedBool_codec); break; } case 354: { - repeatedString_.AddEntriesFrom(input, _repeated_repeatedString_codec); + repeatedString_.AddEntriesFrom(ref input, _repeated_repeatedString_codec); break; } case 362: { - repeatedBytes_.AddEntriesFrom(input, _repeated_repeatedBytes_codec); + repeatedBytes_.AddEntriesFrom(ref input, _repeated_repeatedBytes_codec); break; } case 386: { - repeatedNestedMessage_.AddEntriesFrom(input, _repeated_repeatedNestedMessage_codec); + repeatedNestedMessage_.AddEntriesFrom(ref input, _repeated_repeatedNestedMessage_codec); break; } case 394: { - repeatedForeignMessage_.AddEntriesFrom(input, _repeated_repeatedForeignMessage_codec); + repeatedForeignMessage_.AddEntriesFrom(ref input, _repeated_repeatedForeignMessage_codec); break; } case 410: case 408: { - repeatedNestedEnum_.AddEntriesFrom(input, _repeated_repeatedNestedEnum_codec); + repeatedNestedEnum_.AddEntriesFrom(ref input, _repeated_repeatedNestedEnum_codec); break; } case 418: case 416: { - repeatedForeignEnum_.AddEntriesFrom(input, _repeated_repeatedForeignEnum_codec); + repeatedForeignEnum_.AddEntriesFrom(ref input, _repeated_repeatedForeignEnum_codec); break; } case 434: { - repeatedStringPiece_.AddEntriesFrom(input, _repeated_repeatedStringPiece_codec); + repeatedStringPiece_.AddEntriesFrom(ref input, _repeated_repeatedStringPiece_codec); break; } case 442: { - repeatedCord_.AddEntriesFrom(input, _repeated_repeatedCord_codec); + repeatedCord_.AddEntriesFrom(ref input, _repeated_repeatedCord_codec); break; } case 450: { - mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec); + mapInt32Int32_.AddEntriesFrom(ref input, _map_mapInt32Int32_codec); break; } case 458: { - mapInt64Int64_.AddEntriesFrom(input, _map_mapInt64Int64_codec); + mapInt64Int64_.AddEntriesFrom(ref input, _map_mapInt64Int64_codec); break; } case 466: { - mapUint32Uint32_.AddEntriesFrom(input, _map_mapUint32Uint32_codec); + mapUint32Uint32_.AddEntriesFrom(ref input, _map_mapUint32Uint32_codec); break; } case 474: { - mapUint64Uint64_.AddEntriesFrom(input, _map_mapUint64Uint64_codec); + mapUint64Uint64_.AddEntriesFrom(ref input, _map_mapUint64Uint64_codec); break; } case 482: { - mapSint32Sint32_.AddEntriesFrom(input, _map_mapSint32Sint32_codec); + mapSint32Sint32_.AddEntriesFrom(ref input, _map_mapSint32Sint32_codec); break; } case 490: { - mapSint64Sint64_.AddEntriesFrom(input, _map_mapSint64Sint64_codec); + mapSint64Sint64_.AddEntriesFrom(ref input, _map_mapSint64Sint64_codec); break; } case 498: { - mapFixed32Fixed32_.AddEntriesFrom(input, _map_mapFixed32Fixed32_codec); + mapFixed32Fixed32_.AddEntriesFrom(ref input, _map_mapFixed32Fixed32_codec); break; } case 506: { - mapFixed64Fixed64_.AddEntriesFrom(input, _map_mapFixed64Fixed64_codec); + mapFixed64Fixed64_.AddEntriesFrom(ref input, _map_mapFixed64Fixed64_codec); break; } case 514: { - mapSfixed32Sfixed32_.AddEntriesFrom(input, _map_mapSfixed32Sfixed32_codec); + mapSfixed32Sfixed32_.AddEntriesFrom(ref input, _map_mapSfixed32Sfixed32_codec); break; } case 522: { - mapSfixed64Sfixed64_.AddEntriesFrom(input, _map_mapSfixed64Sfixed64_codec); + mapSfixed64Sfixed64_.AddEntriesFrom(ref input, _map_mapSfixed64Sfixed64_codec); break; } case 530: { - mapInt32Float_.AddEntriesFrom(input, _map_mapInt32Float_codec); + mapInt32Float_.AddEntriesFrom(ref input, _map_mapInt32Float_codec); break; } case 538: { - mapInt32Double_.AddEntriesFrom(input, _map_mapInt32Double_codec); + mapInt32Double_.AddEntriesFrom(ref input, _map_mapInt32Double_codec); break; } case 546: { - mapBoolBool_.AddEntriesFrom(input, _map_mapBoolBool_codec); + mapBoolBool_.AddEntriesFrom(ref input, _map_mapBoolBool_codec); break; } case 554: { - mapStringString_.AddEntriesFrom(input, _map_mapStringString_codec); + mapStringString_.AddEntriesFrom(ref input, _map_mapStringString_codec); break; } case 562: { - mapStringBytes_.AddEntriesFrom(input, _map_mapStringBytes_codec); + mapStringBytes_.AddEntriesFrom(ref input, _map_mapStringBytes_codec); break; } case 570: { - mapStringNestedMessage_.AddEntriesFrom(input, _map_mapStringNestedMessage_codec); + mapStringNestedMessage_.AddEntriesFrom(ref input, _map_mapStringNestedMessage_codec); break; } case 578: { - mapStringForeignMessage_.AddEntriesFrom(input, _map_mapStringForeignMessage_codec); + mapStringForeignMessage_.AddEntriesFrom(ref input, _map_mapStringForeignMessage_codec); break; } case 586: { - mapStringNestedEnum_.AddEntriesFrom(input, _map_mapStringNestedEnum_codec); + mapStringNestedEnum_.AddEntriesFrom(ref input, _map_mapStringNestedEnum_codec); break; } case 594: { - mapStringForeignEnum_.AddEntriesFrom(input, _map_mapStringForeignEnum_codec); + mapStringForeignEnum_.AddEntriesFrom(ref input, _map_mapStringForeignEnum_codec); break; } case 602: case 600: { - packedInt32_.AddEntriesFrom(input, _repeated_packedInt32_codec); + packedInt32_.AddEntriesFrom(ref input, _repeated_packedInt32_codec); break; } case 610: case 608: { - packedInt64_.AddEntriesFrom(input, _repeated_packedInt64_codec); + packedInt64_.AddEntriesFrom(ref input, _repeated_packedInt64_codec); break; } case 618: case 616: { - packedUint32_.AddEntriesFrom(input, _repeated_packedUint32_codec); + packedUint32_.AddEntriesFrom(ref input, _repeated_packedUint32_codec); break; } case 626: case 624: { - packedUint64_.AddEntriesFrom(input, _repeated_packedUint64_codec); + packedUint64_.AddEntriesFrom(ref input, _repeated_packedUint64_codec); break; } case 634: case 632: { - packedSint32_.AddEntriesFrom(input, _repeated_packedSint32_codec); + packedSint32_.AddEntriesFrom(ref input, _repeated_packedSint32_codec); break; } case 642: case 640: { - packedSint64_.AddEntriesFrom(input, _repeated_packedSint64_codec); + packedSint64_.AddEntriesFrom(ref input, _repeated_packedSint64_codec); break; } case 650: case 653: { - packedFixed32_.AddEntriesFrom(input, _repeated_packedFixed32_codec); + packedFixed32_.AddEntriesFrom(ref input, _repeated_packedFixed32_codec); break; } case 658: case 657: { - packedFixed64_.AddEntriesFrom(input, _repeated_packedFixed64_codec); + packedFixed64_.AddEntriesFrom(ref input, _repeated_packedFixed64_codec); break; } case 666: case 669: { - packedSfixed32_.AddEntriesFrom(input, _repeated_packedSfixed32_codec); + packedSfixed32_.AddEntriesFrom(ref input, _repeated_packedSfixed32_codec); break; } case 674: case 673: { - packedSfixed64_.AddEntriesFrom(input, _repeated_packedSfixed64_codec); + packedSfixed64_.AddEntriesFrom(ref input, _repeated_packedSfixed64_codec); break; } case 682: case 685: { - packedFloat_.AddEntriesFrom(input, _repeated_packedFloat_codec); + packedFloat_.AddEntriesFrom(ref input, _repeated_packedFloat_codec); break; } case 690: case 689: { - packedDouble_.AddEntriesFrom(input, _repeated_packedDouble_codec); + packedDouble_.AddEntriesFrom(ref input, _repeated_packedDouble_codec); break; } case 698: case 696: { - packedBool_.AddEntriesFrom(input, _repeated_packedBool_codec); + packedBool_.AddEntriesFrom(ref input, _repeated_packedBool_codec); break; } case 706: case 704: { - packedNestedEnum_.AddEntriesFrom(input, _repeated_packedNestedEnum_codec); + packedNestedEnum_.AddEntriesFrom(ref input, _repeated_packedNestedEnum_codec); break; } case 714: case 712: { - unpackedInt32_.AddEntriesFrom(input, _repeated_unpackedInt32_codec); + unpackedInt32_.AddEntriesFrom(ref input, _repeated_unpackedInt32_codec); break; } case 722: case 720: { - unpackedInt64_.AddEntriesFrom(input, _repeated_unpackedInt64_codec); + unpackedInt64_.AddEntriesFrom(ref input, _repeated_unpackedInt64_codec); break; } case 730: case 728: { - unpackedUint32_.AddEntriesFrom(input, _repeated_unpackedUint32_codec); + unpackedUint32_.AddEntriesFrom(ref input, _repeated_unpackedUint32_codec); break; } case 738: case 736: { - unpackedUint64_.AddEntriesFrom(input, _repeated_unpackedUint64_codec); + unpackedUint64_.AddEntriesFrom(ref input, _repeated_unpackedUint64_codec); break; } case 746: case 744: { - unpackedSint32_.AddEntriesFrom(input, _repeated_unpackedSint32_codec); + unpackedSint32_.AddEntriesFrom(ref input, _repeated_unpackedSint32_codec); break; } case 754: case 752: { - unpackedSint64_.AddEntriesFrom(input, _repeated_unpackedSint64_codec); + unpackedSint64_.AddEntriesFrom(ref input, _repeated_unpackedSint64_codec); break; } case 762: case 765: { - unpackedFixed32_.AddEntriesFrom(input, _repeated_unpackedFixed32_codec); + unpackedFixed32_.AddEntriesFrom(ref input, _repeated_unpackedFixed32_codec); break; } case 770: case 769: { - unpackedFixed64_.AddEntriesFrom(input, _repeated_unpackedFixed64_codec); + unpackedFixed64_.AddEntriesFrom(ref input, _repeated_unpackedFixed64_codec); break; } case 778: case 781: { - unpackedSfixed32_.AddEntriesFrom(input, _repeated_unpackedSfixed32_codec); + unpackedSfixed32_.AddEntriesFrom(ref input, _repeated_unpackedSfixed32_codec); break; } case 786: case 785: { - unpackedSfixed64_.AddEntriesFrom(input, _repeated_unpackedSfixed64_codec); + unpackedSfixed64_.AddEntriesFrom(ref input, _repeated_unpackedSfixed64_codec); break; } case 794: case 797: { - unpackedFloat_.AddEntriesFrom(input, _repeated_unpackedFloat_codec); + unpackedFloat_.AddEntriesFrom(ref input, _repeated_unpackedFloat_codec); break; } case 802: case 801: { - unpackedDouble_.AddEntriesFrom(input, _repeated_unpackedDouble_codec); + unpackedDouble_.AddEntriesFrom(ref input, _repeated_unpackedDouble_codec); break; } case 810: case 808: { - unpackedBool_.AddEntriesFrom(input, _repeated_unpackedBool_codec); + unpackedBool_.AddEntriesFrom(ref input, _repeated_unpackedBool_codec); break; } case 818: case 816: { - unpackedNestedEnum_.AddEntriesFrom(input, _repeated_unpackedNestedEnum_codec); + unpackedNestedEnum_.AddEntriesFrom(ref input, _repeated_unpackedNestedEnum_codec); break; } case 888: { @@ -3934,7 +3939,7 @@ public enum NestedEnum { [pbr::OriginalName("NEG")] Neg = -1, } - public sealed partial class NestedMessage : pb::IMessage { + public sealed partial class NestedMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -4099,11 +4104,16 @@ public sealed partial class NestedMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { A = input.ReadInt32(); @@ -4125,7 +4135,7 @@ public sealed partial class NestedMessage : pb::IMessage { /// /// groups /// - public sealed partial class Data : pb::IMessage { + public sealed partial class Data : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Data()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -4290,13 +4300,18 @@ public sealed partial class Data : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { case 1612: return; default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 1616: { GroupInt32 = input.ReadInt32(); @@ -4315,7 +4330,7 @@ public sealed partial class Data : pb::IMessage { /// /// message_set test case. /// - public sealed partial class MessageSetCorrect : pb::IExtendableMessage { + public sealed partial class MessageSetCorrect : pb::IExtendableMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MessageSetCorrect()); private pb::UnknownFieldSet _unknownFields; private pb::ExtensionSet _extensions; @@ -4420,12 +4435,17 @@ public sealed partial class MessageSetCorrect : pb::IExtendableMessage { + public sealed partial class MessageSetCorrectExtension1 : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MessageSetCorrectExtension1()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -4581,11 +4601,16 @@ public sealed partial class MessageSetCorrectExtension1 : pb::IMessage { + public sealed partial class MessageSetCorrectExtension2 : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MessageSetCorrectExtension2()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -4734,11 +4759,16 @@ public sealed partial class MessageSetCorrectExtension2 : pb::IMessage { + public sealed partial class ForeignMessageProto2 : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ForeignMessageProto2()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -4892,11 +4922,16 @@ public sealed partial class ForeignMessageProto2 : pb::IMessage { + public sealed partial class UnknownToTestAllTypes : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new UnknownToTestAllTypes()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -5200,11 +5235,16 @@ public sealed partial class UnknownToTestAllTypes : pb::IMessageContainer for nested types declared in the UnknownToTestAllTypes message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class OptionalGroup : pb::IMessage { + public sealed partial class OptionalGroup : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OptionalGroup()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -5373,13 +5413,18 @@ public sealed partial class OptionalGroup : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { case 8036: return; default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { A = input.ReadInt32(); diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs index 064d0c0acec0..465d5e804c47 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs @@ -259,7 +259,7 @@ public enum ForeignEnum { /// could trigger bugs that occur in any message type in this file. We verify /// this stays true in a unit test. /// - public sealed partial class TestAllTypesProto3 : pb::IMessage { + public sealed partial class TestAllTypesProto3 : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestAllTypesProto3()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -3383,11 +3383,16 @@ public enum OneofFieldOneofCase { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { OptionalInt32 = input.ReadInt32(); @@ -3492,317 +3497,317 @@ public enum OneofFieldOneofCase { } case 250: case 248: { - repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec); + repeatedInt32_.AddEntriesFrom(ref input, _repeated_repeatedInt32_codec); break; } case 258: case 256: { - repeatedInt64_.AddEntriesFrom(input, _repeated_repeatedInt64_codec); + repeatedInt64_.AddEntriesFrom(ref input, _repeated_repeatedInt64_codec); break; } case 266: case 264: { - repeatedUint32_.AddEntriesFrom(input, _repeated_repeatedUint32_codec); + repeatedUint32_.AddEntriesFrom(ref input, _repeated_repeatedUint32_codec); break; } case 274: case 272: { - repeatedUint64_.AddEntriesFrom(input, _repeated_repeatedUint64_codec); + repeatedUint64_.AddEntriesFrom(ref input, _repeated_repeatedUint64_codec); break; } case 282: case 280: { - repeatedSint32_.AddEntriesFrom(input, _repeated_repeatedSint32_codec); + repeatedSint32_.AddEntriesFrom(ref input, _repeated_repeatedSint32_codec); break; } case 290: case 288: { - repeatedSint64_.AddEntriesFrom(input, _repeated_repeatedSint64_codec); + repeatedSint64_.AddEntriesFrom(ref input, _repeated_repeatedSint64_codec); break; } case 298: case 301: { - repeatedFixed32_.AddEntriesFrom(input, _repeated_repeatedFixed32_codec); + repeatedFixed32_.AddEntriesFrom(ref input, _repeated_repeatedFixed32_codec); break; } case 306: case 305: { - repeatedFixed64_.AddEntriesFrom(input, _repeated_repeatedFixed64_codec); + repeatedFixed64_.AddEntriesFrom(ref input, _repeated_repeatedFixed64_codec); break; } case 314: case 317: { - repeatedSfixed32_.AddEntriesFrom(input, _repeated_repeatedSfixed32_codec); + repeatedSfixed32_.AddEntriesFrom(ref input, _repeated_repeatedSfixed32_codec); break; } case 322: case 321: { - repeatedSfixed64_.AddEntriesFrom(input, _repeated_repeatedSfixed64_codec); + repeatedSfixed64_.AddEntriesFrom(ref input, _repeated_repeatedSfixed64_codec); break; } case 330: case 333: { - repeatedFloat_.AddEntriesFrom(input, _repeated_repeatedFloat_codec); + repeatedFloat_.AddEntriesFrom(ref input, _repeated_repeatedFloat_codec); break; } case 338: case 337: { - repeatedDouble_.AddEntriesFrom(input, _repeated_repeatedDouble_codec); + repeatedDouble_.AddEntriesFrom(ref input, _repeated_repeatedDouble_codec); break; } case 346: case 344: { - repeatedBool_.AddEntriesFrom(input, _repeated_repeatedBool_codec); + repeatedBool_.AddEntriesFrom(ref input, _repeated_repeatedBool_codec); break; } case 354: { - repeatedString_.AddEntriesFrom(input, _repeated_repeatedString_codec); + repeatedString_.AddEntriesFrom(ref input, _repeated_repeatedString_codec); break; } case 362: { - repeatedBytes_.AddEntriesFrom(input, _repeated_repeatedBytes_codec); + repeatedBytes_.AddEntriesFrom(ref input, _repeated_repeatedBytes_codec); break; } case 386: { - repeatedNestedMessage_.AddEntriesFrom(input, _repeated_repeatedNestedMessage_codec); + repeatedNestedMessage_.AddEntriesFrom(ref input, _repeated_repeatedNestedMessage_codec); break; } case 394: { - repeatedForeignMessage_.AddEntriesFrom(input, _repeated_repeatedForeignMessage_codec); + repeatedForeignMessage_.AddEntriesFrom(ref input, _repeated_repeatedForeignMessage_codec); break; } case 410: case 408: { - repeatedNestedEnum_.AddEntriesFrom(input, _repeated_repeatedNestedEnum_codec); + repeatedNestedEnum_.AddEntriesFrom(ref input, _repeated_repeatedNestedEnum_codec); break; } case 418: case 416: { - repeatedForeignEnum_.AddEntriesFrom(input, _repeated_repeatedForeignEnum_codec); + repeatedForeignEnum_.AddEntriesFrom(ref input, _repeated_repeatedForeignEnum_codec); break; } case 434: { - repeatedStringPiece_.AddEntriesFrom(input, _repeated_repeatedStringPiece_codec); + repeatedStringPiece_.AddEntriesFrom(ref input, _repeated_repeatedStringPiece_codec); break; } case 442: { - repeatedCord_.AddEntriesFrom(input, _repeated_repeatedCord_codec); + repeatedCord_.AddEntriesFrom(ref input, _repeated_repeatedCord_codec); break; } case 450: { - mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec); + mapInt32Int32_.AddEntriesFrom(ref input, _map_mapInt32Int32_codec); break; } case 458: { - mapInt64Int64_.AddEntriesFrom(input, _map_mapInt64Int64_codec); + mapInt64Int64_.AddEntriesFrom(ref input, _map_mapInt64Int64_codec); break; } case 466: { - mapUint32Uint32_.AddEntriesFrom(input, _map_mapUint32Uint32_codec); + mapUint32Uint32_.AddEntriesFrom(ref input, _map_mapUint32Uint32_codec); break; } case 474: { - mapUint64Uint64_.AddEntriesFrom(input, _map_mapUint64Uint64_codec); + mapUint64Uint64_.AddEntriesFrom(ref input, _map_mapUint64Uint64_codec); break; } case 482: { - mapSint32Sint32_.AddEntriesFrom(input, _map_mapSint32Sint32_codec); + mapSint32Sint32_.AddEntriesFrom(ref input, _map_mapSint32Sint32_codec); break; } case 490: { - mapSint64Sint64_.AddEntriesFrom(input, _map_mapSint64Sint64_codec); + mapSint64Sint64_.AddEntriesFrom(ref input, _map_mapSint64Sint64_codec); break; } case 498: { - mapFixed32Fixed32_.AddEntriesFrom(input, _map_mapFixed32Fixed32_codec); + mapFixed32Fixed32_.AddEntriesFrom(ref input, _map_mapFixed32Fixed32_codec); break; } case 506: { - mapFixed64Fixed64_.AddEntriesFrom(input, _map_mapFixed64Fixed64_codec); + mapFixed64Fixed64_.AddEntriesFrom(ref input, _map_mapFixed64Fixed64_codec); break; } case 514: { - mapSfixed32Sfixed32_.AddEntriesFrom(input, _map_mapSfixed32Sfixed32_codec); + mapSfixed32Sfixed32_.AddEntriesFrom(ref input, _map_mapSfixed32Sfixed32_codec); break; } case 522: { - mapSfixed64Sfixed64_.AddEntriesFrom(input, _map_mapSfixed64Sfixed64_codec); + mapSfixed64Sfixed64_.AddEntriesFrom(ref input, _map_mapSfixed64Sfixed64_codec); break; } case 530: { - mapInt32Float_.AddEntriesFrom(input, _map_mapInt32Float_codec); + mapInt32Float_.AddEntriesFrom(ref input, _map_mapInt32Float_codec); break; } case 538: { - mapInt32Double_.AddEntriesFrom(input, _map_mapInt32Double_codec); + mapInt32Double_.AddEntriesFrom(ref input, _map_mapInt32Double_codec); break; } case 546: { - mapBoolBool_.AddEntriesFrom(input, _map_mapBoolBool_codec); + mapBoolBool_.AddEntriesFrom(ref input, _map_mapBoolBool_codec); break; } case 554: { - mapStringString_.AddEntriesFrom(input, _map_mapStringString_codec); + mapStringString_.AddEntriesFrom(ref input, _map_mapStringString_codec); break; } case 562: { - mapStringBytes_.AddEntriesFrom(input, _map_mapStringBytes_codec); + mapStringBytes_.AddEntriesFrom(ref input, _map_mapStringBytes_codec); break; } case 570: { - mapStringNestedMessage_.AddEntriesFrom(input, _map_mapStringNestedMessage_codec); + mapStringNestedMessage_.AddEntriesFrom(ref input, _map_mapStringNestedMessage_codec); break; } case 578: { - mapStringForeignMessage_.AddEntriesFrom(input, _map_mapStringForeignMessage_codec); + mapStringForeignMessage_.AddEntriesFrom(ref input, _map_mapStringForeignMessage_codec); break; } case 586: { - mapStringNestedEnum_.AddEntriesFrom(input, _map_mapStringNestedEnum_codec); + mapStringNestedEnum_.AddEntriesFrom(ref input, _map_mapStringNestedEnum_codec); break; } case 594: { - mapStringForeignEnum_.AddEntriesFrom(input, _map_mapStringForeignEnum_codec); + mapStringForeignEnum_.AddEntriesFrom(ref input, _map_mapStringForeignEnum_codec); break; } case 602: case 600: { - packedInt32_.AddEntriesFrom(input, _repeated_packedInt32_codec); + packedInt32_.AddEntriesFrom(ref input, _repeated_packedInt32_codec); break; } case 610: case 608: { - packedInt64_.AddEntriesFrom(input, _repeated_packedInt64_codec); + packedInt64_.AddEntriesFrom(ref input, _repeated_packedInt64_codec); break; } case 618: case 616: { - packedUint32_.AddEntriesFrom(input, _repeated_packedUint32_codec); + packedUint32_.AddEntriesFrom(ref input, _repeated_packedUint32_codec); break; } case 626: case 624: { - packedUint64_.AddEntriesFrom(input, _repeated_packedUint64_codec); + packedUint64_.AddEntriesFrom(ref input, _repeated_packedUint64_codec); break; } case 634: case 632: { - packedSint32_.AddEntriesFrom(input, _repeated_packedSint32_codec); + packedSint32_.AddEntriesFrom(ref input, _repeated_packedSint32_codec); break; } case 642: case 640: { - packedSint64_.AddEntriesFrom(input, _repeated_packedSint64_codec); + packedSint64_.AddEntriesFrom(ref input, _repeated_packedSint64_codec); break; } case 650: case 653: { - packedFixed32_.AddEntriesFrom(input, _repeated_packedFixed32_codec); + packedFixed32_.AddEntriesFrom(ref input, _repeated_packedFixed32_codec); break; } case 658: case 657: { - packedFixed64_.AddEntriesFrom(input, _repeated_packedFixed64_codec); + packedFixed64_.AddEntriesFrom(ref input, _repeated_packedFixed64_codec); break; } case 666: case 669: { - packedSfixed32_.AddEntriesFrom(input, _repeated_packedSfixed32_codec); + packedSfixed32_.AddEntriesFrom(ref input, _repeated_packedSfixed32_codec); break; } case 674: case 673: { - packedSfixed64_.AddEntriesFrom(input, _repeated_packedSfixed64_codec); + packedSfixed64_.AddEntriesFrom(ref input, _repeated_packedSfixed64_codec); break; } case 682: case 685: { - packedFloat_.AddEntriesFrom(input, _repeated_packedFloat_codec); + packedFloat_.AddEntriesFrom(ref input, _repeated_packedFloat_codec); break; } case 690: case 689: { - packedDouble_.AddEntriesFrom(input, _repeated_packedDouble_codec); + packedDouble_.AddEntriesFrom(ref input, _repeated_packedDouble_codec); break; } case 698: case 696: { - packedBool_.AddEntriesFrom(input, _repeated_packedBool_codec); + packedBool_.AddEntriesFrom(ref input, _repeated_packedBool_codec); break; } case 706: case 704: { - packedNestedEnum_.AddEntriesFrom(input, _repeated_packedNestedEnum_codec); + packedNestedEnum_.AddEntriesFrom(ref input, _repeated_packedNestedEnum_codec); break; } case 714: case 712: { - unpackedInt32_.AddEntriesFrom(input, _repeated_unpackedInt32_codec); + unpackedInt32_.AddEntriesFrom(ref input, _repeated_unpackedInt32_codec); break; } case 722: case 720: { - unpackedInt64_.AddEntriesFrom(input, _repeated_unpackedInt64_codec); + unpackedInt64_.AddEntriesFrom(ref input, _repeated_unpackedInt64_codec); break; } case 730: case 728: { - unpackedUint32_.AddEntriesFrom(input, _repeated_unpackedUint32_codec); + unpackedUint32_.AddEntriesFrom(ref input, _repeated_unpackedUint32_codec); break; } case 738: case 736: { - unpackedUint64_.AddEntriesFrom(input, _repeated_unpackedUint64_codec); + unpackedUint64_.AddEntriesFrom(ref input, _repeated_unpackedUint64_codec); break; } case 746: case 744: { - unpackedSint32_.AddEntriesFrom(input, _repeated_unpackedSint32_codec); + unpackedSint32_.AddEntriesFrom(ref input, _repeated_unpackedSint32_codec); break; } case 754: case 752: { - unpackedSint64_.AddEntriesFrom(input, _repeated_unpackedSint64_codec); + unpackedSint64_.AddEntriesFrom(ref input, _repeated_unpackedSint64_codec); break; } case 762: case 765: { - unpackedFixed32_.AddEntriesFrom(input, _repeated_unpackedFixed32_codec); + unpackedFixed32_.AddEntriesFrom(ref input, _repeated_unpackedFixed32_codec); break; } case 770: case 769: { - unpackedFixed64_.AddEntriesFrom(input, _repeated_unpackedFixed64_codec); + unpackedFixed64_.AddEntriesFrom(ref input, _repeated_unpackedFixed64_codec); break; } case 778: case 781: { - unpackedSfixed32_.AddEntriesFrom(input, _repeated_unpackedSfixed32_codec); + unpackedSfixed32_.AddEntriesFrom(ref input, _repeated_unpackedSfixed32_codec); break; } case 786: case 785: { - unpackedSfixed64_.AddEntriesFrom(input, _repeated_unpackedSfixed64_codec); + unpackedSfixed64_.AddEntriesFrom(ref input, _repeated_unpackedSfixed64_codec); break; } case 794: case 797: { - unpackedFloat_.AddEntriesFrom(input, _repeated_unpackedFloat_codec); + unpackedFloat_.AddEntriesFrom(ref input, _repeated_unpackedFloat_codec); break; } case 802: case 801: { - unpackedDouble_.AddEntriesFrom(input, _repeated_unpackedDouble_codec); + unpackedDouble_.AddEntriesFrom(ref input, _repeated_unpackedDouble_codec); break; } case 810: case 808: { - unpackedBool_.AddEntriesFrom(input, _repeated_unpackedBool_codec); + unpackedBool_.AddEntriesFrom(ref input, _repeated_unpackedBool_codec); break; } case 818: case 816: { - unpackedNestedEnum_.AddEntriesFrom(input, _repeated_unpackedNestedEnum_codec); + unpackedNestedEnum_.AddEntriesFrom(ref input, _repeated_unpackedNestedEnum_codec); break; } case 888: { @@ -3848,102 +3853,102 @@ public enum OneofFieldOneofCase { break; } case 1610: { - bool? value = _single_optionalBoolWrapper_codec.Read(input); + bool? value = _single_optionalBoolWrapper_codec.Read(ref input); if (optionalBoolWrapper_ == null || value != false) { OptionalBoolWrapper = value; } break; } case 1618: { - int? value = _single_optionalInt32Wrapper_codec.Read(input); + int? value = _single_optionalInt32Wrapper_codec.Read(ref input); if (optionalInt32Wrapper_ == null || value != 0) { OptionalInt32Wrapper = value; } break; } case 1626: { - long? value = _single_optionalInt64Wrapper_codec.Read(input); + long? value = _single_optionalInt64Wrapper_codec.Read(ref input); if (optionalInt64Wrapper_ == null || value != 0L) { OptionalInt64Wrapper = value; } break; } case 1634: { - uint? value = _single_optionalUint32Wrapper_codec.Read(input); + uint? value = _single_optionalUint32Wrapper_codec.Read(ref input); if (optionalUint32Wrapper_ == null || value != 0) { OptionalUint32Wrapper = value; } break; } case 1642: { - ulong? value = _single_optionalUint64Wrapper_codec.Read(input); + ulong? value = _single_optionalUint64Wrapper_codec.Read(ref input); if (optionalUint64Wrapper_ == null || value != 0UL) { OptionalUint64Wrapper = value; } break; } case 1650: { - float? value = _single_optionalFloatWrapper_codec.Read(input); + float? value = _single_optionalFloatWrapper_codec.Read(ref input); if (optionalFloatWrapper_ == null || value != 0F) { OptionalFloatWrapper = value; } break; } case 1658: { - double? value = _single_optionalDoubleWrapper_codec.Read(input); + double? value = _single_optionalDoubleWrapper_codec.Read(ref input); if (optionalDoubleWrapper_ == null || value != 0D) { OptionalDoubleWrapper = value; } break; } case 1666: { - string value = _single_optionalStringWrapper_codec.Read(input); + string value = _single_optionalStringWrapper_codec.Read(ref input); if (optionalStringWrapper_ == null || value != "") { OptionalStringWrapper = value; } break; } case 1674: { - pb::ByteString value = _single_optionalBytesWrapper_codec.Read(input); + pb::ByteString value = _single_optionalBytesWrapper_codec.Read(ref input); if (optionalBytesWrapper_ == null || value != pb::ByteString.Empty) { OptionalBytesWrapper = value; } break; } case 1690: { - repeatedBoolWrapper_.AddEntriesFrom(input, _repeated_repeatedBoolWrapper_codec); + repeatedBoolWrapper_.AddEntriesFrom(ref input, _repeated_repeatedBoolWrapper_codec); break; } case 1698: { - repeatedInt32Wrapper_.AddEntriesFrom(input, _repeated_repeatedInt32Wrapper_codec); + repeatedInt32Wrapper_.AddEntriesFrom(ref input, _repeated_repeatedInt32Wrapper_codec); break; } case 1706: { - repeatedInt64Wrapper_.AddEntriesFrom(input, _repeated_repeatedInt64Wrapper_codec); + repeatedInt64Wrapper_.AddEntriesFrom(ref input, _repeated_repeatedInt64Wrapper_codec); break; } case 1714: { - repeatedUint32Wrapper_.AddEntriesFrom(input, _repeated_repeatedUint32Wrapper_codec); + repeatedUint32Wrapper_.AddEntriesFrom(ref input, _repeated_repeatedUint32Wrapper_codec); break; } case 1722: { - repeatedUint64Wrapper_.AddEntriesFrom(input, _repeated_repeatedUint64Wrapper_codec); + repeatedUint64Wrapper_.AddEntriesFrom(ref input, _repeated_repeatedUint64Wrapper_codec); break; } case 1730: { - repeatedFloatWrapper_.AddEntriesFrom(input, _repeated_repeatedFloatWrapper_codec); + repeatedFloatWrapper_.AddEntriesFrom(ref input, _repeated_repeatedFloatWrapper_codec); break; } case 1738: { - repeatedDoubleWrapper_.AddEntriesFrom(input, _repeated_repeatedDoubleWrapper_codec); + repeatedDoubleWrapper_.AddEntriesFrom(ref input, _repeated_repeatedDoubleWrapper_codec); break; } case 1746: { - repeatedStringWrapper_.AddEntriesFrom(input, _repeated_repeatedStringWrapper_codec); + repeatedStringWrapper_.AddEntriesFrom(ref input, _repeated_repeatedStringWrapper_codec); break; } case 1754: { - repeatedBytesWrapper_.AddEntriesFrom(input, _repeated_repeatedBytesWrapper_codec); + repeatedBytesWrapper_.AddEntriesFrom(ref input, _repeated_repeatedBytesWrapper_codec); break; } case 2410: { @@ -3989,31 +3994,31 @@ public enum OneofFieldOneofCase { break; } case 2490: { - repeatedDuration_.AddEntriesFrom(input, _repeated_repeatedDuration_codec); + repeatedDuration_.AddEntriesFrom(ref input, _repeated_repeatedDuration_codec); break; } case 2498: { - repeatedTimestamp_.AddEntriesFrom(input, _repeated_repeatedTimestamp_codec); + repeatedTimestamp_.AddEntriesFrom(ref input, _repeated_repeatedTimestamp_codec); break; } case 2506: { - repeatedFieldmask_.AddEntriesFrom(input, _repeated_repeatedFieldmask_codec); + repeatedFieldmask_.AddEntriesFrom(ref input, _repeated_repeatedFieldmask_codec); break; } case 2522: { - repeatedAny_.AddEntriesFrom(input, _repeated_repeatedAny_codec); + repeatedAny_.AddEntriesFrom(ref input, _repeated_repeatedAny_codec); break; } case 2530: { - repeatedValue_.AddEntriesFrom(input, _repeated_repeatedValue_codec); + repeatedValue_.AddEntriesFrom(ref input, _repeated_repeatedValue_codec); break; } case 2538: { - repeatedListValue_.AddEntriesFrom(input, _repeated_repeatedListValue_codec); + repeatedListValue_.AddEntriesFrom(ref input, _repeated_repeatedListValue_codec); break; } case 2594: { - repeatedStruct_.AddEntriesFrom(input, _repeated_repeatedStruct_codec); + repeatedStruct_.AddEntriesFrom(ref input, _repeated_repeatedStruct_codec); break; } case 3208: { @@ -4115,7 +4120,7 @@ public enum AliasedEnum { [pbr::OriginalName("bAz", PreferredAlias = false)] BAz = 2, } - public sealed partial class NestedMessage : pb::IMessage { + public sealed partial class NestedMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -4255,11 +4260,16 @@ public sealed partial class NestedMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { A = input.ReadInt32(); @@ -4283,7 +4293,7 @@ public sealed partial class NestedMessage : pb::IMessage { } - public sealed partial class ForeignMessage : pb::IMessage { + public sealed partial class ForeignMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ForeignMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -4396,11 +4406,16 @@ public sealed partial class ForeignMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { C = input.ReadInt32(); diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs b/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs index 25fecb9b29e7..b25816759330 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs @@ -1120,7 +1120,7 @@ public enum VeryLargeEnum { /// This proto includes every type of field in both singular and repeated /// forms. /// - public sealed partial class TestAllTypes : pb::IMessage { + public sealed partial class TestAllTypes : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestAllTypes()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -3504,11 +3504,16 @@ public enum OneofFieldOneofCase { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { OptionalInt32 = input.ReadInt32(); @@ -3634,118 +3639,118 @@ public enum OneofFieldOneofCase { } case 250: case 248: { - repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec); + repeatedInt32_.AddEntriesFrom(ref input, _repeated_repeatedInt32_codec); break; } case 258: case 256: { - repeatedInt64_.AddEntriesFrom(input, _repeated_repeatedInt64_codec); + repeatedInt64_.AddEntriesFrom(ref input, _repeated_repeatedInt64_codec); break; } case 266: case 264: { - repeatedUint32_.AddEntriesFrom(input, _repeated_repeatedUint32_codec); + repeatedUint32_.AddEntriesFrom(ref input, _repeated_repeatedUint32_codec); break; } case 274: case 272: { - repeatedUint64_.AddEntriesFrom(input, _repeated_repeatedUint64_codec); + repeatedUint64_.AddEntriesFrom(ref input, _repeated_repeatedUint64_codec); break; } case 282: case 280: { - repeatedSint32_.AddEntriesFrom(input, _repeated_repeatedSint32_codec); + repeatedSint32_.AddEntriesFrom(ref input, _repeated_repeatedSint32_codec); break; } case 290: case 288: { - repeatedSint64_.AddEntriesFrom(input, _repeated_repeatedSint64_codec); + repeatedSint64_.AddEntriesFrom(ref input, _repeated_repeatedSint64_codec); break; } case 298: case 301: { - repeatedFixed32_.AddEntriesFrom(input, _repeated_repeatedFixed32_codec); + repeatedFixed32_.AddEntriesFrom(ref input, _repeated_repeatedFixed32_codec); break; } case 306: case 305: { - repeatedFixed64_.AddEntriesFrom(input, _repeated_repeatedFixed64_codec); + repeatedFixed64_.AddEntriesFrom(ref input, _repeated_repeatedFixed64_codec); break; } case 314: case 317: { - repeatedSfixed32_.AddEntriesFrom(input, _repeated_repeatedSfixed32_codec); + repeatedSfixed32_.AddEntriesFrom(ref input, _repeated_repeatedSfixed32_codec); break; } case 322: case 321: { - repeatedSfixed64_.AddEntriesFrom(input, _repeated_repeatedSfixed64_codec); + repeatedSfixed64_.AddEntriesFrom(ref input, _repeated_repeatedSfixed64_codec); break; } case 330: case 333: { - repeatedFloat_.AddEntriesFrom(input, _repeated_repeatedFloat_codec); + repeatedFloat_.AddEntriesFrom(ref input, _repeated_repeatedFloat_codec); break; } case 338: case 337: { - repeatedDouble_.AddEntriesFrom(input, _repeated_repeatedDouble_codec); + repeatedDouble_.AddEntriesFrom(ref input, _repeated_repeatedDouble_codec); break; } case 346: case 344: { - repeatedBool_.AddEntriesFrom(input, _repeated_repeatedBool_codec); + repeatedBool_.AddEntriesFrom(ref input, _repeated_repeatedBool_codec); break; } case 354: { - repeatedString_.AddEntriesFrom(input, _repeated_repeatedString_codec); + repeatedString_.AddEntriesFrom(ref input, _repeated_repeatedString_codec); break; } case 362: { - repeatedBytes_.AddEntriesFrom(input, _repeated_repeatedBytes_codec); + repeatedBytes_.AddEntriesFrom(ref input, _repeated_repeatedBytes_codec); break; } case 371: { - repeatedGroup_.AddEntriesFrom(input, _repeated_repeatedGroup_codec); + repeatedGroup_.AddEntriesFrom(ref input, _repeated_repeatedGroup_codec); break; } case 386: { - repeatedNestedMessage_.AddEntriesFrom(input, _repeated_repeatedNestedMessage_codec); + repeatedNestedMessage_.AddEntriesFrom(ref input, _repeated_repeatedNestedMessage_codec); break; } case 394: { - repeatedForeignMessage_.AddEntriesFrom(input, _repeated_repeatedForeignMessage_codec); + repeatedForeignMessage_.AddEntriesFrom(ref input, _repeated_repeatedForeignMessage_codec); break; } case 402: { - repeatedImportMessage_.AddEntriesFrom(input, _repeated_repeatedImportMessage_codec); + repeatedImportMessage_.AddEntriesFrom(ref input, _repeated_repeatedImportMessage_codec); break; } case 410: case 408: { - repeatedNestedEnum_.AddEntriesFrom(input, _repeated_repeatedNestedEnum_codec); + repeatedNestedEnum_.AddEntriesFrom(ref input, _repeated_repeatedNestedEnum_codec); break; } case 418: case 416: { - repeatedForeignEnum_.AddEntriesFrom(input, _repeated_repeatedForeignEnum_codec); + repeatedForeignEnum_.AddEntriesFrom(ref input, _repeated_repeatedForeignEnum_codec); break; } case 426: case 424: { - repeatedImportEnum_.AddEntriesFrom(input, _repeated_repeatedImportEnum_codec); + repeatedImportEnum_.AddEntriesFrom(ref input, _repeated_repeatedImportEnum_codec); break; } case 434: { - repeatedStringPiece_.AddEntriesFrom(input, _repeated_repeatedStringPiece_codec); + repeatedStringPiece_.AddEntriesFrom(ref input, _repeated_repeatedStringPiece_codec); break; } case 442: { - repeatedCord_.AddEntriesFrom(input, _repeated_repeatedCord_codec); + repeatedCord_.AddEntriesFrom(ref input, _repeated_repeatedCord_codec); break; } case 458: { - repeatedLazyMessage_.AddEntriesFrom(input, _repeated_repeatedLazyMessage_codec); + repeatedLazyMessage_.AddEntriesFrom(ref input, _repeated_repeatedLazyMessage_codec); break; } case 488: { @@ -3867,7 +3872,7 @@ public enum NestedEnum { [pbr::OriginalName("NEG")] Neg = -1, } - public sealed partial class NestedMessage : pb::IMessage { + public sealed partial class NestedMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -4000,11 +4005,16 @@ public sealed partial class NestedMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Bb = input.ReadInt32(); @@ -4016,7 +4026,7 @@ public sealed partial class NestedMessage : pb::IMessage { } - public sealed partial class OptionalGroup : pb::IMessage { + public sealed partial class OptionalGroup : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OptionalGroup()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -4144,13 +4154,18 @@ public sealed partial class OptionalGroup : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { case 132: return; default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 136: { A = input.ReadInt32(); @@ -4162,7 +4177,7 @@ public sealed partial class OptionalGroup : pb::IMessage { } - public sealed partial class RepeatedGroup : pb::IMessage { + public sealed partial class RepeatedGroup : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new RepeatedGroup()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -4290,13 +4305,18 @@ public sealed partial class RepeatedGroup : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { case 372: return; default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 376: { A = input.ReadInt32(); @@ -4316,7 +4336,7 @@ public sealed partial class RepeatedGroup : pb::IMessage { /// /// This proto includes a recursively nested message. /// - public sealed partial class NestedTestAllTypes : pb::IMessage { + public sealed partial class NestedTestAllTypes : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedTestAllTypes()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -4495,11 +4515,16 @@ public sealed partial class NestedTestAllTypes : pb::IMessage { + public sealed partial class TestDeprecatedFields : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestDeprecatedFields()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -4723,11 +4748,16 @@ public enum OneofFieldsOneofCase { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { DeprecatedInt32 = input.ReadInt32(); @@ -4744,7 +4774,7 @@ public enum OneofFieldsOneofCase { } [global::System.ObsoleteAttribute] - public sealed partial class TestDeprecatedMessage : pb::IMessage { + public sealed partial class TestDeprecatedMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestDeprecatedMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -4833,11 +4863,16 @@ public sealed partial class TestDeprecatedMessage : pb::IMessage - public sealed partial class ForeignMessage : pb::IMessage { + public sealed partial class ForeignMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ForeignMessage()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -5014,11 +5049,16 @@ public sealed partial class ForeignMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { C = input.ReadInt32(); @@ -5034,7 +5074,7 @@ public sealed partial class ForeignMessage : pb::IMessage { } - public sealed partial class TestReservedFields : pb::IMessage { + public sealed partial class TestReservedFields : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestReservedFields()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -5123,11 +5163,16 @@ public sealed partial class TestReservedFields : pb::IMessage { + public sealed partial class TestAllExtensions : pb::IExtendableMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestAllExtensions()); private pb::UnknownFieldSet _unknownFields; private pb::ExtensionSet _extensions; @@ -5240,12 +5285,17 @@ public sealed partial class TestAllExtensions : pb::IExtendableMessage { + public sealed partial class OptionalGroup_extension : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OptionalGroup_extension()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -5404,13 +5454,18 @@ public sealed partial class OptionalGroup_extension : pb::IMessage { + public sealed partial class RepeatedGroup_extension : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new RepeatedGroup_extension()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -5550,13 +5605,18 @@ public sealed partial class RepeatedGroup_extension : pb::IMessage { + public sealed partial class TestGroup : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestGroup()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -5734,11 +5794,16 @@ public sealed partial class TestGroup : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 131: { if (!HasOptionalGroup) { @@ -5759,7 +5824,7 @@ public sealed partial class TestGroup : pb::IMessage { /// Container for nested types declared in the TestGroup message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class OptionalGroup : pb::IMessage { + public sealed partial class OptionalGroup : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OptionalGroup()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -5887,13 +5952,18 @@ public sealed partial class OptionalGroup : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { case 132: return; default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 136: { A = input.ReadInt32(); @@ -5910,7 +5980,7 @@ public sealed partial class OptionalGroup : pb::IMessage { } - public sealed partial class TestGroupExtension : pb::IExtendableMessage { + public sealed partial class TestGroupExtension : pb::IExtendableMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestGroupExtension()); private pb::UnknownFieldSet _unknownFields; private pb::ExtensionSet _extensions; @@ -6015,12 +6085,17 @@ public sealed partial class TestGroupExtension : pb::IExtendableMessage { + public sealed partial class TestNestedExtension : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestNestedExtension()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -6140,11 +6215,16 @@ public sealed partial class TestNestedExtension : pb::IMessageContainer for nested types declared in the TestNestedExtension message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class OptionalGroup_extension : pb::IMessage { + public sealed partial class OptionalGroup_extension : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OptionalGroup_extension()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -6282,13 +6362,18 @@ public sealed partial class OptionalGroup_extension : pb::IMessage - public sealed partial class TestRequired : pb::IMessage { + public sealed partial class TestRequired : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestRequired()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -7653,11 +7738,16 @@ public sealed partial class TestRequired : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { A = input.ReadInt32(); @@ -7808,7 +7898,7 @@ public static partial class Extensions { } - public sealed partial class TestRequiredForeign : pb::IMessage { + public sealed partial class TestRequiredForeign : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestRequiredForeign()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -7989,11 +8079,16 @@ public sealed partial class TestRequiredForeign : pb::IMessage { + public sealed partial class TestRequiredMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestRequiredMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -8195,11 +8290,16 @@ public sealed partial class TestRequiredMessage : pb::IMessage /// Test that we can use NestedMessage from outside TestAllTypes. /// - public sealed partial class TestForeignNested : pb::IMessage { + public sealed partial class TestForeignNested : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestForeignNested()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -8354,11 +8454,16 @@ public sealed partial class TestForeignNested : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { if (!HasForeignNested) { @@ -8376,7 +8481,7 @@ public sealed partial class TestForeignNested : pb::IMessage /// /// TestEmptyMessage is used to test unknown field support. /// - public sealed partial class TestEmptyMessage : pb::IMessage { + public sealed partial class TestEmptyMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestEmptyMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -8465,11 +8570,16 @@ public sealed partial class TestEmptyMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } @@ -8481,7 +8591,7 @@ public sealed partial class TestEmptyMessage : pb::IMessage { /// Like above, but declare all field numbers as potential extensions. No /// actual extensions should ever be defined for this type. /// - public sealed partial class TestEmptyMessageWithExtensions : pb::IExtendableMessage { + public sealed partial class TestEmptyMessageWithExtensions : pb::IExtendableMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestEmptyMessageWithExtensions()); private pb::UnknownFieldSet _unknownFields; private pb::ExtensionSet _extensions; @@ -8586,12 +8696,17 @@ public sealed partial class TestEmptyMessageWithExtensions : pb::IExtendableMess [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); } break; } @@ -8622,7 +8737,7 @@ public sealed partial class TestEmptyMessageWithExtensions : pb::IExtendableMess } - public sealed partial class TestMultipleExtensionRanges : pb::IExtendableMessage { + public sealed partial class TestMultipleExtensionRanges : pb::IExtendableMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMultipleExtensionRanges()); private pb::UnknownFieldSet _unknownFields; private pb::ExtensionSet _extensions; @@ -8727,12 +8842,17 @@ public sealed partial class TestMultipleExtensionRanges : pb::IExtendableMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); } break; } @@ -8766,7 +8886,7 @@ public sealed partial class TestMultipleExtensionRanges : pb::IExtendableMessage /// /// Test that really large tag numbers don't break anything. /// - public sealed partial class TestReallyLargeTagNumber : pb::IMessage { + public sealed partial class TestReallyLargeTagNumber : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestReallyLargeTagNumber()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -8935,11 +9055,16 @@ public sealed partial class TestReallyLargeTagNumber : pb::IMessage { + public sealed partial class TestRecursiveMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestRecursiveMessage()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -9120,11 +9245,16 @@ public sealed partial class TestRecursiveMessage : pb::IMessage /// Test that mutual recursion works. /// - public sealed partial class TestMutualRecursionA : pb::IMessage { + public sealed partial class TestMutualRecursionA : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMutualRecursionA()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -9310,11 +9440,16 @@ public sealed partial class TestMutualRecursionA : pb::IMessageContainer for nested types declared in the TestMutualRecursionA message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class SubMessage : pb::IMessage { + public sealed partial class SubMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SubMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -9464,11 +9599,16 @@ public sealed partial class SubMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { if (!HasB) { @@ -9483,7 +9623,7 @@ public sealed partial class SubMessage : pb::IMessage { } - public sealed partial class SubGroup : pb::IMessage { + public sealed partial class SubGroup : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SubGroup()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -9649,13 +9789,18 @@ public sealed partial class SubGroup : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { case 20: return; default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 26: { if (!HasSubMessage) { @@ -9682,7 +9827,7 @@ public sealed partial class SubGroup : pb::IMessage { } - public sealed partial class TestMutualRecursionB : pb::IMessage { + public sealed partial class TestMutualRecursionB : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMutualRecursionB()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -9847,11 +9992,16 @@ public sealed partial class TestMutualRecursionB : pb::IMessage { + public sealed partial class TestIsInitialized : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestIsInitialized()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -9996,11 +10146,16 @@ public sealed partial class TestIsInitialized : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { if (!HasSubMessage) { @@ -10017,7 +10172,7 @@ public sealed partial class TestIsInitialized : pb::IMessage /// Container for nested types declared in the TestIsInitialized message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class SubMessage : pb::IMessage { + public sealed partial class SubMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SubMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -10144,11 +10299,16 @@ public sealed partial class SubMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 11: { if (!HasSubGroup) { @@ -10165,7 +10325,7 @@ public sealed partial class SubMessage : pb::IMessage { /// Container for nested types declared in the SubMessage message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class SubGroup : pb::IMessage { + public sealed partial class SubGroup : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SubGroup()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -10293,13 +10453,18 @@ public sealed partial class SubGroup : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { case 12: return; default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 16: { I = input.ReadInt32(); @@ -10327,7 +10492,7 @@ public sealed partial class SubGroup : pb::IMessage { /// to compile with proto1, this will emit an error; so we only include it /// in protobuf_unittest_proto. /// - public sealed partial class TestDupFieldNumber : pb::IMessage { + public sealed partial class TestDupFieldNumber : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestDupFieldNumber()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -10534,11 +10699,16 @@ public sealed partial class TestDupFieldNumber : pb::IMessageContainer for nested types declared in the TestDupFieldNumber message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class Foo : pb::IMessage { + public sealed partial class Foo : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Foo()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -10694,13 +10864,18 @@ public sealed partial class Foo : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { case 20: return; default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { A = input.ReadInt32(); @@ -10712,7 +10887,7 @@ public sealed partial class Foo : pb::IMessage { } - public sealed partial class Bar : pb::IMessage { + public sealed partial class Bar : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Bar()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -10840,13 +11015,18 @@ public sealed partial class Bar : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { case 28: return; default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { A = input.ReadInt32(); @@ -10866,7 +11046,7 @@ public sealed partial class Bar : pb::IMessage { /// /// Additional messages for testing lazy fields. /// - public sealed partial class TestEagerMessage : pb::IMessage { + public sealed partial class TestEagerMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestEagerMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -10992,11 +11172,16 @@ public sealed partial class TestEagerMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { if (!HasSubMessage) { @@ -11011,7 +11196,7 @@ public sealed partial class TestEagerMessage : pb::IMessage { } - public sealed partial class TestLazyMessage : pb::IMessage { + public sealed partial class TestLazyMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestLazyMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -11137,11 +11322,16 @@ public sealed partial class TestLazyMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { if (!HasSubMessage) { @@ -11159,7 +11349,7 @@ public sealed partial class TestLazyMessage : pb::IMessage { /// /// Needed for a Python test. /// - public sealed partial class TestNestedMessageHasBits : pb::IMessage { + public sealed partial class TestNestedMessageHasBits : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestNestedMessageHasBits()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -11285,11 +11475,16 @@ public sealed partial class TestNestedMessageHasBits : pb::IMessageContainer for nested types declared in the TestNestedMessageHasBits message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class NestedMessage : pb::IMessage { + public sealed partial class NestedMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -11427,19 +11622,24 @@ public sealed partial class NestedMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: case 8: { - nestedmessageRepeatedInt32_.AddEntriesFrom(input, _repeated_nestedmessageRepeatedInt32_codec); + nestedmessageRepeatedInt32_.AddEntriesFrom(ref input, _repeated_nestedmessageRepeatedInt32_codec); break; } case 18: { - nestedmessageRepeatedForeignmessage_.AddEntriesFrom(input, _repeated_nestedmessageRepeatedForeignmessage_codec); + nestedmessageRepeatedForeignmessage_.AddEntriesFrom(ref input, _repeated_nestedmessageRepeatedForeignmessage_codec); break; } } @@ -11457,7 +11657,7 @@ public sealed partial class NestedMessage : pb::IMessage { /// Test message with CamelCase field names. This violates Protocol Buffer /// standard style. /// - public sealed partial class TestCamelCaseFieldNames : pb::IMessage { + public sealed partial class TestCamelCaseFieldNames : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestCamelCaseFieldNames()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -11863,11 +12063,16 @@ public sealed partial class TestCamelCaseFieldNames : pb::IMessage - public sealed partial class TestFieldOrderings : pb::IExtendableMessage { + public sealed partial class TestFieldOrderings : pb::IExtendableMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestFieldOrderings()); private pb::UnknownFieldSet _unknownFields; private pb::ExtensionSet _extensions; @@ -12186,12 +12391,17 @@ public sealed partial class TestFieldOrderings : pb::IExtendableMessageContainer for nested types declared in the TestFieldOrderings message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class NestedMessage : pb::IMessage { + public sealed partial class NestedMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -12413,11 +12623,16 @@ public sealed partial class NestedMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Bb = input.ReadInt32(); @@ -12438,7 +12653,7 @@ public sealed partial class NestedMessage : pb::IMessage { } - public sealed partial class TestExtensionOrderings1 : pb::IMessage { + public sealed partial class TestExtensionOrderings1 : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestExtensionOrderings1()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -12563,11 +12778,16 @@ public sealed partial class TestExtensionOrderings1 : pb::IMessage { + public sealed partial class TestExtensionOrderings2 : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestExtensionOrderings2()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -12713,11 +12933,16 @@ public sealed partial class TestExtensionOrderings2 : pb::IMessageContainer for nested types declared in the TestExtensionOrderings2 message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class TestExtensionOrderings3 : pb::IMessage { + public sealed partial class TestExtensionOrderings3 : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestExtensionOrderings3()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -12856,11 +13081,16 @@ public sealed partial class TestExtensionOrderings3 : pb::IMessage { + public sealed partial class TestExtremeDefaultValues : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestExtremeDefaultValues()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -14001,11 +14231,16 @@ public sealed partial class TestExtremeDefaultValues : pb::IMessage { + public sealed partial class SparseEnumMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SparseEnumMessage()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -14249,11 +14484,16 @@ public sealed partial class SparseEnumMessage : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { SparseEnum = (global::Google.Protobuf.TestProtos.Proto2.TestSparseEnum) input.ReadEnum(); @@ -14268,7 +14508,7 @@ public sealed partial class SparseEnumMessage : pb::IMessage /// /// Test String and Bytes: string is for valid UTF-8 strings /// - public sealed partial class OneString : pb::IMessage { + public sealed partial class OneString : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneString()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -14393,11 +14633,16 @@ public sealed partial class OneString : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Data = input.ReadString(); @@ -14409,7 +14654,7 @@ public sealed partial class OneString : pb::IMessage { } - public sealed partial class MoreString : pb::IMessage { + public sealed partial class MoreString : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MoreString()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -14514,14 +14759,19 @@ public sealed partial class MoreString : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { - data_.AddEntriesFrom(input, _repeated_data_codec); + data_.AddEntriesFrom(ref input, _repeated_data_codec); break; } } @@ -14530,7 +14780,7 @@ public sealed partial class MoreString : pb::IMessage { } - public sealed partial class OneBytes : pb::IMessage { + public sealed partial class OneBytes : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneBytes()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -14655,11 +14905,16 @@ public sealed partial class OneBytes : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Data = input.ReadBytes(); @@ -14671,7 +14926,7 @@ public sealed partial class OneBytes : pb::IMessage { } - public sealed partial class MoreBytes : pb::IMessage { + public sealed partial class MoreBytes : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MoreBytes()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -14776,14 +15031,19 @@ public sealed partial class MoreBytes : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { - data_.AddEntriesFrom(input, _repeated_data_codec); + data_.AddEntriesFrom(ref input, _repeated_data_codec); break; } } @@ -14795,7 +15055,7 @@ public sealed partial class MoreBytes : pb::IMessage { /// /// Test int32, uint32, int64, uint64, and bool are all compatible /// - public sealed partial class Int32Message : pb::IMessage { + public sealed partial class Int32Message : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Int32Message()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -14923,11 +15183,16 @@ public sealed partial class Int32Message : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Data = input.ReadInt32(); @@ -14939,7 +15204,7 @@ public sealed partial class Int32Message : pb::IMessage { } - public sealed partial class Uint32Message : pb::IMessage { + public sealed partial class Uint32Message : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Uint32Message()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -15067,11 +15332,16 @@ public sealed partial class Uint32Message : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Data = input.ReadUInt32(); @@ -15083,7 +15353,7 @@ public sealed partial class Uint32Message : pb::IMessage { } - public sealed partial class Int64Message : pb::IMessage { + public sealed partial class Int64Message : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Int64Message()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -15211,11 +15481,16 @@ public sealed partial class Int64Message : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Data = input.ReadInt64(); @@ -15227,7 +15502,7 @@ public sealed partial class Int64Message : pb::IMessage { } - public sealed partial class Uint64Message : pb::IMessage { + public sealed partial class Uint64Message : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Uint64Message()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -15355,11 +15630,16 @@ public sealed partial class Uint64Message : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Data = input.ReadUInt64(); @@ -15371,7 +15651,7 @@ public sealed partial class Uint64Message : pb::IMessage { } - public sealed partial class BoolMessage : pb::IMessage { + public sealed partial class BoolMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BoolMessage()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -15499,11 +15779,16 @@ public sealed partial class BoolMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Data = input.ReadBool(); @@ -15518,7 +15803,7 @@ public sealed partial class BoolMessage : pb::IMessage { /// /// Test oneofs. /// - public sealed partial class TestOneof : pb::IMessage { + public sealed partial class TestOneof : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestOneof()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -15795,11 +16080,16 @@ public enum FooOneofCase { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { FooInt = input.ReadInt32(); @@ -15835,7 +16125,7 @@ public enum FooOneofCase { /// Container for nested types declared in the TestOneof message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class FooGroup : pb::IMessage { + public sealed partial class FooGroup : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooGroup()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -15999,13 +16289,18 @@ public sealed partial class FooGroup : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { case 36: return; default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 40: { A = input.ReadInt32(); @@ -16026,7 +16321,7 @@ public sealed partial class FooGroup : pb::IMessage { } - public sealed partial class TestOneofBackwardsCompatible : pb::IMessage { + public sealed partial class TestOneofBackwardsCompatible : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestOneofBackwardsCompatible()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -16265,11 +16560,16 @@ public sealed partial class TestOneofBackwardsCompatible : pb::IMessageContainer for nested types declared in the TestOneofBackwardsCompatible message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class FooGroup : pb::IMessage { + public sealed partial class FooGroup : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooGroup()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -16465,13 +16765,18 @@ public sealed partial class FooGroup : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { case 36: return; default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 40: { A = input.ReadInt32(); @@ -16492,7 +16797,7 @@ public sealed partial class FooGroup : pb::IMessage { } - public sealed partial class TestOneof2 : pb::IMessage { + public sealed partial class TestOneof2 : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestOneof2()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -17301,11 +17606,16 @@ public enum BarOneofCase { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { FooInt = input.ReadInt32(); @@ -17406,7 +17716,7 @@ public enum NestedEnum { [pbr::OriginalName("BAZ")] Baz = 3, } - public sealed partial class FooGroup : pb::IMessage { + public sealed partial class FooGroup : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooGroup()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -17570,13 +17880,18 @@ public sealed partial class FooGroup : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { case 68: return; default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 72: { A = input.ReadInt32(); @@ -17592,7 +17907,7 @@ public sealed partial class FooGroup : pb::IMessage { } - public sealed partial class NestedMessage : pb::IMessage { + public sealed partial class NestedMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -17736,11 +18051,16 @@ public sealed partial class NestedMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { QuxInt = input.ReadInt64(); @@ -17748,7 +18068,7 @@ public sealed partial class NestedMessage : pb::IMessage { } case 18: case 16: { - corgeInt_.AddEntriesFrom(input, _repeated_corgeInt_codec); + corgeInt_.AddEntriesFrom(ref input, _repeated_corgeInt_codec); break; } } @@ -17762,7 +18082,7 @@ public sealed partial class NestedMessage : pb::IMessage { } - public sealed partial class TestRequiredOneof : pb::IMessage { + public sealed partial class TestRequiredOneof : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestRequiredOneof()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -17996,11 +18316,16 @@ public enum FooOneofCase { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { FooInt = input.ReadInt32(); @@ -18027,7 +18352,7 @@ public enum FooOneofCase { /// Container for nested types declared in the TestRequiredOneof message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class NestedMessage : pb::IMessage { + public sealed partial class NestedMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -18155,11 +18480,16 @@ public sealed partial class NestedMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 9: { RequiredDouble = input.ReadDouble(); @@ -18176,7 +18506,7 @@ public sealed partial class NestedMessage : pb::IMessage { } - public sealed partial class TestRequiredMap : pb::IMessage { + public sealed partial class TestRequiredMap : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestRequiredMap()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -18281,14 +18611,19 @@ public sealed partial class TestRequiredMap : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { - foo_.AddEntriesFrom(input, _map_foo_codec); + foo_.AddEntriesFrom(ref input, _map_foo_codec); break; } } @@ -18299,7 +18634,7 @@ public sealed partial class TestRequiredMap : pb::IMessage { /// Container for nested types declared in the TestRequiredMap message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class NestedMessage : pb::IMessage { + public sealed partial class NestedMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -18427,11 +18762,16 @@ public sealed partial class NestedMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { RequiredInt32 = input.ReadInt32(); @@ -18448,7 +18788,7 @@ public sealed partial class NestedMessage : pb::IMessage { } - public sealed partial class TestPackedTypes : pb::IMessage { + public sealed partial class TestPackedTypes : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestPackedTypes()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -18761,80 +19101,85 @@ public sealed partial class TestPackedTypes : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 722: case 720: { - packedInt32_.AddEntriesFrom(input, _repeated_packedInt32_codec); + packedInt32_.AddEntriesFrom(ref input, _repeated_packedInt32_codec); break; } case 730: case 728: { - packedInt64_.AddEntriesFrom(input, _repeated_packedInt64_codec); + packedInt64_.AddEntriesFrom(ref input, _repeated_packedInt64_codec); break; } case 738: case 736: { - packedUint32_.AddEntriesFrom(input, _repeated_packedUint32_codec); + packedUint32_.AddEntriesFrom(ref input, _repeated_packedUint32_codec); break; } case 746: case 744: { - packedUint64_.AddEntriesFrom(input, _repeated_packedUint64_codec); + packedUint64_.AddEntriesFrom(ref input, _repeated_packedUint64_codec); break; } case 754: case 752: { - packedSint32_.AddEntriesFrom(input, _repeated_packedSint32_codec); + packedSint32_.AddEntriesFrom(ref input, _repeated_packedSint32_codec); break; } case 762: case 760: { - packedSint64_.AddEntriesFrom(input, _repeated_packedSint64_codec); + packedSint64_.AddEntriesFrom(ref input, _repeated_packedSint64_codec); break; } case 770: case 773: { - packedFixed32_.AddEntriesFrom(input, _repeated_packedFixed32_codec); + packedFixed32_.AddEntriesFrom(ref input, _repeated_packedFixed32_codec); break; } case 778: case 777: { - packedFixed64_.AddEntriesFrom(input, _repeated_packedFixed64_codec); + packedFixed64_.AddEntriesFrom(ref input, _repeated_packedFixed64_codec); break; } case 786: case 789: { - packedSfixed32_.AddEntriesFrom(input, _repeated_packedSfixed32_codec); + packedSfixed32_.AddEntriesFrom(ref input, _repeated_packedSfixed32_codec); break; } case 794: case 793: { - packedSfixed64_.AddEntriesFrom(input, _repeated_packedSfixed64_codec); + packedSfixed64_.AddEntriesFrom(ref input, _repeated_packedSfixed64_codec); break; } case 802: case 805: { - packedFloat_.AddEntriesFrom(input, _repeated_packedFloat_codec); + packedFloat_.AddEntriesFrom(ref input, _repeated_packedFloat_codec); break; } case 810: case 809: { - packedDouble_.AddEntriesFrom(input, _repeated_packedDouble_codec); + packedDouble_.AddEntriesFrom(ref input, _repeated_packedDouble_codec); break; } case 818: case 816: { - packedBool_.AddEntriesFrom(input, _repeated_packedBool_codec); + packedBool_.AddEntriesFrom(ref input, _repeated_packedBool_codec); break; } case 826: case 824: { - packedEnum_.AddEntriesFrom(input, _repeated_packedEnum_codec); + packedEnum_.AddEntriesFrom(ref input, _repeated_packedEnum_codec); break; } } @@ -18847,7 +19192,7 @@ public sealed partial class TestPackedTypes : pb::IMessage { /// A message with the same fields as TestPackedTypes, but without packing. Used /// to test packed <-> unpacked wire compatibility. /// - public sealed partial class TestUnpackedTypes : pb::IMessage { + public sealed partial class TestUnpackedTypes : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestUnpackedTypes()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -19160,80 +19505,85 @@ public sealed partial class TestUnpackedTypes : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 722: case 720: { - unpackedInt32_.AddEntriesFrom(input, _repeated_unpackedInt32_codec); + unpackedInt32_.AddEntriesFrom(ref input, _repeated_unpackedInt32_codec); break; } case 730: case 728: { - unpackedInt64_.AddEntriesFrom(input, _repeated_unpackedInt64_codec); + unpackedInt64_.AddEntriesFrom(ref input, _repeated_unpackedInt64_codec); break; } case 738: case 736: { - unpackedUint32_.AddEntriesFrom(input, _repeated_unpackedUint32_codec); + unpackedUint32_.AddEntriesFrom(ref input, _repeated_unpackedUint32_codec); break; } case 746: case 744: { - unpackedUint64_.AddEntriesFrom(input, _repeated_unpackedUint64_codec); + unpackedUint64_.AddEntriesFrom(ref input, _repeated_unpackedUint64_codec); break; } case 754: case 752: { - unpackedSint32_.AddEntriesFrom(input, _repeated_unpackedSint32_codec); + unpackedSint32_.AddEntriesFrom(ref input, _repeated_unpackedSint32_codec); break; } case 762: case 760: { - unpackedSint64_.AddEntriesFrom(input, _repeated_unpackedSint64_codec); + unpackedSint64_.AddEntriesFrom(ref input, _repeated_unpackedSint64_codec); break; } case 770: case 773: { - unpackedFixed32_.AddEntriesFrom(input, _repeated_unpackedFixed32_codec); + unpackedFixed32_.AddEntriesFrom(ref input, _repeated_unpackedFixed32_codec); break; } case 778: case 777: { - unpackedFixed64_.AddEntriesFrom(input, _repeated_unpackedFixed64_codec); + unpackedFixed64_.AddEntriesFrom(ref input, _repeated_unpackedFixed64_codec); break; } case 786: case 789: { - unpackedSfixed32_.AddEntriesFrom(input, _repeated_unpackedSfixed32_codec); + unpackedSfixed32_.AddEntriesFrom(ref input, _repeated_unpackedSfixed32_codec); break; } case 794: case 793: { - unpackedSfixed64_.AddEntriesFrom(input, _repeated_unpackedSfixed64_codec); + unpackedSfixed64_.AddEntriesFrom(ref input, _repeated_unpackedSfixed64_codec); break; } case 802: case 805: { - unpackedFloat_.AddEntriesFrom(input, _repeated_unpackedFloat_codec); + unpackedFloat_.AddEntriesFrom(ref input, _repeated_unpackedFloat_codec); break; } case 810: case 809: { - unpackedDouble_.AddEntriesFrom(input, _repeated_unpackedDouble_codec); + unpackedDouble_.AddEntriesFrom(ref input, _repeated_unpackedDouble_codec); break; } case 818: case 816: { - unpackedBool_.AddEntriesFrom(input, _repeated_unpackedBool_codec); + unpackedBool_.AddEntriesFrom(ref input, _repeated_unpackedBool_codec); break; } case 826: case 824: { - unpackedEnum_.AddEntriesFrom(input, _repeated_unpackedEnum_codec); + unpackedEnum_.AddEntriesFrom(ref input, _repeated_unpackedEnum_codec); break; } } @@ -19242,7 +19592,7 @@ public sealed partial class TestUnpackedTypes : pb::IMessage } - public sealed partial class TestPackedExtensions : pb::IExtendableMessage { + public sealed partial class TestPackedExtensions : pb::IExtendableMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestPackedExtensions()); private pb::UnknownFieldSet _unknownFields; private pb::ExtensionSet _extensions; @@ -19347,12 +19697,17 @@ public sealed partial class TestPackedExtensions : pb::IExtendableMessage { + public sealed partial class TestUnpackedExtensions : pb::IExtendableMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestUnpackedExtensions()); private pb::UnknownFieldSet _unknownFields; private pb::ExtensionSet _extensions; @@ -19488,12 +19843,17 @@ public sealed partial class TestUnpackedExtensions : pb::IExtendableMessage - public sealed partial class TestDynamicExtensions : pb::IMessage { + public sealed partial class TestDynamicExtensions : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestDynamicExtensions()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -19837,11 +20197,16 @@ public sealed partial class TestDynamicExtensions : pb::IMessage { + public sealed partial class DynamicMessageType : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DynamicMessageType()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -20020,11 +20385,16 @@ public sealed partial class DynamicMessageType : pb::IMessage { + public sealed partial class TestRepeatedScalarDifferentTagSizes : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestRepeatedScalarDifferentTagSizes()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -20240,40 +20610,45 @@ public sealed partial class TestRepeatedScalarDifferentTagSizes : pb::IMessage - public sealed partial class TestParsingMerge : pb::IExtendableMessage { + public sealed partial class TestParsingMerge : pb::IExtendableMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestParsingMerge()); private pb::UnknownFieldSet _unknownFields; private pb::ExtensionSet _extensions; @@ -20535,12 +20910,17 @@ public sealed partial class TestParsingMerge : pb::IExtendableMessage - public sealed partial class RepeatedFieldsGenerator : pb::IMessage { + public sealed partial class RepeatedFieldsGenerator : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new RepeatedFieldsGenerator()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -20810,38 +21190,43 @@ public sealed partial class RepeatedFieldsGenerator : pb::IMessageContainer for nested types declared in the RepeatedFieldsGenerator message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class Group1 : pb::IMessage { + public sealed partial class Group1 : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Group1()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -20978,13 +21363,18 @@ public sealed partial class Group1 : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { case 84: return; default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 90: { if (!HasField1) { @@ -20999,7 +21389,7 @@ public sealed partial class Group1 : pb::IMessage { } - public sealed partial class Group2 : pb::IMessage { + public sealed partial class Group2 : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Group2()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -21125,13 +21515,18 @@ public sealed partial class Group2 : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { case 164: return; default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 170: { if (!HasField1) { @@ -21151,7 +21546,7 @@ public sealed partial class Group2 : pb::IMessage { } - public sealed partial class OptionalGroup : pb::IMessage { + public sealed partial class OptionalGroup : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OptionalGroup()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -21277,13 +21672,18 @@ public sealed partial class OptionalGroup : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { case 84: return; default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 90: { if (!HasOptionalGroupAllTypes) { @@ -21298,7 +21698,7 @@ public sealed partial class OptionalGroup : pb::IMessage { } - public sealed partial class RepeatedGroup : pb::IMessage { + public sealed partial class RepeatedGroup : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new RepeatedGroup()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -21424,13 +21824,18 @@ public sealed partial class RepeatedGroup : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { case 164: return; default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 170: { if (!HasRepeatedGroupAllTypes) { @@ -21461,7 +21866,7 @@ public static partial class Extensions { } - public sealed partial class TestCommentInjectionMessage : pb::IMessage { + public sealed partial class TestCommentInjectionMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestCommentInjectionMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -21589,11 +21994,16 @@ public sealed partial class TestCommentInjectionMessage : pb::IMessage /// Test that RPC services work. /// - public sealed partial class FooRequest : pb::IMessage { + public sealed partial class FooRequest : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooRequest()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -21697,11 +22107,16 @@ public sealed partial class FooRequest : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } @@ -21709,7 +22124,7 @@ public sealed partial class FooRequest : pb::IMessage { } - public sealed partial class FooResponse : pb::IMessage { + public sealed partial class FooResponse : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooResponse()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -21798,11 +22213,16 @@ public sealed partial class FooResponse : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } @@ -21810,7 +22230,7 @@ public sealed partial class FooResponse : pb::IMessage { } - public sealed partial class FooClientMessage : pb::IMessage { + public sealed partial class FooClientMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooClientMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -21899,11 +22319,16 @@ public sealed partial class FooClientMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } @@ -21911,7 +22336,7 @@ public sealed partial class FooClientMessage : pb::IMessage { } - public sealed partial class FooServerMessage : pb::IMessage { + public sealed partial class FooServerMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooServerMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -22000,11 +22425,16 @@ public sealed partial class FooServerMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } @@ -22012,7 +22442,7 @@ public sealed partial class FooServerMessage : pb::IMessage { } - public sealed partial class BarRequest : pb::IMessage { + public sealed partial class BarRequest : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BarRequest()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -22101,11 +22531,16 @@ public sealed partial class BarRequest : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } @@ -22113,7 +22548,7 @@ public sealed partial class BarRequest : pb::IMessage { } - public sealed partial class BarResponse : pb::IMessage { + public sealed partial class BarResponse : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BarResponse()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -22202,11 +22637,16 @@ public sealed partial class BarResponse : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } @@ -22214,7 +22654,7 @@ public sealed partial class BarResponse : pb::IMessage { } - public sealed partial class TestJsonName : pb::IMessage { + public sealed partial class TestJsonName : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestJsonName()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -22527,11 +22967,16 @@ public sealed partial class TestJsonName : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { FieldName1 = input.ReadInt32(); @@ -22563,7 +23008,7 @@ public sealed partial class TestJsonName : pb::IMessage { } - public sealed partial class TestHugeFieldNumbers : pb::IExtendableMessage { + public sealed partial class TestHugeFieldNumbers : pb::IExtendableMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestHugeFieldNumbers()); private pb::UnknownFieldSet _unknownFields; private pb::ExtensionSet _extensions; @@ -23160,12 +23605,17 @@ public enum OneofFieldOneofCase { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); } break; case 4294960000: { @@ -23178,12 +23628,12 @@ public enum OneofFieldOneofCase { } case 4294960018: case 4294960016: { - repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec); + repeatedInt32_.AddEntriesFrom(ref input, _repeated_repeatedInt32_codec); break; } case 4294960026: case 4294960024: { - packedInt32_.AddEntriesFrom(input, _repeated_packedInt32_codec); + packedInt32_.AddEntriesFrom(ref input, _repeated_packedInt32_codec); break; } case 4294960032: { @@ -23213,7 +23663,7 @@ public enum OneofFieldOneofCase { break; } case 4294960082: { - stringStringMap_.AddEntriesFrom(input, _map_stringStringMap_codec); + stringStringMap_.AddEntriesFrom(ref input, _map_stringStringMap_codec); break; } case 4294960088: { @@ -23267,7 +23717,7 @@ public enum OneofFieldOneofCase { /// Container for nested types declared in the TestHugeFieldNumbers message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class OptionalGroup : pb::IMessage { + public sealed partial class OptionalGroup : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OptionalGroup()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -23395,13 +23845,18 @@ public sealed partial class OptionalGroup : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { case 4294960068: return; default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 4294960072: { GroupA = input.ReadInt32(); @@ -23418,7 +23873,7 @@ public sealed partial class OptionalGroup : pb::IMessage { } - public sealed partial class TestExtensionInsideTable : pb::IExtendableMessage { + public sealed partial class TestExtensionInsideTable : pb::IExtendableMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestExtensionInsideTable()); private pb::UnknownFieldSet _unknownFields; private pb::ExtensionSet _extensions; @@ -23858,12 +24313,17 @@ public sealed partial class TestExtensionInsideTable : pb::IExtendableMessage - public sealed partial class TestMessageWithCustomOptions : pb::IMessage { + public sealed partial class TestMessageWithCustomOptions : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMessageWithCustomOptions()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -422,11 +422,16 @@ public enum AnOneofOneofCase { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Field1 = input.ReadString(); @@ -459,7 +464,7 @@ public enum AnEnum { /// A test RPC service with custom options at all possible locations (and also /// some regular options, to make sure they interact nicely). /// - public sealed partial class CustomOptionFooRequest : pb::IMessage { + public sealed partial class CustomOptionFooRequest : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionFooRequest()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -548,11 +553,16 @@ public sealed partial class CustomOptionFooRequest : pb::IMessage { + public sealed partial class CustomOptionFooResponse : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionFooResponse()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -649,11 +659,16 @@ public sealed partial class CustomOptionFooResponse : pb::IMessage { + public sealed partial class CustomOptionFooClientMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionFooClientMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -750,11 +765,16 @@ public sealed partial class CustomOptionFooClientMessage : pb::IMessage { + public sealed partial class CustomOptionFooServerMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionFooServerMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -851,11 +871,16 @@ public sealed partial class CustomOptionFooServerMessage : pb::IMessage { + public sealed partial class DummyMessageContainingEnum : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DummyMessageContainingEnum()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -952,11 +977,16 @@ public sealed partial class DummyMessageContainingEnum : pb::IMessage { + public sealed partial class DummyMessageInvalidAsOptionType : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DummyMessageInvalidAsOptionType()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1066,11 +1096,16 @@ public sealed partial class DummyMessageInvalidAsOptionType : pb::IMessage { + public sealed partial class CustomOptionMinIntegerValues : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionMinIntegerValues()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1167,11 +1202,16 @@ public sealed partial class CustomOptionMinIntegerValues : pb::IMessage { + public sealed partial class CustomOptionMaxIntegerValues : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionMaxIntegerValues()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1268,11 +1308,16 @@ public sealed partial class CustomOptionMaxIntegerValues : pb::IMessage { + public sealed partial class CustomOptionOtherValues : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionOtherValues()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1369,11 +1414,16 @@ public sealed partial class CustomOptionOtherValues : pb::IMessage { + public sealed partial class SettingRealsFromPositiveInts : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SettingRealsFromPositiveInts()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1470,11 +1520,16 @@ public sealed partial class SettingRealsFromPositiveInts : pb::IMessage { + public sealed partial class SettingRealsFromNegativeInts : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SettingRealsFromNegativeInts()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1571,11 +1626,16 @@ public sealed partial class SettingRealsFromNegativeInts : pb::IMessage { + public sealed partial class ComplexOptionType1 : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ComplexOptionType1()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1760,11 +1820,16 @@ public sealed partial class ComplexOptionType1 : pb::IMessage { + public sealed partial class ComplexOptionType2 : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ComplexOptionType2()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1972,11 +2037,16 @@ public sealed partial class ComplexOptionType2 : pb::IMessageContainer for nested types declared in the ComplexOptionType2 message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class ComplexOptionType4 : pb::IMessage { + public sealed partial class ComplexOptionType4 : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ComplexOptionType4()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2121,11 +2191,16 @@ public sealed partial class ComplexOptionType4 : pb::IMessage { + public sealed partial class ComplexOptionType3 : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ComplexOptionType3()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2264,11 +2339,16 @@ public sealed partial class ComplexOptionType3 : pb::IMessage /// Note that we try various different ways of naming the same extension. /// - public sealed partial class VariousComplexOptions : pb::IMessage { + public sealed partial class VariousComplexOptions : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new VariousComplexOptions()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2372,11 +2452,16 @@ public sealed partial class VariousComplexOptions : pb::IMessage /// A helper type used to test aggregate option parsing /// - public sealed partial class Aggregate : pb::IMessage { + public sealed partial class Aggregate : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Aggregate()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2554,11 +2639,16 @@ public sealed partial class Aggregate : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { I = input.ReadInt32(); @@ -2581,7 +2671,7 @@ public sealed partial class Aggregate : pb::IMessage { } - public sealed partial class AggregateMessage : pb::IMessage { + public sealed partial class AggregateMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new AggregateMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2694,11 +2784,16 @@ public sealed partial class AggregateMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Fieldname = input.ReadInt32(); @@ -2713,7 +2808,7 @@ public sealed partial class AggregateMessage : pb::IMessage { /// /// Test custom options for nested type. /// - public sealed partial class NestedOptionType : pb::IMessage { + public sealed partial class NestedOptionType : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedOptionType()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2802,11 +2897,16 @@ public sealed partial class NestedOptionType : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } @@ -2821,7 +2921,7 @@ public enum NestedEnum { [pbr::OriginalName("NESTED_ENUM_VALUE")] Value = 1, } - public sealed partial class NestedMessage : pb::IMessage { + public sealed partial class NestedMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2934,11 +3034,16 @@ public sealed partial class NestedMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { NestedField = input.ReadInt32(); diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.cs index d5f8589315e3..1cddcd82cef4 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.cs @@ -59,7 +59,7 @@ public enum ImportEnumForMap { #endregion #region Messages - public sealed partial class ImportMessage : pb::IMessage { + public sealed partial class ImportMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ImportMessage()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -187,11 +187,16 @@ public sealed partial class ImportMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { D = input.ReadInt32(); diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportProto3.cs index 19a1a34634f9..bcd27bf2e1e4 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportProto3.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportProto3.cs @@ -50,7 +50,7 @@ public enum ImportEnum { #endregion #region Messages - public sealed partial class ImportMessage : pb::IMessage { + public sealed partial class ImportMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ImportMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -163,11 +163,16 @@ public sealed partial class ImportMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { D = input.ReadInt32(); diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublic.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublic.cs index 77f212176035..6b35c107d677 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublic.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublic.cs @@ -37,7 +37,7 @@ public static partial class UnittestImportPublicReflection { } #region Messages - public sealed partial class PublicImportMessage : pb::IMessage { + public sealed partial class PublicImportMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new PublicImportMessage()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -165,11 +165,16 @@ public sealed partial class PublicImportMessage : pb::IMessage { + public sealed partial class PublicImportMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new PublicImportMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -151,11 +151,16 @@ public sealed partial class PublicImportMessage : pb::IMessage { + public sealed partial class Foo : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Foo()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -126,11 +126,16 @@ public sealed partial class Foo : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936C.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936C.cs index a8a73f6cb6ec..e86780f70e05 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936C.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936C.cs @@ -39,7 +39,7 @@ public static partial class UnittestIssue6936CReflection { } #region Messages - public sealed partial class Bar : pb::IMessage { + public sealed partial class Bar : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Bar()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -155,11 +155,16 @@ public sealed partial class Bar : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { if (foo_ == null) { diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs index f3f40c6a70cf..68884e196122 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs @@ -88,7 +88,7 @@ public enum DeprecatedEnum { /// Issue 307: when generating doubly-nested types, any references /// should be of the form A.Types.B.Types.C. /// - public sealed partial class Issue307 : pb::IMessage { + public sealed partial class Issue307 : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Issue307()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -177,11 +177,16 @@ public sealed partial class Issue307 : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } @@ -191,7 +196,7 @@ public sealed partial class Issue307 : pb::IMessage { /// Container for nested types declared in the Issue307 message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class NestedOnce : pb::IMessage { + public sealed partial class NestedOnce : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedOnce()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -280,11 +285,16 @@ public sealed partial class NestedOnce : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } @@ -294,7 +304,7 @@ public sealed partial class NestedOnce : pb::IMessage { /// Container for nested types declared in the NestedOnce message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class NestedTwice : pb::IMessage { + public sealed partial class NestedTwice : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedTwice()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -383,11 +393,16 @@ public sealed partial class NestedTwice : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } @@ -405,7 +420,7 @@ public sealed partial class NestedTwice : pb::IMessage { } - public sealed partial class NegativeEnumMessage : pb::IMessage { + public sealed partial class NegativeEnumMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NegativeEnumMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -550,11 +565,16 @@ public sealed partial class NegativeEnumMessage : pb::IMessage { + public sealed partial class DeprecatedChild : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DeprecatedChild()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -665,11 +685,16 @@ public sealed partial class DeprecatedChild : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } @@ -677,7 +702,7 @@ public sealed partial class DeprecatedChild : pb::IMessage { } - public sealed partial class DeprecatedFieldsMessage : pb::IMessage { + public sealed partial class DeprecatedFieldsMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DeprecatedFieldsMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -895,11 +920,16 @@ public sealed partial class DeprecatedFieldsMessage : pb::IMessage /// Issue 45: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=45 /// - public sealed partial class ItemField : pb::IMessage { + public sealed partial class ItemField : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ItemField()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1052,11 +1082,16 @@ public sealed partial class ItemField : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Item = input.ReadInt32(); @@ -1068,7 +1103,7 @@ public sealed partial class ItemField : pb::IMessage { } - public sealed partial class ReservedNames : pb::IMessage { + public sealed partial class ReservedNames : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ReservedNames()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1205,11 +1240,16 @@ public sealed partial class ReservedNames : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Types_ = input.ReadInt32(); @@ -1230,7 +1270,7 @@ public static partial class Types { /// /// Force a nested type called Types /// - public sealed partial class SomeNestedType : pb::IMessage { + public sealed partial class SomeNestedType : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SomeNestedType()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1319,11 +1359,16 @@ public sealed partial class SomeNestedType : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } @@ -1348,7 +1393,7 @@ public sealed partial class SomeNestedType : pb::IMessage { /// Alternatively, consider just adding this to /// unittest_proto3.proto if multiple platforms want it. /// - public sealed partial class TestJsonFieldOrdering : pb::IMessage { + public sealed partial class TestJsonFieldOrdering : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestJsonFieldOrdering()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1643,11 +1688,16 @@ public enum O2OneofCase { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { PlainString = input.ReadString(); @@ -1679,7 +1729,7 @@ public enum O2OneofCase { } - public sealed partial class TestJsonName : pb::IMessage { + public sealed partial class TestJsonName : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestJsonName()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1843,11 +1893,16 @@ public sealed partial class TestJsonName : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Name = input.ReadString(); @@ -1872,7 +1927,7 @@ public sealed partial class TestJsonName : pb::IMessage { /// oneof case, which is itself a message type, the submessages should /// be merged. /// - public sealed partial class OneofMerging : pb::IMessage { + public sealed partial class OneofMerging : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneofMerging()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2043,11 +2098,16 @@ public enum ValueOneofCase { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Text = input.ReadString(); @@ -2070,7 +2130,7 @@ public enum ValueOneofCase { /// Container for nested types declared in the OneofMerging message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class Nested : pb::IMessage { + public sealed partial class Nested : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Nested()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2207,11 +2267,16 @@ public sealed partial class Nested : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { X = input.ReadInt32(); diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs index 3f01e38bb973..5d0ea8672d1a 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs @@ -254,7 +254,7 @@ public enum CommentEnum { /// This proto includes every type of field in both singular and repeated /// forms. /// - public sealed partial class TestAllTypes : pb::IMessage { + public sealed partial class TestAllTypes : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestAllTypes()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1383,11 +1383,16 @@ public enum OneofFieldOneofCase { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { SingleInt32 = input.ReadInt32(); @@ -1491,106 +1496,106 @@ public enum OneofFieldOneofCase { } case 250: case 248: { - repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec); + repeatedInt32_.AddEntriesFrom(ref input, _repeated_repeatedInt32_codec); break; } case 258: case 256: { - repeatedInt64_.AddEntriesFrom(input, _repeated_repeatedInt64_codec); + repeatedInt64_.AddEntriesFrom(ref input, _repeated_repeatedInt64_codec); break; } case 266: case 264: { - repeatedUint32_.AddEntriesFrom(input, _repeated_repeatedUint32_codec); + repeatedUint32_.AddEntriesFrom(ref input, _repeated_repeatedUint32_codec); break; } case 274: case 272: { - repeatedUint64_.AddEntriesFrom(input, _repeated_repeatedUint64_codec); + repeatedUint64_.AddEntriesFrom(ref input, _repeated_repeatedUint64_codec); break; } case 282: case 280: { - repeatedSint32_.AddEntriesFrom(input, _repeated_repeatedSint32_codec); + repeatedSint32_.AddEntriesFrom(ref input, _repeated_repeatedSint32_codec); break; } case 290: case 288: { - repeatedSint64_.AddEntriesFrom(input, _repeated_repeatedSint64_codec); + repeatedSint64_.AddEntriesFrom(ref input, _repeated_repeatedSint64_codec); break; } case 298: case 301: { - repeatedFixed32_.AddEntriesFrom(input, _repeated_repeatedFixed32_codec); + repeatedFixed32_.AddEntriesFrom(ref input, _repeated_repeatedFixed32_codec); break; } case 306: case 305: { - repeatedFixed64_.AddEntriesFrom(input, _repeated_repeatedFixed64_codec); + repeatedFixed64_.AddEntriesFrom(ref input, _repeated_repeatedFixed64_codec); break; } case 314: case 317: { - repeatedSfixed32_.AddEntriesFrom(input, _repeated_repeatedSfixed32_codec); + repeatedSfixed32_.AddEntriesFrom(ref input, _repeated_repeatedSfixed32_codec); break; } case 322: case 321: { - repeatedSfixed64_.AddEntriesFrom(input, _repeated_repeatedSfixed64_codec); + repeatedSfixed64_.AddEntriesFrom(ref input, _repeated_repeatedSfixed64_codec); break; } case 330: case 333: { - repeatedFloat_.AddEntriesFrom(input, _repeated_repeatedFloat_codec); + repeatedFloat_.AddEntriesFrom(ref input, _repeated_repeatedFloat_codec); break; } case 338: case 337: { - repeatedDouble_.AddEntriesFrom(input, _repeated_repeatedDouble_codec); + repeatedDouble_.AddEntriesFrom(ref input, _repeated_repeatedDouble_codec); break; } case 346: case 344: { - repeatedBool_.AddEntriesFrom(input, _repeated_repeatedBool_codec); + repeatedBool_.AddEntriesFrom(ref input, _repeated_repeatedBool_codec); break; } case 354: { - repeatedString_.AddEntriesFrom(input, _repeated_repeatedString_codec); + repeatedString_.AddEntriesFrom(ref input, _repeated_repeatedString_codec); break; } case 362: { - repeatedBytes_.AddEntriesFrom(input, _repeated_repeatedBytes_codec); + repeatedBytes_.AddEntriesFrom(ref input, _repeated_repeatedBytes_codec); break; } case 386: { - repeatedNestedMessage_.AddEntriesFrom(input, _repeated_repeatedNestedMessage_codec); + repeatedNestedMessage_.AddEntriesFrom(ref input, _repeated_repeatedNestedMessage_codec); break; } case 394: { - repeatedForeignMessage_.AddEntriesFrom(input, _repeated_repeatedForeignMessage_codec); + repeatedForeignMessage_.AddEntriesFrom(ref input, _repeated_repeatedForeignMessage_codec); break; } case 402: { - repeatedImportMessage_.AddEntriesFrom(input, _repeated_repeatedImportMessage_codec); + repeatedImportMessage_.AddEntriesFrom(ref input, _repeated_repeatedImportMessage_codec); break; } case 410: case 408: { - repeatedNestedEnum_.AddEntriesFrom(input, _repeated_repeatedNestedEnum_codec); + repeatedNestedEnum_.AddEntriesFrom(ref input, _repeated_repeatedNestedEnum_codec); break; } case 418: case 416: { - repeatedForeignEnum_.AddEntriesFrom(input, _repeated_repeatedForeignEnum_codec); + repeatedForeignEnum_.AddEntriesFrom(ref input, _repeated_repeatedForeignEnum_codec); break; } case 426: case 424: { - repeatedImportEnum_.AddEntriesFrom(input, _repeated_repeatedImportEnum_codec); + repeatedImportEnum_.AddEntriesFrom(ref input, _repeated_repeatedImportEnum_codec); break; } case 434: { - repeatedPublicImportMessage_.AddEntriesFrom(input, _repeated_repeatedPublicImportMessage_codec); + repeatedPublicImportMessage_.AddEntriesFrom(ref input, _repeated_repeatedPublicImportMessage_codec); break; } case 888: { @@ -1633,7 +1638,7 @@ public enum NestedEnum { [pbr::OriginalName("NEG")] Neg = -1, } - public sealed partial class NestedMessage : pb::IMessage { + public sealed partial class NestedMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1751,11 +1756,16 @@ public sealed partial class NestedMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Bb = input.ReadInt32(); @@ -1775,7 +1785,7 @@ public sealed partial class NestedMessage : pb::IMessage { /// /// This proto includes a recursively nested message. /// - public sealed partial class NestedTestAllTypes : pb::IMessage { + public sealed partial class NestedTestAllTypes : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedTestAllTypes()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1934,11 +1944,16 @@ public sealed partial class NestedTestAllTypes : pb::IMessage { + public sealed partial class TestDeprecatedFields : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestDeprecatedFields()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2078,11 +2093,16 @@ public sealed partial class TestDeprecatedFields : pb::IMessage - public sealed partial class ForeignMessage : pb::IMessage { + public sealed partial class ForeignMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ForeignMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2211,11 +2231,16 @@ public sealed partial class ForeignMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { C = input.ReadInt32(); @@ -2227,7 +2252,7 @@ public sealed partial class ForeignMessage : pb::IMessage { } - public sealed partial class TestReservedFields : pb::IMessage { + public sealed partial class TestReservedFields : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestReservedFields()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2316,11 +2341,16 @@ public sealed partial class TestReservedFields : pb::IMessage /// Test that we can use NestedMessage from outside TestAllTypes. /// - public sealed partial class TestForeignNested : pb::IMessage { + public sealed partial class TestForeignNested : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestForeignNested()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2447,11 +2477,16 @@ public sealed partial class TestForeignNested : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { if (foreignNested_ == null) { @@ -2469,7 +2504,7 @@ public sealed partial class TestForeignNested : pb::IMessage /// /// Test that really large tag numbers don't break anything. /// - public sealed partial class TestReallyLargeTagNumber : pb::IMessage { + public sealed partial class TestReallyLargeTagNumber : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestReallyLargeTagNumber()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2610,11 +2645,16 @@ public sealed partial class TestReallyLargeTagNumber : pb::IMessage { + public sealed partial class TestRecursiveMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestRecursiveMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2770,11 +2810,16 @@ public sealed partial class TestRecursiveMessage : pb::IMessage /// Test that mutual recursion works. /// - public sealed partial class TestMutualRecursionA : pb::IMessage { + public sealed partial class TestMutualRecursionA : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMutualRecursionA()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2912,11 +2957,16 @@ public sealed partial class TestMutualRecursionA : pb::IMessage { + public sealed partial class TestMutualRecursionB : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMutualRecursionB()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -3071,11 +3121,16 @@ public sealed partial class TestMutualRecursionB : pb::IMessage { + public sealed partial class TestEnumAllowAlias : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestEnumAllowAlias()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -3207,11 +3262,16 @@ public sealed partial class TestEnumAllowAlias : pb::IMessage - public sealed partial class TestCamelCaseFieldNames : pb::IMessage { + public sealed partial class TestCamelCaseFieldNames : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestCamelCaseFieldNames()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -3479,11 +3539,16 @@ public sealed partial class TestCamelCaseFieldNames : pb::IMessage - public sealed partial class TestFieldOrderings : pb::IMessage { + public sealed partial class TestFieldOrderings : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestFieldOrderings()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -3720,11 +3785,16 @@ public sealed partial class TestFieldOrderings : pb::IMessageContainer for nested types declared in the TestFieldOrderings message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class NestedMessage : pb::IMessage { + public sealed partial class NestedMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -3895,11 +3965,16 @@ public sealed partial class NestedMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Bb = input.ReadInt32(); @@ -3920,7 +3995,7 @@ public sealed partial class NestedMessage : pb::IMessage { } - public sealed partial class SparseEnumMessage : pb::IMessage { + public sealed partial class SparseEnumMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SparseEnumMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -4033,11 +4108,16 @@ public sealed partial class SparseEnumMessage : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { SparseEnum = (global::Google.Protobuf.TestProtos.TestSparseEnum) input.ReadEnum(); @@ -4052,7 +4132,7 @@ public sealed partial class SparseEnumMessage : pb::IMessage /// /// Test String and Bytes: string is for valid UTF-8 strings /// - public sealed partial class OneString : pb::IMessage { + public sealed partial class OneString : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneString()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -4165,11 +4245,16 @@ public sealed partial class OneString : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Data = input.ReadString(); @@ -4181,7 +4266,7 @@ public sealed partial class OneString : pb::IMessage { } - public sealed partial class MoreString : pb::IMessage { + public sealed partial class MoreString : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MoreString()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -4286,14 +4371,19 @@ public sealed partial class MoreString : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { - data_.AddEntriesFrom(input, _repeated_data_codec); + data_.AddEntriesFrom(ref input, _repeated_data_codec); break; } } @@ -4302,7 +4392,7 @@ public sealed partial class MoreString : pb::IMessage { } - public sealed partial class OneBytes : pb::IMessage { + public sealed partial class OneBytes : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneBytes()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -4415,11 +4505,16 @@ public sealed partial class OneBytes : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Data = input.ReadBytes(); @@ -4431,7 +4526,7 @@ public sealed partial class OneBytes : pb::IMessage { } - public sealed partial class MoreBytes : pb::IMessage { + public sealed partial class MoreBytes : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MoreBytes()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -4544,11 +4639,16 @@ public sealed partial class MoreBytes : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Data = input.ReadBytes(); @@ -4563,7 +4663,7 @@ public sealed partial class MoreBytes : pb::IMessage { /// /// Test int32, uint32, int64, uint64, and bool are all compatible /// - public sealed partial class Int32Message : pb::IMessage { + public sealed partial class Int32Message : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Int32Message()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -4676,11 +4776,16 @@ public sealed partial class Int32Message : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Data = input.ReadInt32(); @@ -4692,7 +4797,7 @@ public sealed partial class Int32Message : pb::IMessage { } - public sealed partial class Uint32Message : pb::IMessage { + public sealed partial class Uint32Message : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Uint32Message()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -4805,11 +4910,16 @@ public sealed partial class Uint32Message : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Data = input.ReadUInt32(); @@ -4821,7 +4931,7 @@ public sealed partial class Uint32Message : pb::IMessage { } - public sealed partial class Int64Message : pb::IMessage { + public sealed partial class Int64Message : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Int64Message()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -4934,11 +5044,16 @@ public sealed partial class Int64Message : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Data = input.ReadInt64(); @@ -4950,7 +5065,7 @@ public sealed partial class Int64Message : pb::IMessage { } - public sealed partial class Uint64Message : pb::IMessage { + public sealed partial class Uint64Message : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Uint64Message()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -5063,11 +5178,16 @@ public sealed partial class Uint64Message : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Data = input.ReadUInt64(); @@ -5079,7 +5199,7 @@ public sealed partial class Uint64Message : pb::IMessage { } - public sealed partial class BoolMessage : pb::IMessage { + public sealed partial class BoolMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BoolMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -5192,11 +5312,16 @@ public sealed partial class BoolMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Data = input.ReadBool(); @@ -5211,7 +5336,7 @@ public sealed partial class BoolMessage : pb::IMessage { /// /// Test oneofs. /// - public sealed partial class TestOneof : pb::IMessage { + public sealed partial class TestOneof : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestOneof()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -5409,11 +5534,16 @@ public enum FooOneofCase { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { FooInt = input.ReadInt32(); @@ -5438,7 +5568,7 @@ public enum FooOneofCase { } - public sealed partial class TestPackedTypes : pb::IMessage { + public sealed partial class TestPackedTypes : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestPackedTypes()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -5751,80 +5881,85 @@ public sealed partial class TestPackedTypes : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 722: case 720: { - packedInt32_.AddEntriesFrom(input, _repeated_packedInt32_codec); + packedInt32_.AddEntriesFrom(ref input, _repeated_packedInt32_codec); break; } case 730: case 728: { - packedInt64_.AddEntriesFrom(input, _repeated_packedInt64_codec); + packedInt64_.AddEntriesFrom(ref input, _repeated_packedInt64_codec); break; } case 738: case 736: { - packedUint32_.AddEntriesFrom(input, _repeated_packedUint32_codec); + packedUint32_.AddEntriesFrom(ref input, _repeated_packedUint32_codec); break; } case 746: case 744: { - packedUint64_.AddEntriesFrom(input, _repeated_packedUint64_codec); + packedUint64_.AddEntriesFrom(ref input, _repeated_packedUint64_codec); break; } case 754: case 752: { - packedSint32_.AddEntriesFrom(input, _repeated_packedSint32_codec); + packedSint32_.AddEntriesFrom(ref input, _repeated_packedSint32_codec); break; } case 762: case 760: { - packedSint64_.AddEntriesFrom(input, _repeated_packedSint64_codec); + packedSint64_.AddEntriesFrom(ref input, _repeated_packedSint64_codec); break; } case 770: case 773: { - packedFixed32_.AddEntriesFrom(input, _repeated_packedFixed32_codec); + packedFixed32_.AddEntriesFrom(ref input, _repeated_packedFixed32_codec); break; } case 778: case 777: { - packedFixed64_.AddEntriesFrom(input, _repeated_packedFixed64_codec); + packedFixed64_.AddEntriesFrom(ref input, _repeated_packedFixed64_codec); break; } case 786: case 789: { - packedSfixed32_.AddEntriesFrom(input, _repeated_packedSfixed32_codec); + packedSfixed32_.AddEntriesFrom(ref input, _repeated_packedSfixed32_codec); break; } case 794: case 793: { - packedSfixed64_.AddEntriesFrom(input, _repeated_packedSfixed64_codec); + packedSfixed64_.AddEntriesFrom(ref input, _repeated_packedSfixed64_codec); break; } case 802: case 805: { - packedFloat_.AddEntriesFrom(input, _repeated_packedFloat_codec); + packedFloat_.AddEntriesFrom(ref input, _repeated_packedFloat_codec); break; } case 810: case 809: { - packedDouble_.AddEntriesFrom(input, _repeated_packedDouble_codec); + packedDouble_.AddEntriesFrom(ref input, _repeated_packedDouble_codec); break; } case 818: case 816: { - packedBool_.AddEntriesFrom(input, _repeated_packedBool_codec); + packedBool_.AddEntriesFrom(ref input, _repeated_packedBool_codec); break; } case 826: case 824: { - packedEnum_.AddEntriesFrom(input, _repeated_packedEnum_codec); + packedEnum_.AddEntriesFrom(ref input, _repeated_packedEnum_codec); break; } } @@ -5837,7 +5972,7 @@ public sealed partial class TestPackedTypes : pb::IMessage { /// A message with the same fields as TestPackedTypes, but without packing. Used /// to test packed <-> unpacked wire compatibility. /// - public sealed partial class TestUnpackedTypes : pb::IMessage { + public sealed partial class TestUnpackedTypes : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestUnpackedTypes()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -6150,80 +6285,85 @@ public sealed partial class TestUnpackedTypes : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 722: case 720: { - unpackedInt32_.AddEntriesFrom(input, _repeated_unpackedInt32_codec); + unpackedInt32_.AddEntriesFrom(ref input, _repeated_unpackedInt32_codec); break; } case 730: case 728: { - unpackedInt64_.AddEntriesFrom(input, _repeated_unpackedInt64_codec); + unpackedInt64_.AddEntriesFrom(ref input, _repeated_unpackedInt64_codec); break; } case 738: case 736: { - unpackedUint32_.AddEntriesFrom(input, _repeated_unpackedUint32_codec); + unpackedUint32_.AddEntriesFrom(ref input, _repeated_unpackedUint32_codec); break; } case 746: case 744: { - unpackedUint64_.AddEntriesFrom(input, _repeated_unpackedUint64_codec); + unpackedUint64_.AddEntriesFrom(ref input, _repeated_unpackedUint64_codec); break; } case 754: case 752: { - unpackedSint32_.AddEntriesFrom(input, _repeated_unpackedSint32_codec); + unpackedSint32_.AddEntriesFrom(ref input, _repeated_unpackedSint32_codec); break; } case 762: case 760: { - unpackedSint64_.AddEntriesFrom(input, _repeated_unpackedSint64_codec); + unpackedSint64_.AddEntriesFrom(ref input, _repeated_unpackedSint64_codec); break; } case 770: case 773: { - unpackedFixed32_.AddEntriesFrom(input, _repeated_unpackedFixed32_codec); + unpackedFixed32_.AddEntriesFrom(ref input, _repeated_unpackedFixed32_codec); break; } case 778: case 777: { - unpackedFixed64_.AddEntriesFrom(input, _repeated_unpackedFixed64_codec); + unpackedFixed64_.AddEntriesFrom(ref input, _repeated_unpackedFixed64_codec); break; } case 786: case 789: { - unpackedSfixed32_.AddEntriesFrom(input, _repeated_unpackedSfixed32_codec); + unpackedSfixed32_.AddEntriesFrom(ref input, _repeated_unpackedSfixed32_codec); break; } case 794: case 793: { - unpackedSfixed64_.AddEntriesFrom(input, _repeated_unpackedSfixed64_codec); + unpackedSfixed64_.AddEntriesFrom(ref input, _repeated_unpackedSfixed64_codec); break; } case 802: case 805: { - unpackedFloat_.AddEntriesFrom(input, _repeated_unpackedFloat_codec); + unpackedFloat_.AddEntriesFrom(ref input, _repeated_unpackedFloat_codec); break; } case 810: case 809: { - unpackedDouble_.AddEntriesFrom(input, _repeated_unpackedDouble_codec); + unpackedDouble_.AddEntriesFrom(ref input, _repeated_unpackedDouble_codec); break; } case 818: case 816: { - unpackedBool_.AddEntriesFrom(input, _repeated_unpackedBool_codec); + unpackedBool_.AddEntriesFrom(ref input, _repeated_unpackedBool_codec); break; } case 826: case 824: { - unpackedEnum_.AddEntriesFrom(input, _repeated_unpackedEnum_codec); + unpackedEnum_.AddEntriesFrom(ref input, _repeated_unpackedEnum_codec); break; } } @@ -6232,7 +6372,7 @@ public sealed partial class TestUnpackedTypes : pb::IMessage } - public sealed partial class TestRepeatedScalarDifferentTagSizes : pb::IMessage { + public sealed partial class TestRepeatedScalarDifferentTagSizes : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestRepeatedScalarDifferentTagSizes()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -6431,40 +6571,45 @@ public sealed partial class TestRepeatedScalarDifferentTagSizes : pb::IMessage { + public sealed partial class TestCommentInjectionMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestCommentInjectionMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -6589,11 +6734,16 @@ public sealed partial class TestCommentInjectionMessage : pb::IMessage /// Test that RPC services work. /// - public sealed partial class FooRequest : pb::IMessage { + public sealed partial class FooRequest : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooRequest()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -6697,11 +6847,16 @@ public sealed partial class FooRequest : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } @@ -6709,7 +6864,7 @@ public sealed partial class FooRequest : pb::IMessage { } - public sealed partial class FooResponse : pb::IMessage { + public sealed partial class FooResponse : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooResponse()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -6798,11 +6953,16 @@ public sealed partial class FooResponse : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } @@ -6810,7 +6970,7 @@ public sealed partial class FooResponse : pb::IMessage { } - public sealed partial class FooClientMessage : pb::IMessage { + public sealed partial class FooClientMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooClientMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -6899,11 +7059,16 @@ public sealed partial class FooClientMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } @@ -6911,7 +7076,7 @@ public sealed partial class FooClientMessage : pb::IMessage { } - public sealed partial class FooServerMessage : pb::IMessage { + public sealed partial class FooServerMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FooServerMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -7000,11 +7165,16 @@ public sealed partial class FooServerMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } @@ -7012,7 +7182,7 @@ public sealed partial class FooServerMessage : pb::IMessage { } - public sealed partial class BarRequest : pb::IMessage { + public sealed partial class BarRequest : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BarRequest()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -7101,11 +7271,16 @@ public sealed partial class BarRequest : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } @@ -7113,7 +7288,7 @@ public sealed partial class BarRequest : pb::IMessage { } - public sealed partial class BarResponse : pb::IMessage { + public sealed partial class BarResponse : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BarResponse()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -7202,11 +7377,16 @@ public sealed partial class BarResponse : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } @@ -7214,7 +7394,7 @@ public sealed partial class BarResponse : pb::IMessage { } - public sealed partial class TestEmptyMessage : pb::IMessage { + public sealed partial class TestEmptyMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestEmptyMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -7303,11 +7483,16 @@ public sealed partial class TestEmptyMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } @@ -7318,7 +7503,7 @@ public sealed partial class TestEmptyMessage : pb::IMessage { /// /// This is a leading comment /// - public sealed partial class CommentMessage : pb::IMessage { + public sealed partial class CommentMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CommentMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -7434,11 +7619,16 @@ public sealed partial class CommentMessage : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Text = input.ReadString(); @@ -7465,7 +7655,7 @@ public enum NestedCommentEnum { /// /// Leading nested message comment /// - public sealed partial class NestedCommentMessage : pb::IMessage { + public sealed partial class NestedCommentMessage : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedCommentMessage()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -7581,11 +7771,16 @@ public sealed partial class NestedCommentMessage : pb::IMessage - public sealed partial class TestWellKnownTypes : pb::IMessage { + public sealed partial class TestWellKnownTypes : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestWellKnownTypes()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -784,11 +784,16 @@ public sealed partial class TestWellKnownTypes : pb::IMessage /// A repeated field for each well-known type. /// - public sealed partial class RepeatedWellKnownTypes : pb::IMessage { + public sealed partial class RepeatedWellKnownTypes : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new RepeatedWellKnownTypes()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1312,82 +1317,87 @@ public sealed partial class RepeatedWellKnownTypes : pb::IMessage { + public sealed partial class OneofWellKnownTypes : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneofWellKnownTypes()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2023,11 +2033,16 @@ public enum OneofFieldOneofCase { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { global::Google.Protobuf.WellKnownTypes.Any subBuilder = new global::Google.Protobuf.WellKnownTypes.Any(); @@ -2111,39 +2126,39 @@ public enum OneofFieldOneofCase { break; } case 82: { - DoubleField = _oneof_doubleField_codec.Read(input); + DoubleField = _oneof_doubleField_codec.Read(ref input); break; } case 90: { - FloatField = _oneof_floatField_codec.Read(input); + FloatField = _oneof_floatField_codec.Read(ref input); break; } case 98: { - Int64Field = _oneof_int64Field_codec.Read(input); + Int64Field = _oneof_int64Field_codec.Read(ref input); break; } case 106: { - Uint64Field = _oneof_uint64Field_codec.Read(input); + Uint64Field = _oneof_uint64Field_codec.Read(ref input); break; } case 114: { - Int32Field = _oneof_int32Field_codec.Read(input); + Int32Field = _oneof_int32Field_codec.Read(ref input); break; } case 122: { - Uint32Field = _oneof_uint32Field_codec.Read(input); + Uint32Field = _oneof_uint32Field_codec.Read(ref input); break; } case 130: { - BoolField = _oneof_boolField_codec.Read(input); + BoolField = _oneof_boolField_codec.Read(ref input); break; } case 138: { - StringField = _oneof_stringField_codec.Read(input); + StringField = _oneof_stringField_codec.Read(ref input); break; } case 146: { - BytesField = _oneof_bytesField_codec.Read(input); + BytesField = _oneof_bytesField_codec.Read(ref input); break; } } @@ -2157,7 +2172,7 @@ public enum OneofFieldOneofCase { /// need to worry about the value part of the map being the /// well-known types, as messages can't be map keys. /// - public sealed partial class MapWellKnownTypes : pb::IMessage { + public sealed partial class MapWellKnownTypes : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MapWellKnownTypes()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2534,82 +2549,87 @@ public sealed partial class MapWellKnownTypes : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { - anyField_.AddEntriesFrom(input, _map_anyField_codec); + anyField_.AddEntriesFrom(ref input, _map_anyField_codec); break; } case 18: { - apiField_.AddEntriesFrom(input, _map_apiField_codec); + apiField_.AddEntriesFrom(ref input, _map_apiField_codec); break; } case 26: { - durationField_.AddEntriesFrom(input, _map_durationField_codec); + durationField_.AddEntriesFrom(ref input, _map_durationField_codec); break; } case 34: { - emptyField_.AddEntriesFrom(input, _map_emptyField_codec); + emptyField_.AddEntriesFrom(ref input, _map_emptyField_codec); break; } case 42: { - fieldMaskField_.AddEntriesFrom(input, _map_fieldMaskField_codec); + fieldMaskField_.AddEntriesFrom(ref input, _map_fieldMaskField_codec); break; } case 50: { - sourceContextField_.AddEntriesFrom(input, _map_sourceContextField_codec); + sourceContextField_.AddEntriesFrom(ref input, _map_sourceContextField_codec); break; } case 58: { - structField_.AddEntriesFrom(input, _map_structField_codec); + structField_.AddEntriesFrom(ref input, _map_structField_codec); break; } case 66: { - timestampField_.AddEntriesFrom(input, _map_timestampField_codec); + timestampField_.AddEntriesFrom(ref input, _map_timestampField_codec); break; } case 74: { - typeField_.AddEntriesFrom(input, _map_typeField_codec); + typeField_.AddEntriesFrom(ref input, _map_typeField_codec); break; } case 82: { - doubleField_.AddEntriesFrom(input, _map_doubleField_codec); + doubleField_.AddEntriesFrom(ref input, _map_doubleField_codec); break; } case 90: { - floatField_.AddEntriesFrom(input, _map_floatField_codec); + floatField_.AddEntriesFrom(ref input, _map_floatField_codec); break; } case 98: { - int64Field_.AddEntriesFrom(input, _map_int64Field_codec); + int64Field_.AddEntriesFrom(ref input, _map_int64Field_codec); break; } case 106: { - uint64Field_.AddEntriesFrom(input, _map_uint64Field_codec); + uint64Field_.AddEntriesFrom(ref input, _map_uint64Field_codec); break; } case 114: { - int32Field_.AddEntriesFrom(input, _map_int32Field_codec); + int32Field_.AddEntriesFrom(ref input, _map_int32Field_codec); break; } case 122: { - uint32Field_.AddEntriesFrom(input, _map_uint32Field_codec); + uint32Field_.AddEntriesFrom(ref input, _map_uint32Field_codec); break; } case 130: { - boolField_.AddEntriesFrom(input, _map_boolField_codec); + boolField_.AddEntriesFrom(ref input, _map_boolField_codec); break; } case 138: { - stringField_.AddEntriesFrom(input, _map_stringField_codec); + stringField_.AddEntriesFrom(ref input, _map_stringField_codec); break; } case 146: { - bytesField_.AddEntriesFrom(input, _map_bytesField_codec); + bytesField_.AddEntriesFrom(ref input, _map_bytesField_codec); break; } } diff --git a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs index 5f360ff46eaa..bcc6ace28952 100644 --- a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs +++ b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs @@ -31,6 +31,7 @@ #endregion using System; +using System.Buffers; using System.IO; using Google.Protobuf.TestProtos; using Proto2 = Google.Protobuf.TestProtos.Proto2; @@ -62,11 +63,22 @@ private static void AssertReadVarint(byte[] data, ulong value) { CodedInputStream input = new CodedInputStream(data); Assert.AreEqual((uint) value, input.ReadRawVarint32()); + Assert.IsTrue(input.IsAtEnd); input = new CodedInputStream(data); Assert.AreEqual(value, input.ReadRawVarint64()); Assert.IsTrue(input.IsAtEnd); + AssertReadFromParseContext(new ReadOnlySequence(data), (ref ParseContext ctx) => + { + Assert.AreEqual((uint) value, ctx.ReadUInt32()); + }, true); + + AssertReadFromParseContext(new ReadOnlySequence(data), (ref ParseContext ctx) => + { + Assert.AreEqual(value, ctx.ReadUInt64()); + }, true); + // Try different block sizes. for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2) { @@ -76,6 +88,16 @@ private static void AssertReadVarint(byte[] data, ulong value) input = new CodedInputStream(new SmallBlockInputStream(data, bufferSize)); Assert.AreEqual(value, input.ReadRawVarint64()); Assert.IsTrue(input.IsAtEnd); + + AssertReadFromParseContext(ReadOnlySequenceFactory.CreateWithContent(data, bufferSize), (ref ParseContext ctx) => + { + Assert.AreEqual((uint) value, ctx.ReadUInt32()); + }, true); + + AssertReadFromParseContext(ReadOnlySequenceFactory.CreateWithContent(data, bufferSize), (ref ParseContext ctx) => + { + Assert.AreEqual(value, ctx.ReadUInt64()); + }, true); } // Try reading directly from a MemoryStream. We want to verify that it @@ -104,11 +126,49 @@ private static void AssertReadVarintFailure(InvalidProtocolBufferException expec exception = Assert.Throws(() => input.ReadRawVarint64()); Assert.AreEqual(expected.Message, exception.Message); + AssertReadFromParseContext(new ReadOnlySequence(data), (ref ParseContext ctx) => + { + try + { + ctx.ReadUInt32(); + Assert.Fail(); + } + catch (InvalidProtocolBufferException ex) + { + Assert.AreEqual(expected.Message, ex.Message); + } + }, false); + + AssertReadFromParseContext(new ReadOnlySequence(data), (ref ParseContext ctx) => + { + try + { + ctx.ReadUInt64(); + Assert.Fail(); + } + catch (InvalidProtocolBufferException ex) + { + Assert.AreEqual(expected.Message, ex.Message); + } + }, false); + // Make sure we get the same error when reading directly from a Stream. exception = Assert.Throws(() => CodedInputStream.ReadRawVarint32(new MemoryStream(data))); Assert.AreEqual(expected.Message, exception.Message); } + private delegate void ParseContextAssertAction(ref ParseContext ctx); + + private static void AssertReadFromParseContext(ReadOnlySequence input, ParseContextAssertAction assertAction, bool assertIsAtEnd) + { + ParseContext.Initialize(input, out ParseContext parseCtx); + assertAction(ref parseCtx); + if (assertIsAtEnd) + { + Assert.IsTrue(SegmentedBufferHelper.IsAtEnd(ref parseCtx.buffer, ref parseCtx.state)); + } + } + [Test] public void ReadVarint() { @@ -157,6 +217,11 @@ private static void AssertReadLittleEndian32(byte[] data, uint value) Assert.AreEqual(value, input.ReadRawLittleEndian32()); Assert.IsTrue(input.IsAtEnd); + AssertReadFromParseContext(new ReadOnlySequence(data), (ref ParseContext ctx) => + { + Assert.AreEqual(value, ctx.ReadFixed32()); + }, true); + // Try different block sizes. for (int blockSize = 1; blockSize <= 16; blockSize *= 2) { @@ -164,6 +229,11 @@ private static void AssertReadLittleEndian32(byte[] data, uint value) new SmallBlockInputStream(data, blockSize)); Assert.AreEqual(value, input.ReadRawLittleEndian32()); Assert.IsTrue(input.IsAtEnd); + + AssertReadFromParseContext(ReadOnlySequenceFactory.CreateWithContent(data, blockSize), (ref ParseContext ctx) => + { + Assert.AreEqual(value, ctx.ReadFixed32()); + }, true); } } @@ -177,6 +247,11 @@ private static void AssertReadLittleEndian64(byte[] data, ulong value) Assert.AreEqual(value, input.ReadRawLittleEndian64()); Assert.IsTrue(input.IsAtEnd); + AssertReadFromParseContext(new ReadOnlySequence(data), (ref ParseContext ctx) => + { + Assert.AreEqual(value, ctx.ReadFixed64()); + }, true); + // Try different block sizes. for (int blockSize = 1; blockSize <= 16; blockSize *= 2) { @@ -184,6 +259,11 @@ private static void AssertReadLittleEndian64(byte[] data, ulong value) new SmallBlockInputStream(data, blockSize)); Assert.AreEqual(value, input.ReadRawLittleEndian64()); Assert.IsTrue(input.IsAtEnd); + + AssertReadFromParseContext(ReadOnlySequenceFactory.CreateWithContent(data, blockSize), (ref ParseContext ctx) => + { + Assert.AreEqual(value, ctx.ReadFixed64()); + }, true); } } @@ -202,29 +282,29 @@ public void ReadLittleEndian() [Test] public void DecodeZigZag32() { - Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(0)); - Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(1)); - Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(2)); - Assert.AreEqual(-2, CodedInputStream.DecodeZigZag32(3)); - Assert.AreEqual(0x3FFFFFFF, CodedInputStream.DecodeZigZag32(0x7FFFFFFE)); - Assert.AreEqual(unchecked((int) 0xC0000000), CodedInputStream.DecodeZigZag32(0x7FFFFFFF)); - Assert.AreEqual(0x7FFFFFFF, CodedInputStream.DecodeZigZag32(0xFFFFFFFE)); - Assert.AreEqual(unchecked((int) 0x80000000), CodedInputStream.DecodeZigZag32(0xFFFFFFFF)); + Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag32(0)); + Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag32(1)); + Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag32(2)); + Assert.AreEqual(-2, ParsingPrimitives.DecodeZigZag32(3)); + Assert.AreEqual(0x3FFFFFFF, ParsingPrimitives.DecodeZigZag32(0x7FFFFFFE)); + Assert.AreEqual(unchecked((int) 0xC0000000), ParsingPrimitives.DecodeZigZag32(0x7FFFFFFF)); + Assert.AreEqual(0x7FFFFFFF, ParsingPrimitives.DecodeZigZag32(0xFFFFFFFE)); + Assert.AreEqual(unchecked((int) 0x80000000), ParsingPrimitives.DecodeZigZag32(0xFFFFFFFF)); } [Test] public void DecodeZigZag64() { - Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(0)); - Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(1)); - Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(2)); - Assert.AreEqual(-2, CodedInputStream.DecodeZigZag64(3)); - Assert.AreEqual(0x000000003FFFFFFFL, CodedInputStream.DecodeZigZag64(0x000000007FFFFFFEL)); - Assert.AreEqual(unchecked((long) 0xFFFFFFFFC0000000L), CodedInputStream.DecodeZigZag64(0x000000007FFFFFFFL)); - Assert.AreEqual(0x000000007FFFFFFFL, CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFEL)); - Assert.AreEqual(unchecked((long) 0xFFFFFFFF80000000L), CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFFL)); - Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL)); - Assert.AreEqual(unchecked((long) 0x8000000000000000L), CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL)); + Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag64(0)); + Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag64(1)); + Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag64(2)); + Assert.AreEqual(-2, ParsingPrimitives.DecodeZigZag64(3)); + Assert.AreEqual(0x000000003FFFFFFFL, ParsingPrimitives.DecodeZigZag64(0x000000007FFFFFFEL)); + Assert.AreEqual(unchecked((long) 0xFFFFFFFFC0000000L), ParsingPrimitives.DecodeZigZag64(0x000000007FFFFFFFL)); + Assert.AreEqual(0x000000007FFFFFFFL, ParsingPrimitives.DecodeZigZag64(0x00000000FFFFFFFEL)); + Assert.AreEqual(unchecked((long) 0xFFFFFFFF80000000L), ParsingPrimitives.DecodeZigZag64(0x00000000FFFFFFFFL)); + Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, ParsingPrimitives.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL)); + Assert.AreEqual(unchecked((long) 0x8000000000000000L), ParsingPrimitives.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL)); } [Test] @@ -339,64 +419,64 @@ public void MaliciousRecursion() Assert.Throws(() => TestRecursiveMessage.Parser.ParseFrom(input)); } - private static byte[] MakeMaliciousRecursionUnknownFieldsPayload(int recursionDepth) - { - // generate recursively nested groups that will be parsed as unknown fields - int unknownFieldNumber = 14; // an unused field number - MemoryStream ms = new MemoryStream(); - CodedOutputStream output = new CodedOutputStream(ms); - for (int i = 0; i < recursionDepth; i++) - { - output.WriteTag(WireFormat.MakeTag(unknownFieldNumber, WireFormat.WireType.StartGroup)); - } - for (int i = 0; i < recursionDepth; i++) - { - output.WriteTag(WireFormat.MakeTag(unknownFieldNumber, WireFormat.WireType.EndGroup)); - } - output.Flush(); - return ms.ToArray(); + private static byte[] MakeMaliciousRecursionUnknownFieldsPayload(int recursionDepth) + { + // generate recursively nested groups that will be parsed as unknown fields + int unknownFieldNumber = 14; // an unused field number + MemoryStream ms = new MemoryStream(); + CodedOutputStream output = new CodedOutputStream(ms); + for (int i = 0; i < recursionDepth; i++) + { + output.WriteTag(WireFormat.MakeTag(unknownFieldNumber, WireFormat.WireType.StartGroup)); + } + for (int i = 0; i < recursionDepth; i++) + { + output.WriteTag(WireFormat.MakeTag(unknownFieldNumber, WireFormat.WireType.EndGroup)); + } + output.Flush(); + return ms.ToArray(); } [Test] public void MaliciousRecursion_UnknownFields() { - byte[] payloadAtRecursiveLimit = MakeMaliciousRecursionUnknownFieldsPayload(CodedInputStream.DefaultRecursionLimit); - byte[] payloadBeyondRecursiveLimit = MakeMaliciousRecursionUnknownFieldsPayload(CodedInputStream.DefaultRecursionLimit + 1); - - Assert.DoesNotThrow(() => TestRecursiveMessage.Parser.ParseFrom(payloadAtRecursiveLimit)); + byte[] payloadAtRecursiveLimit = MakeMaliciousRecursionUnknownFieldsPayload(CodedInputStream.DefaultRecursionLimit); + byte[] payloadBeyondRecursiveLimit = MakeMaliciousRecursionUnknownFieldsPayload(CodedInputStream.DefaultRecursionLimit + 1); + + Assert.DoesNotThrow(() => TestRecursiveMessage.Parser.ParseFrom(payloadAtRecursiveLimit)); Assert.Throws(() => TestRecursiveMessage.Parser.ParseFrom(payloadBeyondRecursiveLimit)); } [Test] public void ReadGroup_WrongEndGroupTag() - { - int groupFieldNumber = Proto2.TestAllTypes.OptionalGroupFieldNumber; - - // write Proto2.TestAllTypes with "optional_group" set, but use wrong EndGroup closing tag - MemoryStream ms = new MemoryStream(); - CodedOutputStream output = new CodedOutputStream(ms); - output.WriteTag(WireFormat.MakeTag(groupFieldNumber, WireFormat.WireType.StartGroup)); - output.WriteGroup(new Proto2.TestAllTypes.Types.OptionalGroup { A = 12345 }); - // end group with different field number - output.WriteTag(WireFormat.MakeTag(groupFieldNumber + 1, WireFormat.WireType.EndGroup)); - output.Flush(); - var payload = ms.ToArray(); - - Assert.Throws(() => Proto2.TestAllTypes.Parser.ParseFrom(payload)); + { + int groupFieldNumber = Proto2.TestAllTypes.OptionalGroupFieldNumber; + + // write Proto2.TestAllTypes with "optional_group" set, but use wrong EndGroup closing tag + MemoryStream ms = new MemoryStream(); + CodedOutputStream output = new CodedOutputStream(ms); + output.WriteTag(WireFormat.MakeTag(groupFieldNumber, WireFormat.WireType.StartGroup)); + output.WriteGroup(new Proto2.TestAllTypes.Types.OptionalGroup { A = 12345 }); + // end group with different field number + output.WriteTag(WireFormat.MakeTag(groupFieldNumber + 1, WireFormat.WireType.EndGroup)); + output.Flush(); + var payload = ms.ToArray(); + + Assert.Throws(() => Proto2.TestAllTypes.Parser.ParseFrom(payload)); } [Test] public void ReadGroup_UnknownFields_WrongEndGroupTag() - { - MemoryStream ms = new MemoryStream(); - CodedOutputStream output = new CodedOutputStream(ms); - output.WriteTag(WireFormat.MakeTag(14, WireFormat.WireType.StartGroup)); - // end group with different field number - output.WriteTag(WireFormat.MakeTag(15, WireFormat.WireType.EndGroup)); - output.Flush(); - var payload = ms.ToArray(); - - Assert.Throws(() => TestRecursiveMessage.Parser.ParseFrom(payload)); + { + MemoryStream ms = new MemoryStream(); + CodedOutputStream output = new CodedOutputStream(ms); + output.WriteTag(WireFormat.MakeTag(14, WireFormat.WireType.StartGroup)); + // end group with different field number + output.WriteTag(WireFormat.MakeTag(15, WireFormat.WireType.EndGroup)); + output.Flush(); + var payload = ms.ToArray(); + + Assert.Throws(() => TestRecursiveMessage.Parser.ParseFrom(payload)); } [Test] diff --git a/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs index 98cabd55adc4..b9ff51521f59 100644 --- a/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs +++ b/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs @@ -247,26 +247,26 @@ public void RoundTripZigZag32() { // Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1) // were chosen semi-randomly via keyboard bashing. - Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(0))); - Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(1))); - Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-1))); - Assert.AreEqual(14927, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(14927))); - Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-3612))); + 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))); } [Test] public void RoundTripZigZag64() { - Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(0))); - Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(1))); - Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-1))); - Assert.AreEqual(14927, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(14927))); - Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-3612))); + 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(856912304801416L, - CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(856912304801416L))); + ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(856912304801416L))); Assert.AreEqual(-75123905439571256L, - CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-75123905439571256L))); + ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-75123905439571256L))); } [Test] diff --git a/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs b/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs index f64ebac4ef9f..d8cdee0f0f75 100644 --- a/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs +++ b/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs @@ -31,6 +31,7 @@ #endregion using System; +using System.IO; using System.Collections.Generic; using Google.Protobuf.TestProtos; using NUnit.Framework; @@ -583,6 +584,33 @@ public void NaNKeysComparedBitwise() Assert.False(map.TryGetValue(SampleNaNs.PayloadFlipped, out ignored)); } + [Test] + public void AddEntriesFrom_CodedInputStream() + { + // map will have string key and string value + var keyTag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited); + var valueTag = WireFormat.MakeTag(2, WireFormat.WireType.LengthDelimited); + + var memoryStream = new MemoryStream(); + var output = new CodedOutputStream(memoryStream); + output.WriteLength(20); // total of keyTag + key + valueTag + value + output.WriteTag(keyTag); + output.WriteString("the_key"); + output.WriteTag(valueTag); + output.WriteString("the_value"); + output.Flush(); + + var field = new MapField(); + var mapCodec = new MapField.Codec(FieldCodec.ForString(keyTag, ""), FieldCodec.ForString(valueTag, ""), 10); + var input = new CodedInputStream(memoryStream.ToArray()); + + // test the legacy overload of AddEntriesFrom that takes a CodedInputStream + field.AddEntriesFrom(input, mapCodec); + CollectionAssert.AreEquivalent(new[] { "the_key" }, field.Keys); + CollectionAssert.AreEquivalent(new[] { "the_value" }, field.Values); + Assert.IsTrue(input.IsAtEnd); + } + #if !NET35 [Test] public void IDictionaryKeys_Equals_IReadOnlyDictionaryKeys() diff --git a/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs b/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs index 33dc50430d07..934b780ccc2d 100644 --- a/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs +++ b/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs @@ -1,4 +1,4 @@ -using Google.Protobuf.TestProtos.Proto2; +using Google.Protobuf.TestProtos.Proto2; using NUnit.Framework; using static Google.Protobuf.TestProtos.Proto2.UnittestExtensions; @@ -34,12 +34,14 @@ public void TestMergeCodedInput() message.SetExtension(OptionalBoolExtension, true); var serialized = message.ToByteArray(); - var other = TestAllExtensions.Parser - .WithExtensionRegistry(new ExtensionRegistry() { OptionalBoolExtension }) - .ParseFrom(serialized); - - Assert.AreEqual(message, other); - Assert.AreEqual(message.CalculateSize(), other.CalculateSize()); + MessageParsingHelpers.AssertReadingMessage( + TestAllExtensions.Parser.WithExtensionRegistry(new ExtensionRegistry() { OptionalBoolExtension }), + serialized, + other => + { + Assert.AreEqual(message, other); + Assert.AreEqual(message.CalculateSize(), other.CalculateSize()); + }); } [Test] @@ -59,6 +61,22 @@ public void TestMergeMessage() Assert.AreEqual(message.CalculateSize(), other.CalculateSize()); } + [Test] + public void TryMergeFieldFrom_CodedInputStream() + { + var message = new TestAllExtensions(); + message.SetExtension(OptionalStringExtension, "abcd"); + + var input = new CodedInputStream(message.ToByteArray()); + input.ExtensionRegistry = new ExtensionRegistry() { OptionalStringExtension }; + input.ReadTag(); // TryMergeFieldFrom expects that a tag was just read and will inspect the LastTag value + + ExtensionSet extensionSet = null; + // test the legacy overload of TryMergeFieldFrom that takes a CodedInputStream + Assert.IsTrue(ExtensionSet.TryMergeFieldFrom(ref extensionSet, input)); + Assert.AreEqual("abcd", ExtensionSet.Get(ref extensionSet, OptionalStringExtension)); + } + [Test] public void TestEquals() { diff --git a/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs b/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs index b20ecccde2d0..5be0cecd99bd 100644 --- a/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs +++ b/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs @@ -128,7 +128,7 @@ public void TestRoundTripRaw() codedOutput.Flush(); stream.Position = 0; var codedInput = new CodedInputStream(stream); - Assert.AreEqual(sampleValue, codec.ValueReader(codedInput)); + Assert.AreEqual(sampleValue, codec.Read(codedInput)); Assert.IsTrue(codedInput.IsAtEnd); } @@ -158,7 +158,7 @@ public void TestDefaultValue() { // WriteTagAndValue ignores default values var stream = new MemoryStream(); - CodedOutputStream codedOutput; + CodedOutputStream codedOutput; #if !NET35 codedOutput = new CodedOutputStream(stream); codec.WriteTagAndValue(codedOutput, codec.DefaultValue); @@ -181,7 +181,7 @@ public void TestDefaultValue() Assert.AreEqual(stream.Position, codec.ValueSizeCalculator(codec.DefaultValue)); stream.Position = 0; var codedInput = new CodedInputStream(stream); - Assert.AreEqual(codec.DefaultValue, codec.ValueReader(codedInput)); + Assert.AreEqual(codec.DefaultValue, codec.Read(codedInput)); } } diff --git a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs index 718c3edcb80e..5f90c94cce6d 100644 --- a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs +++ b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs @@ -269,8 +269,8 @@ public void RequiredFields() [Test] public void RequiredFieldsNoThrow() { - Assert.DoesNotThrow(() => TestRequired.Parser.ParseFrom(new byte[0])); - Assert.DoesNotThrow(() => (TestRequired.Parser as MessageParser).ParseFrom(new byte[0])); + Assert.DoesNotThrow(() => MessageParsingHelpers.AssertReadingMessage(TestRequired.Parser, new byte[0], m => { })); + Assert.DoesNotThrow(() => MessageParsingHelpers.AssertReadingMessage(TestRequired.Parser as MessageParser, new byte[0], m => { })); } [Test] @@ -344,9 +344,7 @@ public void RoundTrip_Groups() } }; - byte[] bytes = message.ToByteArray(); - TestAllTypes parsed = Proto2.TestAllTypes.Parser.ParseFrom(bytes); - Assert.AreEqual(message, parsed); + MessageParsingHelpers.AssertRoundtrip(Proto2.TestAllTypes.Parser, message); } [Test] @@ -361,9 +359,9 @@ public void RoundTrip_ExtensionGroups() new RepeatedGroup_extension { A = 30 } }); - byte[] bytes = message.ToByteArray(); - TestAllExtensions extendable_parsed = TestAllExtensions.Parser.WithExtensionRegistry(new ExtensionRegistry() { UnittestExtensions.OptionalGroupExtension, UnittestExtensions.RepeatedGroupExtension }).ParseFrom(bytes); - Assert.AreEqual(message, extendable_parsed); + MessageParsingHelpers.AssertRoundtrip( + TestAllExtensions.Parser.WithExtensionRegistry(new ExtensionRegistry() { UnittestExtensions.OptionalGroupExtension, UnittestExtensions.RepeatedGroupExtension }), + message); } [Test] @@ -372,9 +370,9 @@ public void RoundTrip_NestedExtensionGroup() var message = new TestGroupExtension(); message.SetExtension(TestNestedExtension.Extensions.OptionalGroupExtension, new TestNestedExtension.Types.OptionalGroup_extension { A = 10 }); - byte[] bytes = message.ToByteArray(); - TestGroupExtension extendable_parsed = TestGroupExtension.Parser.WithExtensionRegistry(new ExtensionRegistry() { TestNestedExtension.Extensions.OptionalGroupExtension }).ParseFrom(bytes); - Assert.AreEqual(message, extendable_parsed); + 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 103df7dd2fef..3499e6617d93 100644 --- a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs +++ b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs @@ -131,8 +131,8 @@ public void RoundTrip_Empty() // Without setting any values, there's nothing to write. byte[] bytes = message.ToByteArray(); Assert.AreEqual(0, bytes.Length); - TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes); - Assert.AreEqual(message, parsed); + + MessageParsingHelpers.AssertRoundtrip(TestAllTypes.Parser, message); } [Test] @@ -165,8 +165,8 @@ public void RoundTrip_SingleValues() }; byte[] bytes = message.ToByteArray(); - TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes); - Assert.AreEqual(message, parsed); + + MessageParsingHelpers.AssertRoundtrip(TestAllTypes.Parser, message); } [Test] @@ -199,8 +199,8 @@ public void RoundTrip_RepeatedValues() }; byte[] bytes = message.ToByteArray(); - TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes); - Assert.AreEqual(message, parsed); + + MessageParsingHelpers.AssertRoundtrip(TestAllTypes.Parser, message); } // Note that not every map within map_unittest_proto3 is used. They all go through very @@ -231,8 +231,8 @@ public void RoundTrip_Maps() }; byte[] bytes = message.ToByteArray(); - TestMap parsed = TestMap.Parser.ParseFrom(bytes); - Assert.AreEqual(message, parsed); + + MessageParsingHelpers.AssertRoundtrip(TestMap.Parser, message); } [Test] @@ -246,9 +246,14 @@ public void MapWithEmptyEntry() byte[] bytes = message.ToByteArray(); Assert.AreEqual(2, bytes.Length); // Tag for field entry (1 byte), length of entry (0; 1 byte) - var parsed = TestMap.Parser.ParseFrom(bytes); - Assert.AreEqual(1, parsed.MapInt32Bytes.Count); - Assert.AreEqual(ByteString.Empty, parsed.MapInt32Bytes[0]); + MessageParsingHelpers.AssertReadingMessage( + TestMap.Parser, + bytes, + parsed=> + { + Assert.AreEqual(1, parsed.MapInt32Bytes.Count); + Assert.AreEqual(ByteString.Empty, parsed.MapInt32Bytes[0]); + }); } [Test] @@ -265,8 +270,13 @@ public void MapWithOnlyValue() output.WriteMessage(nestedMessage); output.Flush(); - var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray()); - Assert.AreEqual(nestedMessage, parsed.MapInt32ForeignMessage[0]); + MessageParsingHelpers.AssertReadingMessage( + TestMap.Parser, + memoryStream.ToArray(), + parsed => + { + Assert.AreEqual(nestedMessage, parsed.MapInt32ForeignMessage[0]); + }); } [Test] @@ -282,8 +292,13 @@ public void MapWithOnlyKey_PrimitiveValue() output.WriteInt32(key); output.Flush(); - var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray()); - Assert.AreEqual(0.0, parsed.MapInt32Double[key]); + MessageParsingHelpers.AssertReadingMessage( + TestMap.Parser, + memoryStream.ToArray(), + parsed => + { + Assert.AreEqual(0.0, parsed.MapInt32Double[key]); + }); } [Test] @@ -299,8 +314,13 @@ public void MapWithOnlyKey_MessageValue() output.WriteInt32(key); output.Flush(); - var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray()); - Assert.AreEqual(new ForeignMessage(), parsed.MapInt32ForeignMessage[key]); + MessageParsingHelpers.AssertReadingMessage( + TestMap.Parser, + memoryStream.ToArray(), + parsed => + { + Assert.AreEqual(new ForeignMessage(), parsed.MapInt32ForeignMessage[key]); + }); } [Test] @@ -327,8 +347,13 @@ public void MapIgnoresExtraFieldsWithinEntryMessages() output.WriteInt32(extra); output.Flush(); - var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray()); - Assert.AreEqual(value, parsed.MapInt32Int32[key]); + MessageParsingHelpers.AssertReadingMessage( + TestMap.Parser, + memoryStream.ToArray(), + parsed => + { + Assert.AreEqual(value, parsed.MapInt32Int32[key]); + }); } [Test] @@ -351,8 +376,13 @@ public void MapFieldOrderIsIrrelevant() output.WriteInt32(key); output.Flush(); - var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray()); - Assert.AreEqual(value, parsed.MapInt32Int32[key]); + MessageParsingHelpers.AssertReadingMessage( + TestMap.Parser, + memoryStream.ToArray(), + parsed => + { + Assert.AreEqual(value, parsed.MapInt32Int32[key]); + }); } [Test] @@ -397,13 +427,19 @@ public void MapNonContiguousEntries() output.WriteInt32(value3); output.Flush(); - var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray()); - var expected = new TestMap - { - MapInt32Int32 = { { key1, value1 }, { key3, value3 } }, - MapStringString = { { key2, value2 } } - }; - Assert.AreEqual(expected, parsed); + + MessageParsingHelpers.AssertReadingMessage( + TestMap.Parser, + memoryStream.ToArray(), + parsed => + { + var expected = new TestMap + { + MapInt32Int32 = { { key1, value1 }, { key3, value3 } }, + MapStringString = { { key2, value2 } } + }; + Assert.AreEqual(expected, parsed); + }); } [Test] @@ -433,8 +469,13 @@ public void DuplicateKeys_LastEntryWins() output.WriteInt32(value2); output.Flush(); - var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray()); - Assert.AreEqual(value2, parsed.MapInt32Int32[key]); + MessageParsingHelpers.AssertReadingMessage( + TestMap.Parser, + memoryStream.ToArray(), + parsed => + { + Assert.AreEqual(value2, parsed.MapInt32Int32[key]); + }); } [Test] @@ -619,9 +660,10 @@ public void OneofSerialization_NonDefaultValue() var bytes = message.ToByteArray(); Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - no string! - var message2 = TestAllTypes.Parser.ParseFrom(bytes); - Assert.AreEqual(message, message2); - Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase); + MessageParsingHelpers.AssertRoundtrip(TestAllTypes.Parser, message, parsedMessage => + { + Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, parsedMessage.OneofFieldCase); + }); } [Test] @@ -633,9 +675,10 @@ public void OneofSerialization_DefaultValue() var bytes = message.ToByteArray(); Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - it's still serialized - var message2 = TestAllTypes.Parser.ParseFrom(bytes); - Assert.AreEqual(message, message2); - Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase); + MessageParsingHelpers.AssertRoundtrip(TestAllTypes.Parser, message, parsedMessage => + { + Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, parsedMessage.OneofFieldCase); + }); } [Test] @@ -651,10 +694,14 @@ public void DiscardUnknownFields_RealDataStillRead() message.WriteTo(output); output.Flush(); - stream.Position = 0; - var parsed = TestAllTypes.Parser.ParseFrom(stream); - // TODO(jieluo): Add test back when DiscardUnknownFields API is supported. - // Assert.AreEqual(message, parsed); + MessageParsingHelpers.AssertReadingMessage( + TestAllTypes.Parser, + stream.ToArray(), + parsed => + { + // TODO(jieluo): Add test back when DiscardUnknownFields API is supported. + // Assert.AreEqual(message, parsed); + }); } [Test] @@ -663,8 +710,15 @@ public void DiscardUnknownFields_AllTypes() // Simple way of ensuring we can skip all kinds of fields. var data = SampleMessages.CreateFullTestAllTypes().ToByteArray(); var empty = Empty.Parser.ParseFrom(data); - // TODO(jieluo): Add test back when DiscardUnknownFields API is supported. - // Assert.AreNotEqual(new Empty(), empty); + + MessageParsingHelpers.AssertReadingMessage( + Empty.Parser, + data, + parsed => + { + // TODO(jieluo): Add test back when DiscardUnknownFields API is supported. + // Assert.AreNotEqual(new Empty(), empty); + }); } // This was originally seen as a conformance test failure. @@ -674,7 +728,7 @@ public void TruncatedMessageFieldThrows() // 130, 3 is the message tag // 1 is the data length - but there's no data. var data = new byte[] { 130, 3, 1 }; - Assert.Throws(() => TestAllTypes.Parser.ParseFrom(data)); + MessageParsingHelpers.AssertReadingMessageThrows(TestAllTypes.Parser, data); } /// @@ -695,7 +749,7 @@ public void ExtraEndGroupThrows() output.Flush(); stream.Position = 0; - Assert.Throws(() => TestAllTypes.Parser.ParseFrom(stream)); + MessageParsingHelpers.AssertReadingMessageThrows(TestAllTypes.Parser, stream.ToArray()); } [Test] diff --git a/csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs b/csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs new file mode 100644 index 000000000000..9c9846c8f577 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs @@ -0,0 +1,233 @@ +#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 Google.Protobuf; +using Google.Protobuf.Reflection; +using System.Buffers; +using pb = global::Google.Protobuf; +using pbr = global::Google.Protobuf.Reflection; +using NUnit.Framework; + + +namespace Google.Protobuf +{ + public class LegacyGeneratedCodeTest + { + [Test] + public void IntermixingOfNewAndLegacyGeneratedCodeWorksWithCodedInputStream() + { + var message = new ParseContextEnabledMessageB + { + 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. + var codedInput = new CodedInputStream(data); + 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 LegacyGeneratedCodeThrowsWithReadOnlySequence() + { + var message = new ParseContextEnabledMessageB + { + A = new LegacyGeneratedCodeMessageA + { + Bb = new ParseContextEnabledMessageB { OptionalInt32 = 12345 } + }, + OptionalInt32 = 6789 + }; + var data = message.ToByteArray(); + + // if parsing started using ReadOnlySequence and we don't have a CodedInputStream + // instance at hand, we cannot fall back to the legacy MergeFrom(CodedInputStream) + // method and parsing will fail. As a consequence, one can only use parsing + // from ReadOnlySequence if all the messages in the parsing tree have their generated + // 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); + }); + 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); + } + + // 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 { + private pb::UnknownFieldSet _unknownFields; + + pbr::MessageDescriptor pb::IMessage.Descriptor => throw new System.NotImplementedException(); + + /// Field number for the "bb" field. + public const int BbFieldNumber = 1; + private ParseContextEnabledMessageB bb_; + public ParseContextEnabledMessageB Bb { + get { return bb_; } + set { + bb_ = value; + } + } + + public void WriteTo(pb::CodedOutputStream output) { + if (bb_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Bb); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + public int CalculateSize() { + int size = 0; + if (bb_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Bb); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (bb_ == null) { + Bb = new ParseContextEnabledMessageB(); + } + input.ReadMessage(Bb); + break; + } + } + } + } + } + + // hand-modified version of a generated message that does provide + // the new InternalMergeFrom(ref ParseContext) method. + private sealed partial class ParseContextEnabledMessageB : pb::IBufferMessage { + private pb::UnknownFieldSet _unknownFields; + + pbr::MessageDescriptor pb::IMessage.Descriptor => throw new System.NotImplementedException(); + + /// Field number for the "a" field. + public const int AFieldNumber = 1; + private LegacyGeneratedCodeMessageA a_; + public LegacyGeneratedCodeMessageA A { + get { return a_; } + set { + a_ = value; + } + } + + /// Field number for the "optional_int32" field. + public const int OptionalInt32FieldNumber = 2; + private int optionalInt32_; + public int OptionalInt32 { + get { return optionalInt32_; } + set { + optionalInt32_ = value; + } + } + + public void WriteTo(pb::CodedOutputStream output) { + if (a_ != null) { + output.WriteRawTag(10); + output.WriteMessage(A); + } + if (OptionalInt32 != 0) { + output.WriteRawTag(16); + output.WriteInt32(OptionalInt32); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + public int CalculateSize() { + int size = 0; + if (a_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(A); + } + if (OptionalInt32 != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(OptionalInt32); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + 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: { + if (a_ == null) { + A = new LegacyGeneratedCodeMessageA(); + } + input.ReadMessage(A); + break; + } + case 16: { + OptionalInt32 = input.ReadInt32(); + break; + } + } + } + } + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs b/csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs new file mode 100644 index 000000000000..ec5f13abc354 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs @@ -0,0 +1,100 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2015 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 NUnit.Framework; +using System; +using System.Buffers; + +namespace Google.Protobuf +{ + public static class MessageParsingHelpers + { + public static void AssertReadingMessage(MessageParser parser, byte[] bytes, Action assert) where T : IMessage + { + var parsedStream = parser.ParseFrom(bytes); + + // Load content as single segment + var parsedBuffer = parser.ParseFrom(new ReadOnlySequence(bytes)); + assert(parsedBuffer); + + // Load content as multiple segments + parsedBuffer = parser.ParseFrom(ReadOnlySequenceFactory.CreateWithContent(bytes)); + assert(parsedBuffer); + + assert(parsedStream); + } + + public static void AssertReadingMessage(MessageParser parser, byte[] bytes, Action assert) + { + var parsedStream = parser.ParseFrom(bytes); + + // Load content as single segment + var parsedBuffer = parser.ParseFrom(new ReadOnlySequence(bytes)); + assert(parsedBuffer); + + // Load content as multiple segments + parsedBuffer = parser.ParseFrom(ReadOnlySequenceFactory.CreateWithContent(bytes)); + assert(parsedBuffer); + + assert(parsedStream); + } + + public static void AssertReadingMessageThrows(MessageParser parser, byte[] bytes) + where TMessage : IMessage + where TException : Exception + { + Assert.Throws(() => parser.ParseFrom(bytes)); + + Assert.Throws(() => parser.ParseFrom(new ReadOnlySequence(bytes))); + } + + public static void AssertRoundtrip(MessageParser parser, T message, Action additionalAssert = null) where T : IMessage + { + var bytes = message.ToByteArray(); + + // Load content as single segment + var parsedBuffer = parser.ParseFrom(new ReadOnlySequence(bytes)); + Assert.AreEqual(message, parsedBuffer); + additionalAssert?.Invoke(parsedBuffer); + + // Load content as multiple segments + parsedBuffer = parser.ParseFrom(ReadOnlySequenceFactory.CreateWithContent(bytes)); + Assert.AreEqual(message, parsedBuffer); + additionalAssert?.Invoke(parsedBuffer); + + var parsedStream = parser.ParseFrom(bytes); + + Assert.AreEqual(message, parsedStream); + additionalAssert?.Invoke(parsedStream); + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs b/csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs new file mode 100644 index 000000000000..d2050d37ca05 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs @@ -0,0 +1,128 @@ +#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.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Google.Protobuf +{ + internal static class ReadOnlySequenceFactory + { + public static ReadOnlySequence CreateWithContent(byte[] data, int segmentSize = 1) + { + var segments = new List(); + + segments.Add(new byte[0]); + var currentIndex = 0; + while (currentIndex < data.Length) + { + var segment = new List(); + for (; currentIndex < Math.Min(currentIndex + segmentSize, data.Length); currentIndex++) + { + segment.Add(data[currentIndex]); + } + segments.Add(segment.ToArray()); + segments.Add(new byte[0]); + } + + return CreateSegments(segments.ToArray()); + } + + /// + /// Originally from corefx, and has been contributed to Protobuf + /// https://github.com/dotnet/corefx/blob/e99ec129cfd594d53f4390bf97d1d736cff6f860/src/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceFactory.byte.cs + /// + private static ReadOnlySequence CreateSegments(params byte[][] inputs) + { + if (inputs == null || inputs.Length == 0) + { + throw new InvalidOperationException(); + } + + int i = 0; + + BufferSegment last = null; + BufferSegment first = null; + + do + { + byte[] s = inputs[i]; + int length = s.Length; + int dataOffset = length; + var chars = new byte[length * 2]; + + for (int j = 0; j < length; j++) + { + chars[dataOffset + j] = s[j]; + } + + // Create a segment that has offset relative to the OwnedMemory and OwnedMemory itself has offset relative to array + var memory = new Memory(chars).Slice(length, length); + + if (first == null) + { + first = new BufferSegment(memory); + last = first; + } + else + { + last = last.Append(memory); + } + i++; + } while (i < inputs.Length); + + return new ReadOnlySequence(first, 0, last, last.Memory.Length); + } + + private class BufferSegment : ReadOnlySequenceSegment + { + public BufferSegment(Memory memory) + { + Memory = memory; + } + + public BufferSegment Append(Memory memory) + { + var segment = new BufferSegment(memory) + { + RunningIndex = RunningIndex + Memory.Length + }; + Next = segment; + return segment; + } + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf.Test/UnknownFieldSetTest.cs b/csharp/src/Google.Protobuf.Test/UnknownFieldSetTest.cs index 886937d70620..15debc1b6c8e 100644 --- a/csharp/src/Google.Protobuf.Test/UnknownFieldSetTest.cs +++ b/csharp/src/Google.Protobuf.Test/UnknownFieldSetTest.cs @@ -161,10 +161,10 @@ public void TestDiscardUnknownFields(IMessage message) MessageParser discardingParser2 = retainingParser2.WithDiscardUnknownFields(true); // Test parse from byte[] - assertFull(retainingParser1.ParseFrom(data)); - assertFull(retainingParser2.ParseFrom(data)); - assertEmpty(discardingParser1.ParseFrom(data)); - assertEmpty(discardingParser2.ParseFrom(data)); + MessageParsingHelpers.AssertReadingMessage(retainingParser1, data, m => assertFull(m)); + MessageParsingHelpers.AssertReadingMessage(retainingParser2, data, m => assertFull(m)); + MessageParsingHelpers.AssertReadingMessage(discardingParser1, data, m => assertEmpty(m)); + MessageParsingHelpers.AssertReadingMessage(discardingParser2, data, m => assertEmpty(m)); // Test parse from byte[] with offset assertFull(retainingParser1.ParseFrom(data, 0, data.Length)); diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs index 4a425f79aa84..47ff2a18ed45 100644 --- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs +++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs @@ -71,18 +71,18 @@ public void NonDefaultSingleValues() Uint64Field = 4 }; - var bytes = message.ToByteArray(); - var parsed = TestWellKnownTypes.Parser.ParseFrom(bytes); - - Assert.AreEqual("x", parsed.StringField); - Assert.AreEqual(ByteString.CopyFrom(1, 2, 3), parsed.BytesField); - Assert.AreEqual(true, parsed.BoolField); - Assert.AreEqual(12.5f, parsed.FloatField); - Assert.AreEqual(12.25d, parsed.DoubleField); - Assert.AreEqual(1, parsed.Int32Field); - Assert.AreEqual(2L, parsed.Int64Field); - Assert.AreEqual(3U, parsed.Uint32Field); - Assert.AreEqual(4UL, parsed.Uint64Field); + MessageParsingHelpers.AssertRoundtrip(TestWellKnownTypes.Parser, message, parsed => + { + Assert.AreEqual("x", parsed.StringField); + Assert.AreEqual(ByteString.CopyFrom(1, 2, 3), parsed.BytesField); + Assert.AreEqual(true, parsed.BoolField); + Assert.AreEqual(12.5f, parsed.FloatField); + Assert.AreEqual(12.25d, parsed.DoubleField); + Assert.AreEqual(1, parsed.Int32Field); + Assert.AreEqual(2L, parsed.Int64Field); + Assert.AreEqual(3U, parsed.Uint32Field); + Assert.AreEqual(4UL, parsed.Uint64Field); + }); } [Test] @@ -101,18 +101,18 @@ public void NonNullDefaultIsPreservedThroughSerialization() Uint64Field = 0 }; - var bytes = message.ToByteArray(); - var parsed = TestWellKnownTypes.Parser.ParseFrom(bytes); - - Assert.AreEqual("", parsed.StringField); - Assert.AreEqual(ByteString.Empty, parsed.BytesField); - Assert.AreEqual(false, parsed.BoolField); - Assert.AreEqual(0f, parsed.FloatField); - Assert.AreEqual(0d, parsed.DoubleField); - Assert.AreEqual(0, parsed.Int32Field); - Assert.AreEqual(0L, parsed.Int64Field); - Assert.AreEqual(0U, parsed.Uint32Field); - Assert.AreEqual(0UL, parsed.Uint64Field); + MessageParsingHelpers.AssertRoundtrip(TestWellKnownTypes.Parser, message, parsed => + { + Assert.AreEqual("", parsed.StringField); + Assert.AreEqual(ByteString.Empty, parsed.BytesField); + Assert.AreEqual(false, parsed.BoolField); + Assert.AreEqual(0f, parsed.FloatField); + Assert.AreEqual(0d, parsed.DoubleField); + Assert.AreEqual(0, parsed.Int32Field); + Assert.AreEqual(0L, parsed.Int64Field); + Assert.AreEqual(0U, parsed.Uint32Field); + Assert.AreEqual(0UL, parsed.Uint64Field); + }); } [Test] @@ -140,12 +140,11 @@ public void RepeatedWrappersSerializeDeserialize() Uint32Field = { uint.MaxValue, uint.MinValue, 0U }, Uint64Field = { ulong.MaxValue, ulong.MinValue, 0UL }, }; - var bytes = message.ToByteArray(); - var parsed = RepeatedWellKnownTypes.Parser.ParseFrom(bytes); - Assert.AreEqual(message, parsed); // Just to test a single value for sanity... Assert.AreEqual("Second", message.StringField[1]); + + MessageParsingHelpers.AssertRoundtrip(RepeatedWellKnownTypes.Parser, message); } [Test] @@ -194,12 +193,10 @@ public void MapWrappersSerializeDeserialize() Uint64Field = { { 18, ulong.MaxValue }, { 19, ulong.MinValue }, { 20, 0UL } }, }; - var bytes = message.ToByteArray(); - var parsed = MapWellKnownTypes.Parser.ParseFrom(bytes); - - Assert.AreEqual(message, parsed); // Just to test a single value for sanity... Assert.AreEqual("Second", message.StringField[12]); + + MessageParsingHelpers.AssertRoundtrip(MapWellKnownTypes.Parser, message); } [Test] @@ -288,10 +285,10 @@ public void Oneof() private void AssertOneofRoundTrip(OneofWellKnownTypes message) { // Normal roundtrip, but explicitly checking the case... - var bytes = message.ToByteArray(); - var parsed = OneofWellKnownTypes.Parser.ParseFrom(bytes); - Assert.AreEqual(message, parsed); - Assert.AreEqual(message.OneofFieldCase, parsed.OneofFieldCase); + MessageParsingHelpers.AssertRoundtrip(OneofWellKnownTypes.Parser, message, parsed => + { + Assert.AreEqual(message.OneofFieldCase, parsed.OneofFieldCase); + }); } [Test] @@ -406,8 +403,10 @@ public void UnknownFieldInWrapperInt32FastPath() Assert.AreEqual(8, stream.Length); // tag (1 byte) + length (1 byte) + message (6 bytes) stream.Position = 0; - var message = TestWellKnownTypes.Parser.ParseFrom(stream); - Assert.AreEqual(65536, message.Int32Field); + MessageParsingHelpers.AssertReadingMessage( + TestWellKnownTypes.Parser, + stream.ToArray(), + message => Assert.AreEqual(65536, message.Int32Field)); } [Test] @@ -431,8 +430,10 @@ public void UnknownFieldInWrapperInt32SlowPath() Assert.Less(stream.Length, 8); // tag (1 byte) + length (1 byte) + message stream.Position = 0; - var message = TestWellKnownTypes.Parser.ParseFrom(stream); - Assert.AreEqual(6, message.Int32Field); + MessageParsingHelpers.AssertReadingMessage( + TestWellKnownTypes.Parser, + stream.ToArray(), + message => Assert.AreEqual(6, message.Int32Field)); } [Test] @@ -456,8 +457,10 @@ public void UnknownFieldInWrapperInt64FastPath() Assert.AreEqual(13, stream.Length); // tag (1 byte) + length (1 byte) + message (11 bytes) stream.Position = 0; - var message = TestWellKnownTypes.Parser.ParseFrom(stream); - Assert.AreEqual(0xfffffffffffffL, message.Int64Field); + MessageParsingHelpers.AssertReadingMessage( + TestWellKnownTypes.Parser, + stream.ToArray(), + message => Assert.AreEqual(0xfffffffffffffL, message.Int64Field)); } [Test] @@ -481,8 +484,10 @@ public void UnknownFieldInWrapperInt64SlowPath() Assert.Less(stream.Length, 12); // tag (1 byte) + length (1 byte) + message stream.Position = 0; - var message = TestWellKnownTypes.Parser.ParseFrom(stream); - Assert.AreEqual(6L, message.Int64Field); + MessageParsingHelpers.AssertReadingMessage( + TestWellKnownTypes.Parser, + stream.ToArray(), + message => Assert.AreEqual(6L, message.Int64Field)); } [Test] diff --git a/csharp/src/Google.Protobuf/ByteString.cs b/csharp/src/Google.Protobuf/ByteString.cs index 3eb00e5bb5c7..8e7d03fea010 100644 --- a/csharp/src/Google.Protobuf/ByteString.cs +++ b/csharp/src/Google.Protobuf/ByteString.cs @@ -160,7 +160,7 @@ public static ByteString FromStream(Stream stream) int capacity = stream.CanSeek ? checked((int) (stream.Length - stream.Position)) : 0; var memoryStream = new MemoryStream(capacity); stream.CopyTo(memoryStream); -#if NETSTANDARD1_0 || NETSTANDARD2_0 +#if NETSTANDARD1_1 || NETSTANDARD2_0 byte[] bytes = memoryStream.ToArray(); #else // Avoid an extra copy if we can. @@ -186,7 +186,7 @@ public async static Task FromStreamAsync(Stream stream, Cancellation // We have to specify the buffer size here, as there's no overload accepting the cancellation token // alone. But it's documented to use 81920 by default if not specified. await stream.CopyToAsync(memoryStream, 81920, cancellationToken); -#if NETSTANDARD1_0 || NETSTANDARD2_0 +#if NETSTANDARD1_1 || NETSTANDARD2_0 byte[] bytes = memoryStream.ToArray(); #else // Avoid an extra copy if we can. diff --git a/csharp/src/Google.Protobuf/CodedInputStream.cs b/csharp/src/Google.Protobuf/CodedInputStream.cs index 9976f5823480..4050cbec8ce9 100644 --- a/csharp/src/Google.Protobuf/CodedInputStream.cs +++ b/csharp/src/Google.Protobuf/CodedInputStream.cs @@ -34,6 +34,9 @@ using System; using System.Collections.Generic; using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; namespace Google.Protobuf { @@ -51,6 +54,7 @@ namespace Google.Protobuf /// and to serialize such fields. /// /// + [SecuritySafeCritical] public sealed class CodedInputStream : IDisposable { /// @@ -64,17 +68,6 @@ public sealed class CodedInputStream : IDisposable /// private readonly byte[] buffer; - /// - /// The index of the buffer at which we need to refill from the stream (if there is one). - /// - private int bufferSize; - - private int bufferSizeAfterLimit = 0; - /// - /// The position within the current buffer (i.e. the next byte to read) - /// - private int bufferPos = 0; - /// /// The stream to read further input from, or null if the byte array buffer was provided /// directly on construction, with no further data available. @@ -82,38 +75,15 @@ public sealed class CodedInputStream : IDisposable private readonly Stream input; /// - /// The last tag we read. 0 indicates we've read to the end of the stream - /// (or haven't read anything yet). + /// The parser state is kept separately so that other parse implementations can reuse the same + /// parsing primitives. /// - private uint lastTag = 0; - - /// - /// The next tag, used to store the value read by PeekTag. - /// - private uint nextTag = 0; - private bool hasNextTag = false; + private ParserInternalState state; internal const int DefaultRecursionLimit = 100; internal const int DefaultSizeLimit = Int32.MaxValue; internal const int BufferSize = 4096; - /// - /// The total number of bytes read before the current buffer. The - /// total bytes read up to the current position can be computed as - /// totalBytesRetired + bufferPos. - /// - private int totalBytesRetired = 0; - - /// - /// The absolute position of the end of the current message. - /// - private int currentLimit = int.MaxValue; - - private int recursionDepth = 0; - - private readonly int recursionLimit; - private readonly int sizeLimit; - #region Construction // Note that the checks are performed such that we don't end up checking obviously-valid things // like non-null references for arrays we've just created. @@ -170,11 +140,14 @@ internal CodedInputStream(Stream input, byte[] buffer, int bufferPos, int buffer { this.input = input; this.buffer = buffer; - this.bufferPos = bufferPos; - this.bufferSize = bufferSize; - this.sizeLimit = DefaultSizeLimit; - this.recursionLimit = DefaultRecursionLimit; + this.state.bufferPos = bufferPos; + this.state.bufferSize = bufferSize; + this.state.sizeLimit = DefaultSizeLimit; + this.state.recursionLimit = DefaultRecursionLimit; + SegmentedBufferHelper.Initialize(this, out this.state.segmentedBufferHelper); this.leaveOpen = leaveOpen; + + this.state.currentLimit = int.MaxValue; } /// @@ -196,8 +169,8 @@ internal CodedInputStream(Stream input, byte[] buffer, int bufferPos, int buffer { throw new ArgumentOutOfRangeException("recursionLimit!", "Recursion limit must be positive"); } - this.sizeLimit = sizeLimit; - this.recursionLimit = recursionLimit; + this.state.sizeLimit = sizeLimit; + this.state.recursionLimit = recursionLimit; } #endregion @@ -230,9 +203,9 @@ public long Position { if (input != null) { - return input.Position - ((bufferSize + bufferSizeAfterLimit) - bufferPos); + return input.Position - ((state.bufferSize + state.bufferSizeAfterLimit) - state.bufferPos); } - return bufferPos; + return state.bufferPos; } } @@ -240,7 +213,7 @@ public long Position /// Returns the last tag read, or 0 if no tags have been read or we've read beyond /// the end of the stream. /// - internal uint LastTag { get { return lastTag; } } + internal uint LastTag { get { return state.lastTag; } } /// /// Returns the size limit for this stream. @@ -253,7 +226,7 @@ public long Position /// /// The size limit. /// - public int SizeLimit { get { return sizeLimit; } } + public int SizeLimit { get { return state.sizeLimit; } } /// /// Returns the recursion limit for this stream. This limit is applied whilst reading messages, @@ -265,17 +238,31 @@ public long Position /// /// The recursion limit for this stream. /// - public int RecursionLimit { get { return recursionLimit; } } + public int RecursionLimit { get { return state.recursionLimit; } } /// /// Internal-only property; when set to true, unknown fields will be discarded while parsing. /// - internal bool DiscardUnknownFields { get; set; } + internal bool DiscardUnknownFields + { + get { return state.DiscardUnknownFields; } + set { state.DiscardUnknownFields = value; } + } /// /// Internal-only property; provides extension identifiers to compatible messages while parsing. /// - internal ExtensionRegistry ExtensionRegistry { get; set; } + internal ExtensionRegistry ExtensionRegistry + { + get { return state.ExtensionRegistry; } + set { state.ExtensionRegistry = value; } + } + + internal byte[] InternalBuffer => buffer; + + internal Stream InternalInputStream => input; + + internal ref ParserInternalState InternalState => ref state; /// /// Disposes of this instance, potentially closing any underlying stream. @@ -302,17 +289,7 @@ public void Dispose() /// tag read was not the one specified internal void CheckReadEndOfStreamTag() { - if (lastTag != 0) - { - throw InvalidProtocolBufferException.MoreDataAvailable(); - } - } - - internal void CheckLastTagWas(uint expectedTag) - { - if (lastTag != expectedTag) { - throw InvalidProtocolBufferException.InvalidEndTag(); - } + ParsingPrimitivesMessages.CheckReadEndOfStreamTag(ref state); } #endregion @@ -325,16 +302,8 @@ internal void CheckLastTagWas(uint expectedTag) /// public uint PeekTag() { - if (hasNextTag) - { - return nextTag; - } - - uint savedLast = lastTag; - nextTag = ReadTag(); - hasNextTag = true; - lastTag = savedLast; // Undo the side effect of ReadTag - return nextTag; + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.PeekTag(ref span, ref state); } /// @@ -348,54 +317,8 @@ public uint PeekTag() /// The next field tag, or 0 for end of stream. (0 is never a valid tag.) public uint ReadTag() { - if (hasNextTag) - { - lastTag = nextTag; - hasNextTag = false; - return lastTag; - } - - // Optimize for the incredibly common case of having at least two bytes left in the buffer, - // and those two bytes being enough to get the tag. This will be true for fields up to 4095. - if (bufferPos + 2 <= bufferSize) - { - int tmp = buffer[bufferPos++]; - if (tmp < 128) - { - lastTag = (uint)tmp; - } - else - { - int result = tmp & 0x7f; - if ((tmp = buffer[bufferPos++]) < 128) - { - result |= tmp << 7; - lastTag = (uint) result; - } - else - { - // Nope, rewind and go the potentially slow route. - bufferPos -= 2; - lastTag = ReadRawVarint32(); - } - } - } - else - { - if (IsAtEnd) - { - lastTag = 0; - return 0; - } - - lastTag = ReadRawVarint32(); - } - if (WireFormat.GetTagFieldNumber(lastTag) == 0) - { - // If we actually read a tag with a field of 0, that's not a valid tag. - throw InvalidProtocolBufferException.InvalidTag(); - } - return lastTag; + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ParseTag(ref span, ref state); } /// @@ -413,32 +336,8 @@ public uint ReadTag() /// The last read operation read to the end of the logical stream public void SkipLastField() { - if (lastTag == 0) - { - throw new InvalidOperationException("SkipLastField cannot be called at the end of a stream"); - } - switch (WireFormat.GetTagWireType(lastTag)) - { - case WireFormat.WireType.StartGroup: - SkipGroup(lastTag); - break; - case WireFormat.WireType.EndGroup: - throw new InvalidProtocolBufferException( - "SkipLastField called on an end-group tag, indicating that the corresponding start-group was missing"); - case WireFormat.WireType.Fixed32: - ReadFixed32(); - break; - case WireFormat.WireType.Fixed64: - ReadFixed64(); - break; - case WireFormat.WireType.LengthDelimited: - var length = ReadLength(); - SkipRawBytes(length); - break; - case WireFormat.WireType.Varint: - ReadRawVarint32(); - break; - } + var span = new ReadOnlySpan(buffer); + ParsingPrimitivesMessages.SkipLastField(ref span, ref state); } /// @@ -446,37 +345,8 @@ public void SkipLastField() /// internal void SkipGroup(uint startGroupTag) { - // Note: Currently we expect this to be the way that groups are read. We could put the recursion - // depth changes into the ReadTag method instead, potentially... - recursionDepth++; - if (recursionDepth >= recursionLimit) - { - throw InvalidProtocolBufferException.RecursionLimitExceeded(); - } - uint tag; - while (true) - { - tag = ReadTag(); - if (tag == 0) - { - throw InvalidProtocolBufferException.TruncatedMessage(); - } - // Can't call SkipLastField for this case- that would throw. - if (WireFormat.GetTagWireType(tag) == WireFormat.WireType.EndGroup) - { - break; - } - // This recursion will allow us to handle nested groups. - SkipLastField(); - } - int startField = WireFormat.GetTagFieldNumber(startGroupTag); - int endField = WireFormat.GetTagFieldNumber(tag); - if (startField != endField) - { - throw new InvalidProtocolBufferException( - $"Mismatched end-group tag. Started with field {startField}; ended with field {endField}"); - } - recursionDepth--; + var span = new ReadOnlySpan(buffer); + ParsingPrimitivesMessages.SkipGroup(ref span, ref state, startGroupTag); } /// @@ -484,33 +354,8 @@ internal void SkipGroup(uint startGroupTag) /// public double ReadDouble() { - if (bufferPos + 8 <= bufferSize) - { - if (BitConverter.IsLittleEndian) - { - var result = BitConverter.ToDouble(buffer, bufferPos); - bufferPos += 8; - return result; - } - else - { - var bytes = new byte[8]; - bytes[0] = buffer[bufferPos + 7]; - bytes[1] = buffer[bufferPos + 6]; - bytes[2] = buffer[bufferPos + 5]; - bytes[3] = buffer[bufferPos + 4]; - bytes[4] = buffer[bufferPos + 3]; - bytes[5] = buffer[bufferPos + 2]; - bytes[6] = buffer[bufferPos + 1]; - bytes[7] = buffer[bufferPos]; - bufferPos += 8; - return BitConverter.ToDouble(bytes, 0); - } - } - else - { - return BitConverter.Int64BitsToDouble((long)ReadRawLittleEndian64()); - } + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ParseDouble(ref span, ref state); } /// @@ -518,21 +363,8 @@ public double ReadDouble() /// public float ReadFloat() { - if (BitConverter.IsLittleEndian && 4 <= bufferSize - bufferPos) - { - float ret = BitConverter.ToSingle(buffer, bufferPos); - bufferPos += 4; - return ret; - } - else - { - byte[] rawBytes = ReadRawBytes(4); - if (!BitConverter.IsLittleEndian) - { - ByteArray.Reverse(rawBytes); - } - return BitConverter.ToSingle(rawBytes, 0); - } + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ParseFloat(ref span, ref state); } /// @@ -588,22 +420,8 @@ public bool ReadBool() /// public string ReadString() { - int length = ReadLength(); - // No need to read any data for an empty string. - if (length == 0) - { - return ""; - } - if (length <= bufferSize - bufferPos && length > 0) - { - // Fast path: We already have the bytes in a contiguous buffer, so - // just copy directly from it. - String result = CodedOutputStream.Utf8Encoding.GetString(buffer, bufferPos, length); - bufferPos += length; - return result; - } - // Slow path: Build a byte array first then copy it. - return CodedOutputStream.Utf8Encoding.GetString(ReadRawBytes(length), 0, length); + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ReadString(ref span, ref state); } /// @@ -611,22 +429,22 @@ public string ReadString() /// public void ReadMessage(IMessage builder) { - int length = ReadLength(); - if (recursionDepth >= recursionLimit) + // TODO(jtattermusch): if the message doesn't implement IBufferMessage (and thus does not provide the InternalMergeFrom method), + // what we're doing here works fine, but could be more efficient. + // What happends is that we first initialize a ParseContext from the current coded input stream only to parse the length of the message, at which point + // we will need to switch back again to CodedInputStream-based parsing (which involves copying and storing the state) to be able to + // invoke the legacy MergeFrom(CodedInputStream) method. + // For now, this inefficiency is fine, considering this is only a backward-compatibility scenario (and regenerating the code fixes it). + var span = new ReadOnlySpan(buffer); + ParseContext.Initialize(ref span, ref state, out ParseContext ctx); + try { - throw InvalidProtocolBufferException.RecursionLimitExceeded(); + ParsingPrimitivesMessages.ReadMessage(ref ctx, builder); } - int oldLimit = PushLimit(length); - ++recursionDepth; - builder.MergeFrom(this); - CheckReadEndOfStreamTag(); - // Check that we've read exactly as much data as expected. - if (!ReachedLimit) + finally { - throw InvalidProtocolBufferException.TruncatedMessage(); + ctx.CopyStateTo(this); } - --recursionDepth; - PopLimit(oldLimit); } /// @@ -634,33 +452,15 @@ public void ReadMessage(IMessage builder) /// public void ReadGroup(IMessage builder) { - if (recursionDepth >= recursionLimit) + ParseContext.Initialize(this, out ParseContext ctx); + try { - throw InvalidProtocolBufferException.RecursionLimitExceeded(); + ParsingPrimitivesMessages.ReadGroup(ref ctx, builder); } - ++recursionDepth; - - uint tag = lastTag; - int fieldNumber = WireFormat.GetTagFieldNumber(tag); - - builder.MergeFrom(this); - CheckLastTagWas(WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup)); - --recursionDepth; - } - - /// - /// Reads an embedded group unknown field from the stream. - /// - internal void ReadGroup(int fieldNumber, UnknownFieldSet set) - { - if (recursionDepth >= recursionLimit) + finally { - throw InvalidProtocolBufferException.RecursionLimitExceeded(); + ctx.CopyStateTo(this); } - ++recursionDepth; - set.MergeGroupFrom(this); - CheckLastTagWas(WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup)); - --recursionDepth; } /// @@ -668,20 +468,8 @@ internal void ReadGroup(int fieldNumber, UnknownFieldSet set) /// public ByteString ReadBytes() { - int length = ReadLength(); - if (length <= bufferSize - bufferPos && length > 0) - { - // Fast path: We already have the bytes in a contiguous buffer, so - // just copy directly from it. - ByteString result = ByteString.CopyFrom(buffer, bufferPos, length); - bufferPos += length; - return result; - } - else - { - // Slow path: Build a byte array and attach it to a new ByteString. - return ByteString.AttachBytes(ReadRawBytes(length)); - } + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ReadBytes(ref span, ref state); } /// @@ -722,7 +510,7 @@ public long ReadSFixed64() /// public int ReadSInt32() { - return DecodeZigZag32(ReadRawVarint32()); + return ParsingPrimitives.DecodeZigZag32(ReadRawVarint32()); } /// @@ -730,7 +518,7 @@ public int ReadSInt32() /// public long ReadSInt64() { - return DecodeZigZag64(ReadRawVarint64()); + return ParsingPrimitives.DecodeZigZag64(ReadRawVarint64()); } /// @@ -742,7 +530,8 @@ public long ReadSInt64() /// public int ReadLength() { - return (int) ReadRawVarint32(); + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ParseLength(ref span, ref state); } /// @@ -752,323 +541,14 @@ public int ReadLength() /// public bool MaybeConsumeTag(uint tag) { - if (PeekTag() == tag) - { - hasNextTag = false; - return true; - } - return false; - } - - internal static float? ReadFloatWrapperLittleEndian(CodedInputStream input) - { - // length:1 + tag:1 + value:4 = 6 bytes - if (input.bufferPos + 6 <= input.bufferSize) - { - // The entire wrapper message is already contained in `buffer`. - int length = input.buffer[input.bufferPos]; - if (length == 0) - { - input.bufferPos++; - return 0F; - } - // tag:1 + value:4 = length of 5 bytes - // field=1, type=32-bit = tag of 13 - if (length != 5 || input.buffer[input.bufferPos + 1] != 13) - { - return ReadFloatWrapperSlow(input); - } - var result = BitConverter.ToSingle(input.buffer, input.bufferPos + 2); - input.bufferPos += 6; - return result; - } - else - { - return ReadFloatWrapperSlow(input); - } - } - - internal static float? ReadFloatWrapperSlow(CodedInputStream input) - { - int length = input.ReadLength(); - if (length == 0) - { - return 0F; - } - int finalBufferPos = input.totalBytesRetired + input.bufferPos + length; - float result = 0F; - do - { - // field=1, type=32-bit = tag of 13 - if (input.ReadTag() == 13) - { - result = input.ReadFloat(); - } - else - { - input.SkipLastField(); - } - } - while (input.totalBytesRetired + input.bufferPos < finalBufferPos); - return result; - } - - internal static double? ReadDoubleWrapperLittleEndian(CodedInputStream input) - { - // length:1 + tag:1 + value:8 = 10 bytes - if (input.bufferPos + 10 <= input.bufferSize) - { - // The entire wrapper message is already contained in `buffer`. - int length = input.buffer[input.bufferPos]; - if (length == 0) - { - input.bufferPos++; - return 0D; - } - // tag:1 + value:8 = length of 9 bytes - // field=1, type=64-bit = tag of 9 - if (length != 9 || input.buffer[input.bufferPos + 1] != 9) - { - return ReadDoubleWrapperSlow(input); - } - var result = BitConverter.ToDouble(input.buffer, input.bufferPos + 2); - input.bufferPos += 10; - return result; - } - else - { - return ReadDoubleWrapperSlow(input); - } - } - - internal static double? ReadDoubleWrapperSlow(CodedInputStream input) - { - int length = input.ReadLength(); - if (length == 0) - { - return 0D; - } - int finalBufferPos = input.totalBytesRetired + input.bufferPos + length; - double result = 0D; - do - { - // field=1, type=64-bit = tag of 9 - if (input.ReadTag() == 9) - { - result = input.ReadDouble(); - } - else - { - input.SkipLastField(); - } - } - while (input.totalBytesRetired + input.bufferPos < finalBufferPos); - return result; - } - - internal static bool? ReadBoolWrapper(CodedInputStream input) - { - return ReadUInt64Wrapper(input) != 0; - } - - internal static uint? ReadUInt32Wrapper(CodedInputStream input) - { - // length:1 + tag:1 + value:5(varint32-max) = 7 bytes - if (input.bufferPos + 7 <= input.bufferSize) - { - // The entire wrapper message is already contained in `buffer`. - int pos0 = input.bufferPos; - int length = input.buffer[input.bufferPos++]; - if (length == 0) - { - return 0; - } - // Length will always fit in a single byte. - if (length >= 128) - { - input.bufferPos = pos0; - return ReadUInt32WrapperSlow(input); - } - int finalBufferPos = input.bufferPos + length; - // field=1, type=varint = tag of 8 - if (input.buffer[input.bufferPos++] != 8) - { - input.bufferPos = pos0; - return ReadUInt32WrapperSlow(input); - } - var result = input.ReadUInt32(); - // Verify this message only contained a single field. - if (input.bufferPos != finalBufferPos) - { - input.bufferPos = pos0; - return ReadUInt32WrapperSlow(input); - } - return result; - } - else - { - return ReadUInt32WrapperSlow(input); - } - } - - private static uint? ReadUInt32WrapperSlow(CodedInputStream input) - { - int length = input.ReadLength(); - if (length == 0) - { - return 0; - } - int finalBufferPos = input.totalBytesRetired + input.bufferPos + length; - uint result = 0; - do - { - // field=1, type=varint = tag of 8 - if (input.ReadTag() == 8) - { - result = input.ReadUInt32(); - } - else - { - input.SkipLastField(); - } - } - while (input.totalBytesRetired + input.bufferPos < finalBufferPos); - return result; - } - - internal static int? ReadInt32Wrapper(CodedInputStream input) - { - return (int?)ReadUInt32Wrapper(input); - } - - internal static ulong? ReadUInt64Wrapper(CodedInputStream input) - { - // field=1, type=varint = tag of 8 - const int expectedTag = 8; - // length:1 + tag:1 + value:10(varint64-max) = 12 bytes - if (input.bufferPos + 12 <= input.bufferSize) - { - // The entire wrapper message is already contained in `buffer`. - int pos0 = input.bufferPos; - int length = input.buffer[input.bufferPos++]; - if (length == 0) - { - return 0L; - } - // Length will always fit in a single byte. - if (length >= 128) - { - input.bufferPos = pos0; - return ReadUInt64WrapperSlow(input); - } - int finalBufferPos = input.bufferPos + length; - if (input.buffer[input.bufferPos++] != expectedTag) - { - input.bufferPos = pos0; - return ReadUInt64WrapperSlow(input); - } - var result = input.ReadUInt64(); - // Verify this message only contained a single field. - if (input.bufferPos != finalBufferPos) - { - input.bufferPos = pos0; - return ReadUInt64WrapperSlow(input); - } - return result; - } - else - { - return ReadUInt64WrapperSlow(input); - } - } - - internal static ulong? ReadUInt64WrapperSlow(CodedInputStream input) - { - // field=1, type=varint = tag of 8 - const int expectedTag = 8; - int length = input.ReadLength(); - if (length == 0) - { - return 0L; - } - int finalBufferPos = input.totalBytesRetired + input.bufferPos + length; - ulong result = 0L; - do - { - if (input.ReadTag() == expectedTag) - { - result = input.ReadUInt64(); - } - else - { - input.SkipLastField(); - } - } - while (input.totalBytesRetired + input.bufferPos < finalBufferPos); - return result; - } - - internal static long? ReadInt64Wrapper(CodedInputStream input) - { - return (long?)ReadUInt64Wrapper(input); + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.MaybeConsumeTag(ref span, ref state, tag); } #endregion #region Underlying reading primitives - /// - /// Same code as ReadRawVarint32, but read each byte individually, checking for - /// buffer overflow. - /// - private uint SlowReadRawVarint32() - { - int tmp = ReadRawByte(); - if (tmp < 128) - { - return (uint) tmp; - } - int result = tmp & 0x7f; - if ((tmp = ReadRawByte()) < 128) - { - result |= tmp << 7; - } - else - { - result |= (tmp & 0x7f) << 7; - if ((tmp = ReadRawByte()) < 128) - { - result |= tmp << 14; - } - else - { - result |= (tmp & 0x7f) << 14; - if ((tmp = ReadRawByte()) < 128) - { - result |= tmp << 21; - } - else - { - result |= (tmp & 0x7f) << 21; - result |= (tmp = ReadRawByte()) << 28; - if (tmp >= 128) - { - // Discard upper 32 bits. - for (int i = 0; i < 5; i++) - { - if (ReadRawByte() < 128) - { - return (uint) result; - } - } - throw InvalidProtocolBufferException.MalformedVarint(); - } - } - } - } - return (uint) result; - } - /// /// Reads a raw Varint from the stream. If larger than 32 bits, discard the upper bits. /// This method is optimised for the case where we've got lots of data in the buffer. @@ -1077,58 +557,8 @@ private uint SlowReadRawVarint32() /// internal uint ReadRawVarint32() { - if (bufferPos + 5 > bufferSize) - { - return SlowReadRawVarint32(); - } - - int tmp = buffer[bufferPos++]; - if (tmp < 128) - { - return (uint) tmp; - } - int result = tmp & 0x7f; - if ((tmp = buffer[bufferPos++]) < 128) - { - result |= tmp << 7; - } - else - { - result |= (tmp & 0x7f) << 7; - if ((tmp = buffer[bufferPos++]) < 128) - { - result |= tmp << 14; - } - else - { - result |= (tmp & 0x7f) << 14; - if ((tmp = buffer[bufferPos++]) < 128) - { - result |= tmp << 21; - } - else - { - result |= (tmp & 0x7f) << 21; - result |= (tmp = buffer[bufferPos++]) << 28; - if (tmp >= 128) - { - // Discard upper 32 bits. - // Note that this has to use ReadRawByte() as we only ensure we've - // got at least 5 bytes at the start of the method. This lets us - // use the fast path in more cases, and we rarely hit this section of code. - for (int i = 0; i < 5; i++) - { - if (ReadRawByte() < 128) - { - return (uint) result; - } - } - throw InvalidProtocolBufferException.MalformedVarint(); - } - } - } - } - return (uint) result; + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ParseRawVarint32(ref span, ref state); } /// @@ -1142,35 +572,7 @@ internal uint ReadRawVarint32() /// internal static uint ReadRawVarint32(Stream input) { - int result = 0; - int offset = 0; - for (; offset < 32; offset += 7) - { - int b = input.ReadByte(); - if (b == -1) - { - throw InvalidProtocolBufferException.TruncatedMessage(); - } - result |= (b & 0x7f) << offset; - if ((b & 0x80) == 0) - { - return (uint) result; - } - } - // Keep reading up to 64 bits. - for (; offset < 64; offset += 7) - { - int b = input.ReadByte(); - if (b == -1) - { - throw InvalidProtocolBufferException.TruncatedMessage(); - } - if ((b & 0x80) == 0) - { - return (uint) result; - } - } - throw InvalidProtocolBufferException.MalformedVarint(); + return ParsingPrimitives.ReadRawVarint32(input); } /// @@ -1178,44 +580,8 @@ internal static uint ReadRawVarint32(Stream input) /// internal ulong ReadRawVarint64() { - if (bufferPos + 10 <= bufferSize) - { - ulong result = buffer[bufferPos++]; - if (result < 128) - { - return result; - } - result &= 0x7f; - int shift = 7; - do - { - byte b = buffer[bufferPos++]; - result |= (ulong)(b & 0x7F) << shift; - if (b < 0x80) - { - return result; - } - shift += 7; - } - while (shift < 64); - } - else - { - int shift = 0; - ulong result = 0; - do - { - byte b = ReadRawByte(); - result |= (ulong)(b & 0x7F) << shift; - if (b < 0x80) - { - return result; - } - shift += 7; - } - while (shift < 64); - } - throw InvalidProtocolBufferException.MalformedVarint(); + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ParseRawVarint64(ref span, ref state); } /// @@ -1223,32 +589,8 @@ internal ulong ReadRawVarint64() /// internal uint ReadRawLittleEndian32() { - if (bufferPos + 4 <= bufferSize) - { - if (BitConverter.IsLittleEndian) - { - var result = BitConverter.ToUInt32(buffer, bufferPos); - bufferPos += 4; - return result; - } - else - { - uint b1 = buffer[bufferPos]; - uint b2 = buffer[bufferPos + 1]; - uint b3 = buffer[bufferPos + 2]; - uint b4 = buffer[bufferPos + 3]; - bufferPos += 4; - return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24); - } - } - else - { - uint b1 = ReadRawByte(); - uint b2 = ReadRawByte(); - uint b3 = ReadRawByte(); - uint b4 = ReadRawByte(); - return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24); - } + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ParseRawLittleEndian32(ref span, ref state); } /// @@ -1256,70 +598,8 @@ internal uint ReadRawLittleEndian32() /// internal ulong ReadRawLittleEndian64() { - if (bufferPos + 8 <= bufferSize) - { - if (BitConverter.IsLittleEndian) - { - var result = BitConverter.ToUInt64(buffer, bufferPos); - bufferPos += 8; - return result; - } - else - { - ulong b1 = buffer[bufferPos]; - ulong b2 = buffer[bufferPos + 1]; - ulong b3 = buffer[bufferPos + 2]; - ulong b4 = buffer[bufferPos + 3]; - ulong b5 = buffer[bufferPos + 4]; - ulong b6 = buffer[bufferPos + 5]; - ulong b7 = buffer[bufferPos + 6]; - ulong b8 = buffer[bufferPos + 7]; - bufferPos += 8; - return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24) - | (b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56); - } - } - else - { - ulong b1 = ReadRawByte(); - ulong b2 = ReadRawByte(); - ulong b3 = ReadRawByte(); - ulong b4 = ReadRawByte(); - ulong b5 = ReadRawByte(); - ulong b6 = ReadRawByte(); - ulong b7 = ReadRawByte(); - ulong b8 = ReadRawByte(); - return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24) - | (b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56); - } - } - - /// - /// Decode 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 int DecodeZigZag32(uint n) - { - return (int)(n >> 1) ^ -(int)(n & 1); - } - - /// - /// Decode 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 long DecodeZigZag64(ulong n) - { - return (long)(n >> 1) ^ -(long)(n & 1); + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ParseRawLittleEndian64(ref span, ref state); } #endregion @@ -1333,37 +613,7 @@ internal static long DecodeZigZag64(ulong n) /// The old limit. internal int PushLimit(int byteLimit) { - if (byteLimit < 0) - { - throw InvalidProtocolBufferException.NegativeSize(); - } - byteLimit += totalBytesRetired + bufferPos; - int oldLimit = currentLimit; - if (byteLimit > oldLimit) - { - throw InvalidProtocolBufferException.TruncatedMessage(); - } - currentLimit = byteLimit; - - RecomputeBufferSizeAfterLimit(); - - return oldLimit; - } - - private void RecomputeBufferSizeAfterLimit() - { - bufferSize += bufferSizeAfterLimit; - int bufferEnd = totalBytesRetired + bufferSize; - if (bufferEnd > currentLimit) - { - // Limit is in current buffer. - bufferSizeAfterLimit = bufferEnd - currentLimit; - bufferSize -= bufferSizeAfterLimit; - } - else - { - bufferSizeAfterLimit = 0; - } + return SegmentedBufferHelper.PushLimit(ref state, byteLimit); } /// @@ -1371,8 +621,7 @@ private void RecomputeBufferSizeAfterLimit() /// internal void PopLimit(int oldLimit) { - currentLimit = oldLimit; - RecomputeBufferSizeAfterLimit(); + SegmentedBufferHelper.PopLimit(ref state, oldLimit); } /// @@ -1383,12 +632,7 @@ internal bool ReachedLimit { get { - if (currentLimit == int.MaxValue) - { - return false; - } - int currentAbsolutePosition = totalBytesRetired + bufferPos; - return currentAbsolutePosition >= currentLimit; + return SegmentedBufferHelper.IsReachedLimit(ref state); } } @@ -1399,7 +643,11 @@ internal bool ReachedLimit /// public bool IsAtEnd { - get { return bufferPos == bufferSize && !RefillBuffer(false); } + get + { + var span = new ReadOnlySpan(buffer); + return SegmentedBufferHelper.IsAtEnd(ref span, ref state); + } } /// @@ -1413,69 +661,8 @@ public bool IsAtEnd /// private bool RefillBuffer(bool mustSucceed) { - if (bufferPos < bufferSize) - { - throw new InvalidOperationException("RefillBuffer() called when buffer wasn't empty."); - } - - if (totalBytesRetired + bufferSize == currentLimit) - { - // Oops, we hit a limit. - if (mustSucceed) - { - throw InvalidProtocolBufferException.TruncatedMessage(); - } - else - { - return false; - } - } - - totalBytesRetired += bufferSize; - - bufferPos = 0; - bufferSize = (input == null) ? 0 : input.Read(buffer, 0, buffer.Length); - if (bufferSize < 0) - { - throw new InvalidOperationException("Stream.Read returned a negative count"); - } - if (bufferSize == 0) - { - if (mustSucceed) - { - throw InvalidProtocolBufferException.TruncatedMessage(); - } - else - { - return false; - } - } - else - { - RecomputeBufferSizeAfterLimit(); - int totalBytesRead = - totalBytesRetired + bufferSize + bufferSizeAfterLimit; - if (totalBytesRead < 0 || totalBytesRead > sizeLimit) - { - throw InvalidProtocolBufferException.SizeLimitExceeded(); - } - return true; - } - } - - /// - /// Read one byte from the input. - /// - /// - /// the end of the stream or the current limit was reached - /// - internal byte ReadRawByte() - { - if (bufferPos == bufferSize) - { - RefillBuffer(true); - } - return buffer[bufferPos++]; + var span = new ReadOnlySpan(buffer); + return state.segmentedBufferHelper.RefillBuffer(ref span, ref state, mustSucceed); } /// @@ -1486,193 +673,25 @@ internal byte ReadRawByte() /// internal byte[] ReadRawBytes(int size) { - if (size < 0) - { - throw InvalidProtocolBufferException.NegativeSize(); - } - - if (totalBytesRetired + bufferPos + size > currentLimit) - { - // Read to the end of the stream (up to the current limit) anyway. - SkipRawBytes(currentLimit - totalBytesRetired - bufferPos); - // Then fail. - throw InvalidProtocolBufferException.TruncatedMessage(); - } - - if (size <= bufferSize - bufferPos) - { - // We have all the bytes we need already. - byte[] bytes = new byte[size]; - ByteArray.Copy(buffer, bufferPos, bytes, 0, size); - bufferPos += size; - return bytes; - } - else if (size < buffer.Length) - { - // Reading more bytes than are in the buffer, but not an excessive number - // of bytes. We can safely allocate the resulting array ahead of time. - - // First copy what we have. - byte[] bytes = new byte[size]; - int pos = bufferSize - bufferPos; - ByteArray.Copy(buffer, bufferPos, bytes, 0, pos); - bufferPos = bufferSize; - - // We want to use RefillBuffer() and then copy from the buffer into our - // byte array rather than reading directly into our byte array because - // the input may be unbuffered. - RefillBuffer(true); - - while (size - pos > bufferSize) - { - Buffer.BlockCopy(buffer, 0, bytes, pos, bufferSize); - pos += bufferSize; - bufferPos = bufferSize; - RefillBuffer(true); - } - - ByteArray.Copy(buffer, 0, bytes, pos, size - pos); - bufferPos = size - pos; - - return bytes; - } - else - { - // The size is very large. For security reasons, we can't allocate the - // entire byte array yet. The size comes directly from the input, so a - // maliciously-crafted message could provide a bogus very large size in - // order to trick the app into allocating a lot of memory. We avoid this - // by allocating and reading only a small chunk at a time, so that the - // malicious message must actually *be* extremely large to cause - // problems. Meanwhile, we limit the allowed size of a message elsewhere. - - // Remember the buffer markers since we'll have to copy the bytes out of - // it later. - int originalBufferPos = bufferPos; - int originalBufferSize = bufferSize; - - // Mark the current buffer consumed. - totalBytesRetired += bufferSize; - bufferPos = 0; - bufferSize = 0; - - // Read all the rest of the bytes we need. - int sizeLeft = size - (originalBufferSize - originalBufferPos); - List chunks = new List(); - - while (sizeLeft > 0) - { - byte[] chunk = new byte[Math.Min(sizeLeft, buffer.Length)]; - int pos = 0; - while (pos < chunk.Length) - { - int n = (input == null) ? -1 : input.Read(chunk, pos, chunk.Length - pos); - if (n <= 0) - { - throw InvalidProtocolBufferException.TruncatedMessage(); - } - totalBytesRetired += n; - pos += n; - } - sizeLeft -= chunk.Length; - chunks.Add(chunk); - } - - // OK, got everything. Now concatenate it all into one buffer. - byte[] bytes = new byte[size]; - - // Start by copying the leftover bytes from this.buffer. - int newPos = originalBufferSize - originalBufferPos; - ByteArray.Copy(buffer, originalBufferPos, bytes, 0, newPos); - - // And now all the chunks. - foreach (byte[] chunk in chunks) - { - Buffer.BlockCopy(chunk, 0, bytes, newPos, chunk.Length); - newPos += chunk.Length; - } - - // Done. - return bytes; - } - } - - /// - /// Reads and discards bytes. - /// - /// the end of the stream - /// or the current limit was reached - private void SkipRawBytes(int size) - { - if (size < 0) - { - throw InvalidProtocolBufferException.NegativeSize(); - } - - if (totalBytesRetired + bufferPos + size > currentLimit) - { - // Read to the end of the stream anyway. - SkipRawBytes(currentLimit - totalBytesRetired - bufferPos); - // Then fail. - throw InvalidProtocolBufferException.TruncatedMessage(); - } - - if (size <= bufferSize - bufferPos) - { - // We have all the bytes we need already. - bufferPos += size; - } - else - { - // Skipping more bytes than are in the buffer. First skip what we have. - int pos = bufferSize - bufferPos; - - // ROK 5/7/2013 Issue #54: should retire all bytes in buffer (bufferSize) - // totalBytesRetired += pos; - totalBytesRetired += bufferSize; - - bufferPos = 0; - bufferSize = 0; - - // Then skip directly from the InputStream for the rest. - if (pos < size) - { - if (input == null) - { - throw InvalidProtocolBufferException.TruncatedMessage(); - } - SkipImpl(size - pos); - totalBytesRetired += size - pos; - } - } + var span = new ReadOnlySpan(buffer); + return ParsingPrimitives.ReadRawBytes(ref span, ref state, size); } /// - /// Abstraction of skipping to cope with streams which can't really skip. + /// Reads a top-level message or a nested message after the limits for this message have been pushed. + /// (parser will proceed until the end of the current limit) + /// NOTE: this method needs to be public because it's invoked by the generated code - e.g. msg.MergeFrom(CodedInputStream input) method /// - private void SkipImpl(int amountToSkip) + public void ReadRawMessage(IMessage message) { - if (input.CanSeek) + ParseContext.Initialize(this, out ParseContext ctx); + try { - long previousPosition = input.Position; - input.Position += amountToSkip; - if (input.Position != previousPosition + amountToSkip) - { - throw InvalidProtocolBufferException.TruncatedMessage(); - } + ParsingPrimitivesMessages.ReadRawMessage(ref ctx, message); } - else + finally { - byte[] skipBuffer = new byte[Math.Min(1024, amountToSkip)]; - while (amountToSkip > 0) - { - int bytesRead = input.Read(skipBuffer, 0, Math.Min(skipBuffer.Length, amountToSkip)); - if (bytesRead <= 0) - { - throw InvalidProtocolBufferException.TruncatedMessage(); - } - amountToSkip -= bytesRead; - } + ctx.CopyStateTo(this); } } #endregion diff --git a/csharp/src/Google.Protobuf/Collections/MapField.cs b/csharp/src/Google.Protobuf/Collections/MapField.cs index 1924439e5cad..48cd7ab445a6 100644 --- a/csharp/src/Google.Protobuf/Collections/MapField.cs +++ b/csharp/src/Google.Protobuf/Collections/MapField.cs @@ -33,10 +33,12 @@ using Google.Protobuf.Compatibility; using Google.Protobuf.Reflection; using System; +using System.Buffers; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Security; namespace Google.Protobuf.Collections { @@ -421,14 +423,38 @@ public bool Equals(MapField other) /// Stream to read from /// Codec describing how the key/value pairs are encoded public void AddEntriesFrom(CodedInputStream input, Codec codec) + { + ParseContext.Initialize(input, out ParseContext ctx); + try + { + AddEntriesFrom(ref ctx, codec); + } + finally + { + ctx.CopyStateTo(input); + } + } + + /// + /// Adds entries to the map from the given parse context. + /// + /// + /// It is assumed that the input is initially positioned after the tag specified by the codec. + /// This method will continue reading entries from the input until the end is reached, or + /// a different tag is encountered. + /// + /// Input to read from + /// Codec describing how the key/value pairs are encoded + [SecuritySafeCritical] + public void AddEntriesFrom(ref ParseContext ctx, Codec codec) { var adapter = new Codec.MessageAdapter(codec); do { adapter.Reset(); - input.ReadMessage(adapter); + ctx.ReadMessage(adapter); this[adapter.Key] = adapter.Value; - } while (input.MaybeConsumeTag(codec.MapTag)); + } while (ParsingPrimitives.MaybeConsumeTag(ref ctx.buffer, ref ctx.state, codec.MapTag)); } /// @@ -620,7 +646,7 @@ public Codec(FieldCodec keyCodec, FieldCodec valueCodec, uint mapT /// This is nested inside Codec as it's tightly coupled to the associated codec, /// and it's simpler if it has direct access to all its fields. /// - internal class MessageAdapter : IMessage + internal class MessageAdapter : IMessage, IBufferMessage { private static readonly byte[] ZeroLengthMessageStreamData = new byte[] { 0 }; @@ -640,29 +666,46 @@ internal void Reset() } public void MergeFrom(CodedInputStream input) + { + // Message adapter is an internal class and we know that all the parsing will happen via InternalMergeFrom. + throw new NotImplementedException(); + } + + [SecuritySafeCritical] + public void InternalMergeFrom(ref ParseContext ctx) { uint tag; - while ((tag = input.ReadTag()) != 0) + while ((tag = ctx.ReadTag()) != 0) { if (tag == codec.keyCodec.Tag) { - Key = codec.keyCodec.Read(input); + Key = codec.keyCodec.Read(ref ctx); } else if (tag == codec.valueCodec.Tag) { - Value = codec.valueCodec.Read(input); + Value = codec.valueCodec.Read(ref ctx); } else { - input.SkipLastField(); + ParsingPrimitivesMessages.SkipLastField(ref ctx.buffer, ref ctx.state); } } // Corner case: a map entry with a key but no value, where the value type is a message. - // Read it as if we'd seen an input stream with no data (i.e. create a "default" message). + // Read it as if we'd seen input with no data (i.e. create a "default" message). if (Value == null) { - Value = codec.valueCodec.Read(new CodedInputStream(ZeroLengthMessageStreamData)); + if (ctx.state.CodedInputStream != null) + { + // the decoded message might not support parsing from ParseContext, so + // we need to allow fallback to the legacy MergeFrom(CodedInputStream) parsing. + Value = codec.valueCodec.Read(new CodedInputStream(ZeroLengthMessageStreamData)); + } + else + { + ParseContext.Initialize(new ReadOnlySequence(ZeroLengthMessageStreamData), out ParseContext zeroLengthCtx); + Value = codec.valueCodec.Read(ref zeroLengthCtx); + } } } diff --git a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs index 0e8bb617647b..5c39aabafb5f 100644 --- a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs +++ b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs @@ -34,6 +34,7 @@ using System.Collections; using System.Collections.Generic; using System.IO; +using System.Security; namespace Google.Protobuf.Collections { @@ -94,23 +95,42 @@ public RepeatedField Clone() /// The input stream to read from. /// The codec to use in order to read each entry. public void AddEntriesFrom(CodedInputStream input, FieldCodec codec) + { + ParseContext.Initialize(input, out ParseContext ctx); + try + { + AddEntriesFrom(ref ctx, codec); + } + finally + { + ctx.CopyStateTo(input); + } + } + + /// + /// Adds the entries from the given parse context, decoding them with the specified codec. + /// + /// The input to read from. + /// The codec to use in order to read each entry. + [SecuritySafeCritical] + public void AddEntriesFrom(ref ParseContext ctx, FieldCodec codec) { // TODO: Inline some of the Add code, so we can avoid checking the size on every // iteration. - uint tag = input.LastTag; + uint tag = ctx.state.lastTag; var reader = codec.ValueReader; // Non-nullable value types can be packed or not. if (FieldCodec.IsPackedRepeatedField(tag)) { - int length = input.ReadLength(); + int length = ctx.ReadLength(); if (length > 0) { - int oldLimit = input.PushLimit(length); - while (!input.ReachedLimit) + int oldLimit = SegmentedBufferHelper.PushLimit(ref ctx.state, length); + while (!SegmentedBufferHelper.IsReachedLimit(ref ctx.state)) { - Add(reader(input)); + Add(reader(ref ctx)); } - input.PopLimit(oldLimit); + SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit); } // Empty packed field. Odd, but valid - just ignore. } @@ -119,8 +139,8 @@ public void AddEntriesFrom(CodedInputStream input, FieldCodec codec) // Not packed... (possibly not packable) do { - Add(reader(input)); - } while (input.MaybeConsumeTag(tag)); + Add(reader(ref ctx)); + } while (ParsingPrimitives.MaybeConsumeTag(ref ctx.buffer, ref ctx.state, tag)); } } diff --git a/csharp/src/Google.Protobuf/ExtensionRegistry.cs b/csharp/src/Google.Protobuf/ExtensionRegistry.cs index d3d7ebdc5dd6..e72314b22c29 100644 --- a/csharp/src/Google.Protobuf/ExtensionRegistry.cs +++ b/csharp/src/Google.Protobuf/ExtensionRegistry.cs @@ -80,9 +80,9 @@ private ExtensionRegistry(IDictionary, Extension> collection /// bool ICollection.IsReadOnly => false; - internal bool ContainsInputField(CodedInputStream stream, Type target, out Extension extension) + internal bool ContainsInputField(uint lastTag, Type target, out Extension extension) { - return extensions.TryGetValue(new ObjectIntPair(target, WireFormat.GetTagFieldNumber(stream.LastTag)), out extension); + return extensions.TryGetValue(new ObjectIntPair(target, WireFormat.GetTagFieldNumber(lastTag)), out extension); } /// diff --git a/csharp/src/Google.Protobuf/ExtensionSet.cs b/csharp/src/Google.Protobuf/ExtensionSet.cs index d1bbf6910247..dd0b9a5519a7 100644 --- a/csharp/src/Google.Protobuf/ExtensionSet.cs +++ b/csharp/src/Google.Protobuf/ExtensionSet.cs @@ -182,20 +182,37 @@ public static class ExtensionSet /// If the set is null or the field was not otherwise merged, this returns false. /// public static bool TryMergeFieldFrom(ref ExtensionSet set, CodedInputStream stream) where TTarget : IExtendableMessage + { + ParseContext.Initialize(stream, out ParseContext ctx); + try + { + return TryMergeFieldFrom(ref set, ref ctx); + } + finally + { + ctx.CopyStateTo(stream); + } + } + + /// + /// Tries to merge a field from the coded input, returning true if the field was merged. + /// If the set is null or the field was not otherwise merged, this returns false. + /// + public static bool TryMergeFieldFrom(ref ExtensionSet set, ref ParseContext ctx) where TTarget : IExtendableMessage { Extension extension; - int lastFieldNumber = WireFormat.GetTagFieldNumber(stream.LastTag); - + int lastFieldNumber = WireFormat.GetTagFieldNumber(ctx.LastTag); + IExtensionValue extensionValue; if (set != null && set.ValuesByNumber.TryGetValue(lastFieldNumber, out extensionValue)) { - extensionValue.MergeFrom(stream); + extensionValue.MergeFrom(ref ctx); return true; } - else if (stream.ExtensionRegistry != null && stream.ExtensionRegistry.ContainsInputField(stream, typeof(TTarget), out extension)) + else if (ctx.ExtensionRegistry != null && ctx.ExtensionRegistry.ContainsInputField(ctx.LastTag, typeof(TTarget), out extension)) { IExtensionValue value = extension.CreateValue(); - value.MergeFrom(stream); + value.MergeFrom(ref ctx); set = (set ?? new ExtensionSet()); set.ValuesByNumber.Add(extension.FieldNumber, value); return true; diff --git a/csharp/src/Google.Protobuf/ExtensionValue.cs b/csharp/src/Google.Protobuf/ExtensionValue.cs index 6ee737a7b0c9..df934ed7a1e6 100644 --- a/csharp/src/Google.Protobuf/ExtensionValue.cs +++ b/csharp/src/Google.Protobuf/ExtensionValue.cs @@ -38,7 +38,8 @@ namespace Google.Protobuf { internal interface IExtensionValue : IEquatable, IDeepCloneable { - void MergeFrom(CodedInputStream input); + void MergeFrom(ref ParseContext ctx); + void MergeFrom(IExtensionValue value); void WriteTo(CodedOutputStream output); int CalculateSize(); @@ -91,16 +92,16 @@ public override int GetHashCode() } } - public void MergeFrom(CodedInputStream input) + public void MergeFrom(ref ParseContext ctx) { - codec.ValueMerger(input, ref field); + codec.ValueMerger(ref ctx, ref field); } public void MergeFrom(IExtensionValue value) { if (value is ExtensionValue) { - var extensionValue = value as ExtensionValue; + var extensionValue = value as ExtensionValue; codec.FieldMerger(ref field, extensionValue.field); } } @@ -124,13 +125,13 @@ public void SetValue(T value) public bool IsInitialized() { - if (field is IMessage) - { - return (field as IMessage).IsInitialized(); + if (field is IMessage) + { + return (field as IMessage).IsInitialized(); } - else - { - return true; + else + { + return true; } } } @@ -185,6 +186,11 @@ public void MergeFrom(CodedInputStream input) field.AddEntriesFrom(input, codec); } + public void MergeFrom(ref ParseContext ctx) + { + field.AddEntriesFrom(ref ctx, codec); + } + public void MergeFrom(IExtensionValue value) { if (value is RepeatedExtensionValue) @@ -202,20 +208,20 @@ public void WriteTo(CodedOutputStream output) public bool IsInitialized() { - for (int i = 0; i < field.Count; i++) - { - var element = field[i]; - if (element is IMessage) - { - if (!(element as IMessage).IsInitialized()) - { - return false; - } - } - else - { - break; - } + for (int i = 0; i < field.Count; i++) + { + var element = field[i]; + if (element is IMessage) + { + if (!(element as IMessage).IsInitialized()) + { + return false; + } + } + else + { + break; + } } return true; diff --git a/csharp/src/Google.Protobuf/FieldCodec.cs b/csharp/src/Google.Protobuf/FieldCodec.cs index 1971261649a0..ee87736d1f31 100644 --- a/csharp/src/Google.Protobuf/FieldCodec.cs +++ b/csharp/src/Google.Protobuf/FieldCodec.cs @@ -35,6 +35,7 @@ using Google.Protobuf.WellKnownTypes; using System; using System.Collections.Generic; +using System.Security; namespace Google.Protobuf { @@ -218,7 +219,7 @@ public static FieldCodec ForEnum(uint tag, Func toInt32, FuncA codec for the given tag. public static FieldCodec ForString(uint tag, string defaultValue) { - return new FieldCodec(input => input.ReadString(), (output, value) => output.WriteString(value), CodedOutputStream.ComputeStringSize, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadString(), (output, value) => output.WriteString(value), CodedOutputStream.ComputeStringSize, tag, defaultValue); } /// @@ -229,7 +230,7 @@ public static FieldCodec ForString(uint tag, string defaultValue) /// A codec for the given tag. public static FieldCodec ForBytes(uint tag, ByteString defaultValue) { - return new FieldCodec(input => input.ReadBytes(), (output, value) => output.WriteBytes(value), CodedOutputStream.ComputeBytesSize, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadBytes(), (output, value) => output.WriteBytes(value), CodedOutputStream.ComputeBytesSize, tag, defaultValue); } /// @@ -240,7 +241,7 @@ public static FieldCodec ForBytes(uint tag, ByteString defaultValue) /// A codec for the given tag. public static FieldCodec ForBool(uint tag, bool defaultValue) { - return new FieldCodec(input => input.ReadBool(), (output, value) => output.WriteBool(value), CodedOutputStream.BoolSize, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadBool(), (output, value) => output.WriteBool(value), CodedOutputStream.BoolSize, tag, defaultValue); } /// @@ -251,7 +252,7 @@ public static FieldCodec ForBool(uint tag, bool defaultValue) /// A codec for the given tag. public static FieldCodec ForInt32(uint tag, int defaultValue) { - return new FieldCodec(input => input.ReadInt32(), (output, value) => output.WriteInt32(value), CodedOutputStream.ComputeInt32Size, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadInt32(), (output, value) => output.WriteInt32(value), CodedOutputStream.ComputeInt32Size, tag, defaultValue); } /// @@ -262,7 +263,7 @@ public static FieldCodec ForInt32(uint tag, int defaultValue) /// A codec for the given tag. public static FieldCodec ForSInt32(uint tag, int defaultValue) { - return new FieldCodec(input => input.ReadSInt32(), (output, value) => output.WriteSInt32(value), CodedOutputStream.ComputeSInt32Size, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadSInt32(), (output, value) => output.WriteSInt32(value), CodedOutputStream.ComputeSInt32Size, tag, defaultValue); } /// @@ -273,7 +274,7 @@ public static FieldCodec ForSInt32(uint tag, int defaultValue) /// A codec for the given tag. public static FieldCodec ForFixed32(uint tag, uint defaultValue) { - return new FieldCodec(input => input.ReadFixed32(), (output, value) => output.WriteFixed32(value), 4, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadFixed32(), (output, value) => output.WriteFixed32(value), 4, tag, defaultValue); } /// @@ -284,7 +285,7 @@ public static FieldCodec ForFixed32(uint tag, uint defaultValue) /// A codec for the given tag. public static FieldCodec ForSFixed32(uint tag, int defaultValue) { - return new FieldCodec(input => input.ReadSFixed32(), (output, value) => output.WriteSFixed32(value), 4, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadSFixed32(), (output, value) => output.WriteSFixed32(value), 4, tag, defaultValue); } /// @@ -295,7 +296,7 @@ public static FieldCodec ForSFixed32(uint tag, int defaultValue) /// A codec for the given tag. public static FieldCodec ForUInt32(uint tag, uint defaultValue) { - return new FieldCodec(input => input.ReadUInt32(), (output, value) => output.WriteUInt32(value), CodedOutputStream.ComputeUInt32Size, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadUInt32(), (output, value) => output.WriteUInt32(value), CodedOutputStream.ComputeUInt32Size, tag, defaultValue); } /// @@ -306,7 +307,7 @@ public static FieldCodec ForUInt32(uint tag, uint defaultValue) /// A codec for the given tag. public static FieldCodec ForInt64(uint tag, long defaultValue) { - return new FieldCodec(input => input.ReadInt64(), (output, value) => output.WriteInt64(value), CodedOutputStream.ComputeInt64Size, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadInt64(), (output, value) => output.WriteInt64(value), CodedOutputStream.ComputeInt64Size, tag, defaultValue); } /// @@ -317,7 +318,7 @@ public static FieldCodec ForInt64(uint tag, long defaultValue) /// A codec for the given tag. public static FieldCodec ForSInt64(uint tag, long defaultValue) { - return new FieldCodec(input => input.ReadSInt64(), (output, value) => output.WriteSInt64(value), CodedOutputStream.ComputeSInt64Size, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadSInt64(), (output, value) => output.WriteSInt64(value), CodedOutputStream.ComputeSInt64Size, tag, defaultValue); } /// @@ -328,7 +329,7 @@ public static FieldCodec ForSInt64(uint tag, long defaultValue) /// A codec for the given tag. public static FieldCodec ForFixed64(uint tag, ulong defaultValue) { - return new FieldCodec(input => input.ReadFixed64(), (output, value) => output.WriteFixed64(value), 8, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadFixed64(), (output, value) => output.WriteFixed64(value), 8, tag, defaultValue); } /// @@ -339,7 +340,7 @@ public static FieldCodec ForFixed64(uint tag, ulong defaultValue) /// A codec for the given tag. public static FieldCodec ForSFixed64(uint tag, long defaultValue) { - return new FieldCodec(input => input.ReadSFixed64(), (output, value) => output.WriteSFixed64(value), 8, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadSFixed64(), (output, value) => output.WriteSFixed64(value), 8, tag, defaultValue); } /// @@ -350,7 +351,7 @@ public static FieldCodec ForSFixed64(uint tag, long defaultValue) /// A codec for the given tag. public static FieldCodec ForUInt64(uint tag, ulong defaultValue) { - return new FieldCodec(input => input.ReadUInt64(), (output, value) => output.WriteUInt64(value), CodedOutputStream.ComputeUInt64Size, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadUInt64(), (output, value) => output.WriteUInt64(value), CodedOutputStream.ComputeUInt64Size, tag, defaultValue); } /// @@ -361,7 +362,7 @@ public static FieldCodec ForUInt64(uint tag, ulong defaultValue) /// A codec for the given tag. public static FieldCodec ForFloat(uint tag, float defaultValue) { - return new FieldCodec(input => input.ReadFloat(), (output, value) => output.WriteFloat(value), CodedOutputStream.FloatSize, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadFloat(), (output, value) => output.WriteFloat(value), CodedOutputStream.FloatSize, tag, defaultValue); } /// @@ -372,7 +373,7 @@ public static FieldCodec ForFloat(uint tag, float defaultValue) /// A codec for the given tag. public static FieldCodec ForDouble(uint tag, double defaultValue) { - return new FieldCodec(input => input.ReadDouble(), (output, value) => output.WriteDouble(value), CodedOutputStream.DoubleSize, tag, defaultValue); + return new FieldCodec((ref ParseContext ctx) => ctx.ReadDouble(), (output, value) => output.WriteDouble(value), CodedOutputStream.DoubleSize, tag, defaultValue); } // Enums are tricky. We can probably use expression trees to build these delegates automatically, @@ -388,8 +389,8 @@ public static FieldCodec ForDouble(uint tag, double defaultValue) /// A codec for the given tag. public static FieldCodec ForEnum(uint tag, Func toInt32, Func fromInt32, T defaultValue) { - return new FieldCodec(input => fromInt32( - input.ReadEnum()), + return new FieldCodec((ref ParseContext ctx) => fromInt32( + ctx.ReadEnum()), (output, value) => output.WriteEnum(toInt32(value)), value => CodedOutputStream.ComputeEnumSize(toInt32(value)), tag, defaultValue); } @@ -403,21 +404,21 @@ public static FieldCodec ForEnum(uint tag, Func toInt32, Func ForMessage(uint tag, MessageParser parser) where T : class, IMessage { return new FieldCodec( - input => + (ref ParseContext ctx) => { T message = parser.CreateTemplate(); - input.ReadMessage(message); + ctx.ReadMessage(message); return message; }, (output, value) => output.WriteMessage(value), - (CodedInputStream i, ref T v) => + (ref ParseContext ctx, ref T v) => { if (v == null) { v = parser.CreateTemplate(); } - i.ReadMessage(v); + ctx.ReadMessage(v); }, (ref T v, T v2) => { @@ -448,21 +449,21 @@ public static FieldCodec ForEnum(uint tag, Func toInt32, Func ForGroup(uint startTag, uint endTag, MessageParser parser) where T : class, IMessage { return new FieldCodec( - input => + (ref ParseContext ctx) => { T message = parser.CreateTemplate(); - input.ReadGroup(message); + ctx.ReadGroup(message); return message; }, (output, value) => output.WriteGroup(value), - (CodedInputStream i, ref T v) => + (ref ParseContext ctx, ref T v) => { if (v == null) { v = parser.CreateTemplate(); } - i.ReadGroup(v); + ctx.ReadGroup(v); }, (ref T v, T v2) => { @@ -490,9 +491,9 @@ public static FieldCodec ForEnum(uint tag, Func toInt32, Func(); return new FieldCodec( - input => WrapperCodecs.Read(input, nestedCodec), + (ref ParseContext ctx) => WrapperCodecs.Read(ref ctx, nestedCodec), (output, value) => WrapperCodecs.Write(output, value, nestedCodec), - (CodedInputStream i, ref T v) => v = WrapperCodecs.Read(i, 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), tag, 0, @@ -509,7 +510,7 @@ public static FieldCodec ForEnum(uint tag, Func toInt32, Func( WrapperCodecs.GetReader(), (output, value) => WrapperCodecs.Write(output, value.Value, nestedCodec), - (CodedInputStream i, ref T? v) => v = WrapperCodecs.Read(i, 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), tag, 0, @@ -542,17 +543,17 @@ private static class WrapperCodecs private static readonly Dictionary Readers = new Dictionary { // TODO: Provide more optimized readers. - { typeof(bool), (Func)CodedInputStream.ReadBoolWrapper }, - { typeof(int), (Func)CodedInputStream.ReadInt32Wrapper }, - { typeof(long), (Func)CodedInputStream.ReadInt64Wrapper }, - { typeof(uint), (Func)CodedInputStream.ReadUInt32Wrapper }, - { typeof(ulong), (Func)CodedInputStream.ReadUInt64Wrapper }, + { typeof(bool), (ValueReader)ParsingPrimitivesWrappers.ReadBoolWrapper }, + { typeof(int), (ValueReader)ParsingPrimitivesWrappers.ReadInt32Wrapper }, + { typeof(long), (ValueReader)ParsingPrimitivesWrappers.ReadInt64Wrapper }, + { typeof(uint), (ValueReader)ParsingPrimitivesWrappers.ReadUInt32Wrapper }, + { typeof(ulong), (ValueReader)ParsingPrimitivesWrappers.ReadUInt64Wrapper }, { typeof(float), BitConverter.IsLittleEndian ? - (Func)CodedInputStream.ReadFloatWrapperLittleEndian : - (Func)CodedInputStream.ReadFloatWrapperSlow }, + (ValueReader)ParsingPrimitivesWrappers.ReadFloatWrapperLittleEndian : + (ValueReader)ParsingPrimitivesWrappers.ReadFloatWrapperSlow }, { typeof(double), BitConverter.IsLittleEndian ? - (Func)CodedInputStream.ReadDoubleWrapperLittleEndian : - (Func)CodedInputStream.ReadDoubleWrapperSlow }, + (ValueReader)ParsingPrimitivesWrappers.ReadDoubleWrapperLittleEndian : + (ValueReader)ParsingPrimitivesWrappers.ReadDoubleWrapperSlow }, // `string` and `ByteString` less performance-sensitive. Do not implement for now. { typeof(string), null }, { typeof(ByteString), null }, @@ -572,7 +573,7 @@ internal static FieldCodec GetCodec() return (FieldCodec) value; } - internal static Func GetReader() where T : struct + internal static ValueReader GetReader() where T : struct { object value; if (!Readers.TryGetValue(typeof(T), out value)) @@ -583,33 +584,34 @@ internal static FieldCodec GetCodec() { // Return default unoptimized reader for the wrapper type. var nestedCoded = GetCodec(); - return input => Read(input, nestedCoded); + return (ref ParseContext ctx) => Read(ref ctx, nestedCoded); } // Return optimized read for the wrapper type. - return (Func)value; + return (ValueReader)value; } - internal static T Read(CodedInputStream input, FieldCodec codec) + [SecuritySafeCritical] + internal static T Read(ref ParseContext ctx, FieldCodec codec) { - int length = input.ReadLength(); - int oldLimit = input.PushLimit(length); + int length = ctx.ReadLength(); + int oldLimit = SegmentedBufferHelper.PushLimit(ref ctx.state, length); uint tag; T value = codec.DefaultValue; - while ((tag = input.ReadTag()) != 0) + while ((tag = ctx.ReadTag()) != 0) { if (tag == codec.Tag) { - value = codec.Read(input); + value = codec.Read(ref ctx); } else { - input.SkipLastField(); + ParsingPrimitivesMessages.SkipLastField(ref ctx.buffer, ref ctx.state); } } - input.CheckReadEndOfStreamTag(); - input.PopLimit(oldLimit); + ParsingPrimitivesMessages.CheckReadEndOfStreamTag(ref ctx.state); + SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit); return value; } @@ -628,6 +630,8 @@ internal static int CalculateSize(T value, FieldCodec codec) } } + internal delegate TValue ValueReader(ref ParseContext ctx); + /// /// /// An encode/decode pair for a single field. This effectively encapsulates @@ -653,7 +657,7 @@ public sealed class FieldCodec /// /// Merges an input stream into a value /// - internal delegate void InputMerger(CodedInputStream input, ref T value); + internal delegate void InputMerger(ref ParseContext ctx, ref T value); /// /// Merges a value into a reference to another value, returning a boolean if the value was set @@ -692,7 +696,7 @@ static FieldCodec() /// Returns a delegate to read a value from a coded input stream. It is assumed that /// the stream is already positioned on the appropriate tag. /// - internal Func ValueReader { get; } + internal ValueReader ValueReader { get; } /// /// Returns a delegate to merge a value from a coded input stream. @@ -739,7 +743,7 @@ static FieldCodec() private readonly int tagSize; internal FieldCodec( - Func reader, + ValueReader reader, Action writer, int fixedSize, uint tag, @@ -749,16 +753,16 @@ static FieldCodec() } internal FieldCodec( - Func reader, + ValueReader reader, Action writer, Func sizeCalculator, uint tag, - T defaultValue) : this(reader, writer, (CodedInputStream i, ref T v) => v = reader(i), (ref T v, T v2) => { v = v2; return true; }, sizeCalculator, tag, 0, defaultValue) + 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) { } internal FieldCodec( - Func reader, + ValueReader reader, Action writer, InputMerger inputMerger, ValuesMerger valuesMerger, @@ -769,7 +773,7 @@ static FieldCodec() } internal FieldCodec( - Func reader, + ValueReader reader, Action writer, InputMerger inputMerger, ValuesMerger valuesMerger, @@ -815,7 +819,28 @@ public void WriteTagAndValue(CodedOutputStream output, T value) /// /// The input stream to read from. /// The value read from the stream. - public T Read(CodedInputStream input) => ValueReader(input); + public T Read(CodedInputStream input) + { + ParseContext.Initialize(input, out ParseContext ctx); + try + { + return ValueReader(ref ctx); + } + finally + { + ctx.CopyStateTo(input); + } + } + + /// + /// Reads a value of the codec type from the given . + /// + /// The parse context to read from. + /// The value read. + public T Read(ref ParseContext ctx) + { + return ValueReader(ref ctx); + } /// /// Calculates the size required to write the given value, with a tag, diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.csproj b/csharp/src/Google.Protobuf/Google.Protobuf.csproj index 53f45febc711..ab1df4aa3cdc 100644 --- a/csharp/src/Google.Protobuf/Google.Protobuf.csproj +++ b/csharp/src/Google.Protobuf/Google.Protobuf.csproj @@ -1,13 +1,14 @@ - + C# runtime library for Protocol Buffers - Google's data interchange format. Copyright 2015, Google Inc. Google Protocol Buffers 3.11.4 - 6 + + 7.2 Google Inc. - netstandard1.0;netstandard2.0;net45 + netstandard1.1;netstandard2.0;net45 true ../../keys/Google.Protobuf.snk true @@ -18,25 +19,26 @@ https://github.com/protocolbuffers/protobuf/blob/master/LICENSE git https://github.com/protocolbuffers/protobuf.git + $(DefineConstants);GOOGLE_PROTOBUF_SUPPORT_SYSTEM_MEMORY + True $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb - - $(DefineConstants);GOOGLE_PROTOBUF_SUPPORT_SYSTEM_MEMORY + + $(DefineConstants);GOOGLE_PROTOBUF_SUPPORT_FAST_STRING - - - - - + + + - - + + + diff --git a/csharp/src/Google.Protobuf/IBufferMessage.cs b/csharp/src/Google.Protobuf/IBufferMessage.cs new file mode 100644 index 000000000000..f6d174b3b768 --- /dev/null +++ b/csharp/src/Google.Protobuf/IBufferMessage.cs @@ -0,0 +1,49 @@ +#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 + +namespace Google.Protobuf +{ +#if GOOGLE_PROTOBUF_SUPPORT_SYSTEM_MEMORY + /// + /// Interface for a Protocol Buffers message, supporting + /// parsing from . + /// + public interface IBufferMessage : IMessage + { + /// + /// Internal implementation of merging data from given parse context into this message. + /// Users should never invoke this method directly. + /// + void InternalMergeFrom(ref ParseContext ctx); + } +#endif +} diff --git a/csharp/src/Google.Protobuf/MessageExtensions.cs b/csharp/src/Google.Protobuf/MessageExtensions.cs index 06e0980ec2b1..51e40915c81d 100644 --- a/csharp/src/Google.Protobuf/MessageExtensions.cs +++ b/csharp/src/Google.Protobuf/MessageExtensions.cs @@ -31,9 +31,11 @@ #endregion using Google.Protobuf.Reflection; +using System.Buffers; using System.Collections; using System.IO; using System.Linq; +using System.Security; namespace Google.Protobuf { @@ -248,6 +250,16 @@ internal static void MergeFrom(this IMessage message, Stream input, bool discard codedInput.CheckReadEndOfStreamTag(); } + [SecuritySafeCritical] + internal static void MergeFrom(this IMessage message, ReadOnlySequence data, bool discardUnknownFields, ExtensionRegistry registry) + { + ParseContext.Initialize(data, out ParseContext ctx); + ctx.DiscardUnknownFields = discardUnknownFields; + ctx.ExtensionRegistry = registry; + ParsingPrimitivesMessages.ReadRawMessage(ref ctx, message); + ParsingPrimitivesMessages.CheckReadEndOfStreamTag(ref ctx.state); + } + internal static void MergeDelimitedFrom(this IMessage message, Stream input, bool discardUnknownFields, ExtensionRegistry registry) { ProtoPreconditions.CheckNotNull(message, "message"); diff --git a/csharp/src/Google.Protobuf/MessageParser.cs b/csharp/src/Google.Protobuf/MessageParser.cs index 06d0f1059c7a..f8b26c2348ed 100644 --- a/csharp/src/Google.Protobuf/MessageParser.cs +++ b/csharp/src/Google.Protobuf/MessageParser.cs @@ -31,7 +31,9 @@ #endregion using System; +using System.Buffers; using System.IO; +using System.Security; namespace Google.Protobuf { @@ -113,6 +115,19 @@ public IMessage ParseFrom(Stream input) return message; } + /// + /// Parses a message from the given sequence. + /// + /// The data to parse. + /// The parsed message. + [SecuritySafeCritical] + public IMessage ParseFrom(ReadOnlySequence data) + { + IMessage message = factory(); + message.MergeFrom(data, DiscardUnknownFields, Extensions); + return message; + } + /// /// Parses a length-delimited message from the given stream. /// @@ -287,6 +302,19 @@ public new T ParseFrom(Stream input) return message; } + /// + /// Parses a message from the given sequence. + /// + /// The data to parse. + /// The parsed message. + [SecuritySafeCritical] + public new T ParseFrom(ReadOnlySequence data) + { + T message = factory(); + message.MergeFrom(data, DiscardUnknownFields, Extensions); + return message; + } + /// /// Parses a length-delimited message from the given stream. /// diff --git a/csharp/src/Google.Protobuf/ParseContext.cs b/csharp/src/Google.Protobuf/ParseContext.cs new file mode 100644 index 000000000000..bf4623656525 --- /dev/null +++ b/csharp/src/Google.Protobuf/ParseContext.cs @@ -0,0 +1,329 @@ +#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 parsing state and is passed along + /// as the parsing 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 ParseContext + { + internal const int DefaultRecursionLimit = 100; + internal const int DefaultSizeLimit = Int32.MaxValue; + + internal ReadOnlySpan buffer; + internal ParserInternalState state; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void Initialize(ref ReadOnlySpan buffer, ref ParserInternalState state, out ParseContext ctx) + { + ctx.buffer = buffer; + ctx.state = state; + } + + /// + /// Creates a ParseContext instance from CodedInputStream. + /// WARNING: internally this copies the CodedInputStream's state, so after done with the ParseContext, + /// the CodedInputStream's state needs to be updated. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void Initialize(CodedInputStream input, out ParseContext ctx) + { + ctx.buffer = new ReadOnlySpan(input.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 CodedInputStream if we want to keep it usable. + ctx.state = input.InternalState; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void Initialize(ReadOnlySequence input, out ParseContext ctx) + { + Initialize(input, DefaultRecursionLimit, out ctx); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void Initialize(ReadOnlySequence input, int recursionLimit, out ParseContext ctx) + { + ctx.buffer = default; + ctx.state = default; + ctx.state.lastTag = 0; + ctx.state.recursionDepth = 0; + ctx.state.sizeLimit = DefaultSizeLimit; + ctx.state.recursionLimit = recursionLimit; + ctx.state.currentLimit = int.MaxValue; + SegmentedBufferHelper.Initialize(input, out ctx.state.segmentedBufferHelper, out ctx.buffer); + ctx.state.bufferPos = 0; + ctx.state.bufferSize = ctx.buffer.Length; + + ctx.state.DiscardUnknownFields = false; + ctx.state.ExtensionRegistry = null; + } + + /// + /// Returns the last tag read, or 0 if no tags have been read or we've read beyond + /// the end of the input. + /// + internal uint LastTag { get { return state.lastTag; } } + + /// + /// Internal-only property; when set to true, unknown fields will be discarded while parsing. + /// + internal bool DiscardUnknownFields { + get { return state.DiscardUnknownFields; } + set { state.DiscardUnknownFields = value; } + } + + /// + /// Internal-only property; provides extension identifiers to compatible messages while parsing. + /// + internal ExtensionRegistry ExtensionRegistry + { + get { return state.ExtensionRegistry; } + set { state.ExtensionRegistry = value; } + } + + /// + /// Reads a field tag, returning the tag of 0 for "end of input". + /// + /// + /// If this method returns 0, it doesn't necessarily mean the end of all + /// the data in this CodedInputReader; it may be the end of the logical input + /// for an embedded message, for example. + /// + /// The next field tag, or 0 for end of input. (0 is never a valid tag.) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public uint ReadTag() + { + return ParsingPrimitives.ParseTag(ref buffer, ref state); + } + + /// + /// Reads a double field from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public double ReadDouble() + { + return ParsingPrimitives.ParseDouble(ref buffer, ref state); + } + + /// + /// Reads a float field from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float ReadFloat() + { + return ParsingPrimitives.ParseFloat(ref buffer, ref state); + } + + /// + /// Reads a uint64 field from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ulong ReadUInt64() + { + return ParsingPrimitives.ParseRawVarint64(ref buffer, ref state); + } + + /// + /// Reads an int64 field from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public long ReadInt64() + { + return (long)ParsingPrimitives.ParseRawVarint64(ref buffer, ref state); + } + + /// + /// Reads an int32 field from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int ReadInt32() + { + return (int)ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); + } + + /// + /// Reads a fixed64 field from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ulong ReadFixed64() + { + return ParsingPrimitives.ParseRawLittleEndian64(ref buffer, ref state); + } + + /// + /// Reads a fixed32 field from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public uint ReadFixed32() + { + return ParsingPrimitives.ParseRawLittleEndian32(ref buffer, ref state); + } + + /// + /// Reads a bool field from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool ReadBool() + { + return ParsingPrimitives.ParseRawVarint64(ref buffer, ref state) != 0; + } + /// + /// Reads a string field from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public string ReadString() + { + return ParsingPrimitives.ReadString(ref buffer, ref state); + } + + /// + /// Reads an embedded message field value from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ReadMessage(IMessage message) + { + ParsingPrimitivesMessages.ReadMessage(ref this, message); + } + + /// + /// Reads an embedded group field from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ReadGroup(IMessage message) + { + ParsingPrimitivesMessages.ReadGroup(ref this, message); + } + + /// + /// Reads a bytes field value from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ByteString ReadBytes() + { + return ParsingPrimitives.ReadBytes(ref buffer, ref state); + } + /// + /// Reads a uint32 field value from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public uint ReadUInt32() + { + return ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); + } + + /// + /// Reads an enum field value from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int ReadEnum() + { + // Currently just a pass-through, but it's nice to separate it logically from WriteInt32. + return (int)ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); + } + + /// + /// Reads an sfixed32 field value from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int ReadSFixed32() + { + return (int)ParsingPrimitives.ParseRawLittleEndian32(ref buffer, ref state); + } + + /// + /// Reads an sfixed64 field value from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public long ReadSFixed64() + { + return (long)ParsingPrimitives.ParseRawLittleEndian64(ref buffer, ref state); + } + + /// + /// Reads an sint32 field value from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int ReadSInt32() + { + return ParsingPrimitives.DecodeZigZag32(ParsingPrimitives.ParseRawVarint32(ref buffer, ref state)); + } + + /// + /// Reads an sint64 field value from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public long ReadSInt64() + { + return ParsingPrimitives.DecodeZigZag64(ParsingPrimitives.ParseRawVarint64(ref buffer, ref state)); + } + + /// + /// Reads a length for length-delimited data. + /// + /// + /// This is internally just reading a varint, but this method exists + /// to make the calling code clearer. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int ReadLength() + { + return (int)ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); + } + + internal void CopyStateTo(CodedInputStream input) + { + input.InternalState = state; + } + + internal void LoadStateFrom(CodedInputStream input) + { + state = input.InternalState; + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/ParserInternalState.cs b/csharp/src/Google.Protobuf/ParserInternalState.cs new file mode 100644 index 000000000000..4f0500b0a8d3 --- /dev/null +++ b/csharp/src/Google.Protobuf/ParserInternalState.cs @@ -0,0 +1,115 @@ +#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 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 + // be included in CodedInputStream's internal state + + /// + /// The position within the current buffer (i.e. the next byte to read) + /// + internal int bufferPos; + + /// + /// Size of the current buffer + /// + internal int bufferSize; + + /// + /// If we are currently inside a length-delimited block, this is the number of + /// bytes in the buffer that are still available once we leave the delimited block. + /// + internal int bufferSizeAfterLimit; + + /// + /// The absolute position of the end of the current length-delimited block (including totalBytesRetired) + /// + internal int currentLimit; + + /// + /// The total number of consumed before the start of the current buffer. The + /// total bytes read up to the current position can be computed as + /// totalBytesRetired + bufferPos. + /// + internal int totalBytesRetired; + + internal int recursionDepth; // current recursion depth + + internal SegmentedBufferHelper segmentedBufferHelper; + + /// + /// The last tag we read. 0 indicates we've read to the end of the stream + /// (or haven't read anything yet). + /// + internal uint lastTag; + + /// + /// The next tag, used to store the value read by PeekTag. + /// + internal uint nextTag; + internal bool hasNextTag; + + // these fields are configuration, they should be readonly + internal int sizeLimit; + internal int recursionLimit; + + // If non-null, the top level parse method was started with given coded input stream as an argument + // which also means we can potentially fallback to calling MergeFrom(CodedInputStream cis) if needed. + internal CodedInputStream CodedInputStream => segmentedBufferHelper.CodedInputStream; + + /// + /// Internal-only property; when set to true, unknown fields will be discarded while parsing. + /// + internal bool DiscardUnknownFields { get; set; } + + /// + /// Internal-only property; provides extension identifiers to compatible messages while parsing. + /// + internal ExtensionRegistry ExtensionRegistry { get; set; } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/ParsingPrimitives.cs b/csharp/src/Google.Protobuf/ParsingPrimitives.cs new file mode 100644 index 000000000000..28a19493d40c --- /dev/null +++ b/csharp/src/Google.Protobuf/ParsingPrimitives.cs @@ -0,0 +1,735 @@ +#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 +{ + /// + /// Primitives for parsing protobuf wire format. + /// + [SecuritySafeCritical] + internal static class ParsingPrimitives + { + + /// + /// Reads a length for length-delimited data. + /// + /// + /// This is internally just reading a varint, but this method exists + /// to make the calling code clearer. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + + public static int ParseLength(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + return (int)ParseRawVarint32(ref buffer, ref state); + } + + /// + /// Parses the next tag. + /// If the end of logical stream was reached, an invalid tag of 0 is returned. + /// + public static uint ParseTag(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + // The "nextTag" logic is there only as an optimization for reading non-packed repeated / map + // fields and is strictly speaking not necessary. + // TODO(jtattermusch): look into simplifying the ParseTag logic. + if (state.hasNextTag) + { + state.lastTag = state.nextTag; + state.hasNextTag = false; + return state.lastTag; + } + + // Optimize for the incredibly common case of having at least two bytes left in the buffer, + // and those two bytes being enough to get the tag. This will be true for fields up to 4095. + if (state.bufferPos + 2 <= state.bufferSize) + { + int tmp = buffer[state.bufferPos++]; + if (tmp < 128) + { + state.lastTag = (uint)tmp; + } + else + { + int result = tmp & 0x7f; + if ((tmp = buffer[state.bufferPos++]) < 128) + { + result |= tmp << 7; + state.lastTag = (uint) result; + } + else + { + // Nope, rewind and go the potentially slow route. + state.bufferPos -= 2; + state.lastTag = ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); + } + } + } + else + { + if (SegmentedBufferHelper.IsAtEnd(ref buffer, ref state)) + { + state.lastTag = 0; + return 0; + } + + state.lastTag = ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); + } + if (WireFormat.GetTagFieldNumber(state.lastTag) == 0) + { + // If we actually read a tag with a field of 0, that's not a valid tag. + throw InvalidProtocolBufferException.InvalidTag(); + } + return state.lastTag; + } + + /// + /// Peeks at the next tag in the stream. If it matches , + /// the tag is consumed and the method returns true; otherwise, the + /// stream is left in the original position and the method returns false. + /// + public static bool MaybeConsumeTag(ref ReadOnlySpan buffer, ref ParserInternalState state, uint tag) + { + if (PeekTag(ref buffer, ref state) == tag) + { + state.hasNextTag = false; + return true; + } + return false; + } + + /// + /// Peeks at the next field tag. This is like calling , but the + /// tag is not consumed. (So a subsequent call to will return the + /// same value.) + /// + public static uint PeekTag(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + if (state.hasNextTag) + { + return state.nextTag; + } + + uint savedLast = state.lastTag; + state.nextTag = ParseTag(ref buffer, ref state); + state.hasNextTag = true; + state.lastTag = savedLast; // Undo the side effect of ReadTag + return state.nextTag; + } + + /// + /// Parses a raw varint. + /// + public static ulong ParseRawVarint64(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + if (state.bufferPos + 10 > state.bufferSize) + { + return ParseRawVarint64SlowPath(ref buffer, ref state); + } + + ulong result = buffer[state.bufferPos++]; + if (result < 128) + { + return result; + } + result &= 0x7f; + int shift = 7; + do + { + byte b = buffer[state.bufferPos++]; + result |= (ulong)(b & 0x7F) << shift; + if (b < 0x80) + { + return result; + } + shift += 7; + } + while (shift < 64); + + throw InvalidProtocolBufferException.MalformedVarint(); + } + + private static ulong ParseRawVarint64SlowPath(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + int shift = 0; + ulong result = 0; + do + { + byte b = ReadRawByte(ref buffer, ref state); + result |= (ulong)(b & 0x7F) << shift; + if (b < 0x80) + { + return result; + } + shift += 7; + } + while (shift < 64); + + throw InvalidProtocolBufferException.MalformedVarint(); + } + + /// + /// Parses a raw Varint. If larger than 32 bits, discard the upper bits. + /// This method is optimised for the case where we've got lots of data in the buffer. + /// That means we can check the size just once, then just read directly from the buffer + /// without constant rechecking of the buffer length. + /// + public static uint ParseRawVarint32(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + if (state.bufferPos + 5 > state.bufferSize) + { + return ParseRawVarint32SlowPath(ref buffer, ref state); + } + + int tmp = buffer[state.bufferPos++]; + if (tmp < 128) + { + return (uint)tmp; + } + int result = tmp & 0x7f; + if ((tmp = buffer[state.bufferPos++]) < 128) + { + result |= tmp << 7; + } + else + { + result |= (tmp & 0x7f) << 7; + if ((tmp = buffer[state.bufferPos++]) < 128) + { + result |= tmp << 14; + } + else + { + result |= (tmp & 0x7f) << 14; + if ((tmp = buffer[state.bufferPos++]) < 128) + { + result |= tmp << 21; + } + else + { + result |= (tmp & 0x7f) << 21; + result |= (tmp = buffer[state.bufferPos++]) << 28; + if (tmp >= 128) + { + // Discard upper 32 bits. + // Note that this has to use ReadRawByte() as we only ensure we've + // got at least 5 bytes at the start of the method. This lets us + // use the fast path in more cases, and we rarely hit this section of code. + for (int i = 0; i < 5; i++) + { + if (ReadRawByte(ref buffer, ref state) < 128) + { + return (uint) result; + } + } + throw InvalidProtocolBufferException.MalformedVarint(); + } + } + } + } + return (uint)result; + } + + private static uint ParseRawVarint32SlowPath(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + int tmp = ReadRawByte(ref buffer, ref state); + if (tmp < 128) + { + return (uint) tmp; + } + int result = tmp & 0x7f; + if ((tmp = ReadRawByte(ref buffer, ref state)) < 128) + { + result |= tmp << 7; + } + else + { + result |= (tmp & 0x7f) << 7; + if ((tmp = ReadRawByte(ref buffer, ref state)) < 128) + { + result |= tmp << 14; + } + else + { + result |= (tmp & 0x7f) << 14; + if ((tmp = ReadRawByte(ref buffer, ref state)) < 128) + { + result |= tmp << 21; + } + else + { + result |= (tmp & 0x7f) << 21; + result |= (tmp = ReadRawByte(ref buffer, ref state)) << 28; + if (tmp >= 128) + { + // Discard upper 32 bits. + for (int i = 0; i < 5; i++) + { + if (ReadRawByte(ref buffer, ref state) < 128) + { + return (uint) result; + } + } + throw InvalidProtocolBufferException.MalformedVarint(); + } + } + } + } + return (uint) result; + } + + /// + /// Parses a 32-bit little-endian integer. + /// + public static uint ParseRawLittleEndian32(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + const int uintLength = sizeof(uint); + const int ulongLength = sizeof(ulong); + if (state.bufferPos + ulongLength > state.bufferSize) + { + return ParseRawLittleEndian32SlowPath(ref buffer, ref state); + } + // ReadUInt32LittleEndian is many times slower than ReadUInt64LittleEndian (at least on some runtimes) + // so it's faster better to use ReadUInt64LittleEndian and truncate the result. + uint result = (uint) BinaryPrimitives.ReadUInt64LittleEndian(buffer.Slice(state.bufferPos, ulongLength)); + state.bufferPos += uintLength; + return result; + } + + private static uint ParseRawLittleEndian32SlowPath(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + uint b1 = ReadRawByte(ref buffer, ref state); + uint b2 = ReadRawByte(ref buffer, ref state); + uint b3 = ReadRawByte(ref buffer, ref state); + uint b4 = ReadRawByte(ref buffer, ref state); + return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24); + } + + /// + /// Parses a 64-bit little-endian integer. + /// + public static ulong ParseRawLittleEndian64(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + const int length = sizeof(ulong); + if (state.bufferPos + length > state.bufferSize) + { + return ParseRawLittleEndian64SlowPath(ref buffer, ref state); + } + ulong result = BinaryPrimitives.ReadUInt64LittleEndian(buffer.Slice(state.bufferPos, length)); + state.bufferPos += length; + return result; + } + + private static ulong ParseRawLittleEndian64SlowPath(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + ulong b1 = ReadRawByte(ref buffer, ref state); + ulong b2 = ReadRawByte(ref buffer, ref state); + ulong b3 = ReadRawByte(ref buffer, ref state); + ulong b4 = ReadRawByte(ref buffer, ref state); + ulong b5 = ReadRawByte(ref buffer, ref state); + ulong b6 = ReadRawByte(ref buffer, ref state); + ulong b7 = ReadRawByte(ref buffer, ref state); + ulong b8 = ReadRawByte(ref buffer, ref state); + return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24) + | (b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56); + } + + /// + /// Parses a double value. + /// + public static double ParseDouble(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + const int length = sizeof(double); + if (!BitConverter.IsLittleEndian || state.bufferPos + length > state.bufferSize) + { + return BitConverter.Int64BitsToDouble((long)ParseRawLittleEndian64(ref buffer, ref state)); + } + // ReadUnaligned uses processor architecture for endianness. + double result = Unsafe.ReadUnaligned(ref MemoryMarshal.GetReference(buffer.Slice(state.bufferPos, length))); + state.bufferPos += length; + return result; + } + + /// + /// Parses a float value. + /// + public static float ParseFloat(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + const int length = sizeof(float); + if (!BitConverter.IsLittleEndian || state.bufferPos + length > state.bufferSize) + { + return ParseFloatSlow(ref buffer, ref state); + } + // ReadUnaligned uses processor architecture for endianness. + float result = Unsafe.ReadUnaligned(ref MemoryMarshal.GetReference(buffer.Slice(state.bufferPos, length))); + state.bufferPos += length; + return result; + } + + private static unsafe float ParseFloatSlow(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + const int length = sizeof(float); + byte* stackBuffer = stackalloc byte[length]; + Span tempSpan = new Span(stackBuffer, length); + for (int i = 0; i < length; i++) + { + tempSpan[i] = ReadRawByte(ref buffer, ref state); + } + + // Content is little endian. Reverse if needed to match endianness of architecture. + if (!BitConverter.IsLittleEndian) + { + tempSpan.Reverse(); + } + return Unsafe.ReadUnaligned(ref MemoryMarshal.GetReference(tempSpan)); + } + + /// + /// Reads a fixed size of bytes from the input. + /// + /// + /// the end of the stream or the current limit was reached + /// + public static byte[] ReadRawBytes(ref ReadOnlySpan buffer, ref ParserInternalState state, int size) + { + if (size < 0) + { + throw InvalidProtocolBufferException.NegativeSize(); + } + + if (state.totalBytesRetired + state.bufferPos + size > state.currentLimit) + { + // Read to the end of the stream (up to the current limit) anyway. + SkipRawBytes(ref buffer, ref state, state.currentLimit - state.totalBytesRetired - state.bufferPos); + // Then fail. + throw InvalidProtocolBufferException.TruncatedMessage(); + } + + if (size <= state.bufferSize - state.bufferPos) + { + // We have all the bytes we need already. + byte[] bytes = new byte[size]; + buffer.Slice(state.bufferPos, size).CopyTo(bytes); + state.bufferPos += size; + return bytes; + } + else if (size < buffer.Length || size < state.segmentedBufferHelper.TotalLength) + { + // Reading more bytes than are in the buffer, but not an excessive number + // of bytes. We can safely allocate the resulting array ahead of time. + + // First copy what we have. + byte[] bytes = new byte[size]; + var bytesSpan = new Span(bytes); + int pos = state.bufferSize - state.bufferPos; + buffer.Slice(state.bufferPos, pos).CopyTo(bytesSpan.Slice(0, pos)); + state.bufferPos = state.bufferSize; + + // We want to use RefillBuffer() and then copy from the buffer into our + // byte array rather than reading directly into our byte array because + // the input may be unbuffered. + state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, true); + + while (size - pos > state.bufferSize) + { + buffer.Slice(0, state.bufferSize) + .CopyTo(bytesSpan.Slice(pos, state.bufferSize)); + pos += state.bufferSize; + state.bufferPos = state.bufferSize; + state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, true); + } + + buffer.Slice(0, size - pos) + .CopyTo(bytesSpan.Slice(pos, size - pos)); + state.bufferPos = size - pos; + + return bytes; + } + else + { + // The size is very large. For security reasons, we can't allocate the + // entire byte array yet. The size comes directly from the input, so a + // maliciously-crafted message could provide a bogus very large size in + // order to trick the app into allocating a lot of memory. We avoid this + // by allocating and reading only a small chunk at a time, so that the + // malicious message must actually *be* extremely large to cause + // problems. Meanwhile, we limit the allowed size of a message elsewhere. + + List chunks = new List(); + + int pos = state.bufferSize - state.bufferPos; + byte[] firstChunk = new byte[pos]; + buffer.Slice(state.bufferPos, pos).CopyTo(firstChunk); + chunks.Add(firstChunk); + state.bufferPos = state.bufferSize; + + // Read all the rest of the bytes we need. + int sizeLeft = size - pos; + while (sizeLeft > 0) + { + state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, true); + byte[] chunk = new byte[Math.Min(sizeLeft, state.bufferSize)]; + + buffer.Slice(0, chunk.Length) + .CopyTo(chunk); + state.bufferPos += chunk.Length; + sizeLeft -= chunk.Length; + chunks.Add(chunk); + } + + // OK, got everything. Now concatenate it all into one buffer. + byte[] bytes = new byte[size]; + int newPos = 0; + foreach (byte[] chunk in chunks) + { + Buffer.BlockCopy(chunk, 0, bytes, newPos, chunk.Length); + newPos += chunk.Length; + } + + // Done. + return bytes; + } + } + + /// + /// Reads and discards bytes. + /// + /// the end of the stream + /// or the current limit was reached + public static void SkipRawBytes(ref ReadOnlySpan buffer, ref ParserInternalState state, int size) + { + if (size < 0) + { + throw InvalidProtocolBufferException.NegativeSize(); + } + + if (state.totalBytesRetired + state.bufferPos + size > state.currentLimit) + { + // Read to the end of the stream anyway. + SkipRawBytes(ref buffer, ref state, state.currentLimit - state.totalBytesRetired - state.bufferPos); + // Then fail. + throw InvalidProtocolBufferException.TruncatedMessage(); + } + + if (size <= state.bufferSize - state.bufferPos) + { + // We have all the bytes we need already. + state.bufferPos += size; + } + else + { + // Skipping more bytes than are in the buffer. First skip what we have. + int pos = state.bufferSize - state.bufferPos; + state.bufferPos = state.bufferSize; + + // TODO: If our segmented buffer is backed by a Stream that is seekable, we could skip the bytes more efficiently + // by simply updating stream's Position property. This used to be supported in the past, but the support was dropped + // because it would make the segmentedBufferHelper more complex. Support can be reintroduced if needed. + state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, true); + + while (size - pos > state.bufferSize) + { + pos += state.bufferSize; + state.bufferPos = state.bufferSize; + state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, true); + } + + state.bufferPos = size - pos; + } + } + + /// + /// Reads a string field value from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string ReadString(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + int length = ParsingPrimitives.ParseLength(ref buffer, ref state); + return ParsingPrimitives.ReadRawString(ref buffer, ref state, length); + } + + /// + /// Reads a bytes field value from the input. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ByteString ReadBytes(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + int length = ParsingPrimitives.ParseLength(ref buffer, ref state); + return ByteString.AttachBytes(ParsingPrimitives.ReadRawBytes(ref buffer, ref state, length)); + } + + /// + /// Reads a UTF-8 string from the next "length" bytes. + /// + /// + /// the end of the stream or the current limit was reached + /// + [SecuritySafeCritical] + public static string ReadRawString(ref ReadOnlySpan buffer, ref ParserInternalState state, int length) + { + // No need to read any data for an empty string. + if (length == 0) + { + return string.Empty; + } + + if (length < 0) + { + throw InvalidProtocolBufferException.NegativeSize(); + } + +#if GOOGLE_PROTOBUF_SUPPORT_FAST_STRING + if (length <= state.bufferSize - state.bufferPos && length > 0) + { + // Fast path: all bytes to decode appear in the same span. + ReadOnlySpan data = buffer.Slice(state.bufferPos, length); + + string value; + unsafe + { + fixed (byte* sourceBytes = &MemoryMarshal.GetReference(data)) + { + value = CodedOutputStream.Utf8Encoding.GetString(sourceBytes, length); + } + } + + state.bufferPos += length; + return value; + } +#endif + + var decoder = CodedOutputStream.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) + // whenever the buffer is backed by a byte array (and avoid creating a new byte array), but the problem is + // there is no way to get the underlying byte array from a span. + + // TODO: in case the string spans multiple buffer segments, creating a char[] and decoding into it and then + // 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); + } + + [SecuritySafeCritical] + private static byte ReadRawByte(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + if (state.bufferPos == state.bufferSize) + { + state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, true); + } + return buffer[state.bufferPos++]; + } + + /// + /// Reads a varint from the input one byte at a time, so that it does not + /// read any bytes after the end of the varint. If you simply wrapped the + /// stream in a CodedInputStream and used ReadRawVarint32(Stream) + /// then you would probably end up reading past the end of the varint since + /// CodedInputStream buffers its input. + /// + /// + /// + public static uint ReadRawVarint32(Stream input) + { + int result = 0; + int offset = 0; + for (; offset < 32; offset += 7) + { + int b = input.ReadByte(); + if (b == -1) + { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + result |= (b & 0x7f) << offset; + if ((b & 0x80) == 0) + { + return (uint) result; + } + } + // Keep reading up to 64 bits. + for (; offset < 64; offset += 7) + { + int b = input.ReadByte(); + if (b == -1) + { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + if ((b & 0x80) == 0) + { + return (uint) result; + } + } + throw InvalidProtocolBufferException.MalformedVarint(); + } + + /// + /// Decode 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 32 bits to be varint encoded, thus always taking + /// 5 bytes on the wire.) + /// + public static int DecodeZigZag32(uint n) + { + return (int)(n >> 1) ^ -(int)(n & 1); + } + + /// + /// Decode 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 long DecodeZigZag64(ulong n) + { + return (long)(n >> 1) ^ -(long)(n & 1); + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/ParsingPrimitivesMessages.cs b/csharp/src/Google.Protobuf/ParsingPrimitivesMessages.cs new file mode 100644 index 000000000000..b7097a2ad04f --- /dev/null +++ b/csharp/src/Google.Protobuf/ParsingPrimitivesMessages.cs @@ -0,0 +1,229 @@ +#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 +{ + /// + /// Reading and skipping messages / groups + /// + [SecuritySafeCritical] + internal static class ParsingPrimitivesMessages + { + public static void SkipLastField(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + if (state.lastTag == 0) + { + throw new InvalidOperationException("SkipLastField cannot be called at the end of a stream"); + } + switch (WireFormat.GetTagWireType(state.lastTag)) + { + case WireFormat.WireType.StartGroup: + SkipGroup(ref buffer, ref state, state.lastTag); + break; + case WireFormat.WireType.EndGroup: + throw new InvalidProtocolBufferException( + "SkipLastField called on an end-group tag, indicating that the corresponding start-group was missing"); + case WireFormat.WireType.Fixed32: + ParsingPrimitives.ParseRawLittleEndian32(ref buffer, ref state); + break; + case WireFormat.WireType.Fixed64: + ParsingPrimitives.ParseRawLittleEndian64(ref buffer, ref state); + break; + case WireFormat.WireType.LengthDelimited: + var length = ParsingPrimitives.ParseLength(ref buffer, ref state); + ParsingPrimitives.SkipRawBytes(ref buffer, ref state, length); + break; + case WireFormat.WireType.Varint: + ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); + break; + } + } + + /// + /// Skip a group. + /// + public static void SkipGroup(ref ReadOnlySpan buffer, ref ParserInternalState state, uint startGroupTag) + { + // Note: Currently we expect this to be the way that groups are read. We could put the recursion + // depth changes into the ReadTag method instead, potentially... + state.recursionDepth++; + if (state.recursionDepth >= state.recursionLimit) + { + throw InvalidProtocolBufferException.RecursionLimitExceeded(); + } + uint tag; + while (true) + { + tag = ParsingPrimitives.ParseTag(ref buffer, ref state); + if (tag == 0) + { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + // Can't call SkipLastField for this case- that would throw. + if (WireFormat.GetTagWireType(tag) == WireFormat.WireType.EndGroup) + { + break; + } + // This recursion will allow us to handle nested groups. + SkipLastField(ref buffer, ref state); + } + int startField = WireFormat.GetTagFieldNumber(startGroupTag); + int endField = WireFormat.GetTagFieldNumber(tag); + if (startField != endField) + { + throw new InvalidProtocolBufferException( + $"Mismatched end-group tag. Started with field {startField}; ended with field {endField}"); + } + state.recursionDepth--; + } + + public static void ReadMessage(ref ParseContext ctx, IMessage message) + { + int length = ParsingPrimitives.ParseLength(ref ctx.buffer, ref ctx.state); + if (ctx.state.recursionDepth >= ctx.state.recursionLimit) + { + throw InvalidProtocolBufferException.RecursionLimitExceeded(); + } + int oldLimit = SegmentedBufferHelper.PushLimit(ref ctx.state, length); + ++ctx.state.recursionDepth; + + ReadRawMessage(ref ctx, message); + + CheckReadEndOfStreamTag(ref ctx.state); + // Check that we've read exactly as much data as expected. + if (!SegmentedBufferHelper.IsReachedLimit(ref ctx.state)) + { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + --ctx.state.recursionDepth; + SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit); + } + + public static void ReadGroup(ref ParseContext ctx, IMessage message) + { + if (ctx.state.recursionDepth >= ctx.state.recursionLimit) + { + throw InvalidProtocolBufferException.RecursionLimitExceeded(); + } + ++ctx.state.recursionDepth; + + uint tag = ctx.state.lastTag; + int fieldNumber = WireFormat.GetTagFieldNumber(tag); + ReadRawMessage(ref ctx, message); + CheckLastTagWas(ref ctx.state, WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup)); + + --ctx.state.recursionDepth; + } + + public static void ReadGroup(ref ParseContext ctx, int fieldNumber, UnknownFieldSet set) + { + if (ctx.state.recursionDepth >= ctx.state.recursionLimit) + { + throw InvalidProtocolBufferException.RecursionLimitExceeded(); + } + ++ctx.state.recursionDepth; + + set.MergeGroupFrom(ref ctx); + CheckLastTagWas(ref ctx.state, WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup)); + + --ctx.state.recursionDepth; + } + + public static void ReadRawMessage(ref ParseContext ctx, IMessage message) + { + if (message is IBufferMessage bufferMessage) + { + bufferMessage.InternalMergeFrom(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 InternalMergeFrom method that takes a ParseContext. + // With a slight performance overhead, we can still parse this message just fine, + // but we need to find the original CodedInputStream instance that initiated this + // parsing 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 InternalMergeFrom method we need. + + if (ctx.state.CodedInputStream == null) + { + // This can only happen when the parsing started without providing a CodedInputStream instance + // (e.g. ParseContext was created directly from a ReadOnlySequence). + // 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 ParseContext support (and fail otherwise). + throw new InvalidProtocolBufferException($"Message {message.GetType().Name} doesn't provide the generated method that enables ParseContext-based parsing. You might need to regenerate the generated protobuf code."); + } + + ctx.CopyStateTo(ctx.state.CodedInputStream); + try + { + // fallback parse using the CodedInputStream that started current parsing tree + message.MergeFrom(ctx.state.CodedInputStream); + } + finally + { + ctx.LoadStateFrom(ctx.state.CodedInputStream); + } + } + } + + /// + /// Verifies that the last call to ReadTag() returned tag 0 - in other words, + /// we've reached the end of the stream when we expected to. + /// + /// The + /// tag read was not the one specified + public static void CheckReadEndOfStreamTag(ref ParserInternalState state) + { + if (state.lastTag != 0) + { + throw InvalidProtocolBufferException.MoreDataAvailable(); + } + } + + private static void CheckLastTagWas(ref ParserInternalState state, uint expectedTag) + { + if (state.lastTag != expectedTag) { + throw InvalidProtocolBufferException.InvalidEndTag(); + } + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/ParsingPrimitivesWrappers.cs b/csharp/src/Google.Protobuf/ParsingPrimitivesWrappers.cs new file mode 100644 index 000000000000..126306490a09 --- /dev/null +++ b/csharp/src/Google.Protobuf/ParsingPrimitivesWrappers.cs @@ -0,0 +1,353 @@ +#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 +{ + /// + /// Fast parsing primitives for wrapper types + /// + [SecuritySafeCritical] + internal static class ParsingPrimitivesWrappers + { + internal static float? ReadFloatWrapperLittleEndian(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + // length:1 + tag:1 + value:4 = 6 bytes + if (state.bufferPos + 6 <= state.bufferSize) + { + // The entire wrapper message is already contained in `buffer`. + int length = buffer[state.bufferPos]; + if (length == 0) + { + state.bufferPos++; + return 0F; + } + // tag:1 + value:4 = length of 5 bytes + // field=1, type=32-bit = tag of 13 + if (length != 5 || buffer[state.bufferPos + 1] != 13) + { + return ReadFloatWrapperSlow(ref buffer, ref state); + } + state.bufferPos += 2; + return ParsingPrimitives.ParseFloat(ref buffer, ref state); + } + else + { + return ReadFloatWrapperSlow(ref buffer, ref state); + } + } + + internal static float? ReadFloatWrapperSlow(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + int length = ParsingPrimitives.ParseLength(ref buffer, ref state); + if (length == 0) + { + return 0F; + } + int finalBufferPos = state.totalBytesRetired + state.bufferPos + length; + float result = 0F; + do + { + // field=1, type=32-bit = tag of 13 + if (ParsingPrimitives.ParseTag(ref buffer, ref state) == 13) + { + result = ParsingPrimitives.ParseFloat(ref buffer, ref state); + } + else + { + ParsingPrimitivesMessages.SkipLastField(ref buffer, ref state); + } + } + while (state.totalBytesRetired + state.bufferPos < finalBufferPos); + return result; + } + + internal static double? ReadDoubleWrapperLittleEndian(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + // length:1 + tag:1 + value:8 = 10 bytes + if (state.bufferPos + 10 <= state.bufferSize) + { + // The entire wrapper message is already contained in `buffer`. + int length = buffer[state.bufferPos]; + if (length == 0) + { + state.bufferPos++; + return 0D; + } + // tag:1 + value:8 = length of 9 bytes + // field=1, type=64-bit = tag of 9 + if (length != 9 || buffer[state.bufferPos + 1] != 9) + { + return ReadDoubleWrapperSlow(ref buffer, ref state); + } + state.bufferPos += 2; + return ParsingPrimitives.ParseDouble(ref buffer, ref state); + } + else + { + return ReadDoubleWrapperSlow(ref buffer, ref state); + } + } + + internal static double? ReadDoubleWrapperSlow(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + int length = ParsingPrimitives.ParseLength(ref buffer, ref state); + if (length == 0) + { + return 0D; + } + int finalBufferPos = state.totalBytesRetired + state.bufferPos + length; + double result = 0D; + do + { + // field=1, type=64-bit = tag of 9 + if (ParsingPrimitives.ParseTag(ref buffer, ref state) == 9) + { + result = ParsingPrimitives.ParseDouble(ref buffer, ref state); + } + else + { + ParsingPrimitivesMessages.SkipLastField(ref buffer, ref state); + } + } + while (state.totalBytesRetired + state.bufferPos < finalBufferPos); + return result; + } + + internal static bool? ReadBoolWrapper(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + return ReadUInt64Wrapper(ref buffer, ref state) != 0; + } + + internal static uint? ReadUInt32Wrapper(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + // length:1 + tag:1 + value:5(varint32-max) = 7 bytes + if (state.bufferPos + 7 <= state.bufferSize) + { + // The entire wrapper message is already contained in `buffer`. + int pos0 = state.bufferPos; + int length = buffer[state.bufferPos++]; + if (length == 0) + { + return 0; + } + // Length will always fit in a single byte. + if (length >= 128) + { + state.bufferPos = pos0; + return ReadUInt32WrapperSlow(ref buffer, ref state); + } + int finalBufferPos = state.bufferPos + length; + // field=1, type=varint = tag of 8 + if (buffer[state.bufferPos++] != 8) + { + state.bufferPos = pos0; + return ReadUInt32WrapperSlow(ref buffer, ref state); + } + var result = ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); + // Verify this message only contained a single field. + if (state.bufferPos != finalBufferPos) + { + state.bufferPos = pos0; + return ReadUInt32WrapperSlow(ref buffer, ref state); + } + return result; + } + else + { + return ReadUInt32WrapperSlow(ref buffer, ref state); + } + } + + internal static uint? ReadUInt32WrapperSlow(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + int length = ParsingPrimitives.ParseLength(ref buffer, ref state); + if (length == 0) + { + return 0; + } + int finalBufferPos = state.totalBytesRetired + state.bufferPos + length; + uint result = 0; + do + { + // field=1, type=varint = tag of 8 + if (ParsingPrimitives.ParseTag(ref buffer, ref state) == 8) + { + result = ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); + } + else + { + ParsingPrimitivesMessages.SkipLastField(ref buffer, ref state); + } + } + while (state.totalBytesRetired + state.bufferPos < finalBufferPos); + return result; + } + + internal static int? ReadInt32Wrapper(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + return (int?)ReadUInt32Wrapper(ref buffer, ref state); + } + + internal static ulong? ReadUInt64Wrapper(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + // field=1, type=varint = tag of 8 + const int expectedTag = 8; + // length:1 + tag:1 + value:10(varint64-max) = 12 bytes + if (state.bufferPos + 12 <= state.bufferSize) + { + // The entire wrapper message is already contained in `buffer`. + int pos0 = state.bufferPos; + int length = buffer[state.bufferPos++]; + if (length == 0) + { + return 0L; + } + // Length will always fit in a single byte. + if (length >= 128) + { + state.bufferPos = pos0; + return ReadUInt64WrapperSlow(ref buffer, ref state); + } + int finalBufferPos = state.bufferPos + length; + if (buffer[state.bufferPos++] != expectedTag) + { + state.bufferPos = pos0; + return ReadUInt64WrapperSlow(ref buffer, ref state); + } + var result = ParsingPrimitives.ParseRawVarint64(ref buffer, ref state); + // Verify this message only contained a single field. + if (state.bufferPos != finalBufferPos) + { + state.bufferPos = pos0; + return ReadUInt64WrapperSlow(ref buffer, ref state); + } + return result; + } + else + { + return ReadUInt64WrapperSlow(ref buffer, ref state); + } + } + + internal static ulong? ReadUInt64WrapperSlow(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + // field=1, type=varint = tag of 8 + const int expectedTag = 8; + int length = ParsingPrimitives.ParseLength(ref buffer, ref state); + if (length == 0) + { + return 0L; + } + int finalBufferPos = state.totalBytesRetired + state.bufferPos + length; + ulong result = 0L; + do + { + if (ParsingPrimitives.ParseTag(ref buffer, ref state) == expectedTag) + { + result = ParsingPrimitives.ParseRawVarint64(ref buffer, ref state); + } + else + { + ParsingPrimitivesMessages.SkipLastField(ref buffer, ref state); + } + } + while (state.totalBytesRetired + state.bufferPos < finalBufferPos); + return result; + } + + internal static long? ReadInt64Wrapper(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + return (long?)ReadUInt64Wrapper(ref buffer, ref state); + } + + internal static float? ReadFloatWrapperLittleEndian(ref ParseContext ctx) + { + return ParsingPrimitivesWrappers.ReadFloatWrapperLittleEndian(ref ctx.buffer, ref ctx.state); + } + + internal static float? ReadFloatWrapperSlow(ref ParseContext ctx) + { + return ParsingPrimitivesWrappers.ReadFloatWrapperSlow(ref ctx.buffer, ref ctx.state); + } + + internal static double? ReadDoubleWrapperLittleEndian(ref ParseContext ctx) + { + return ParsingPrimitivesWrappers.ReadDoubleWrapperLittleEndian(ref ctx.buffer, ref ctx.state); + } + + internal static double? ReadDoubleWrapperSlow(ref ParseContext ctx) + { + return ParsingPrimitivesWrappers.ReadDoubleWrapperSlow(ref ctx.buffer, ref ctx.state); + } + + internal static bool? ReadBoolWrapper(ref ParseContext ctx) + { + return ParsingPrimitivesWrappers.ReadBoolWrapper(ref ctx.buffer, ref ctx.state); + } + + internal static uint? ReadUInt32Wrapper(ref ParseContext ctx) + { + return ParsingPrimitivesWrappers.ReadUInt32Wrapper(ref ctx.buffer, ref ctx.state); + } + + internal static int? ReadInt32Wrapper(ref ParseContext ctx) + { + return ParsingPrimitivesWrappers.ReadInt32Wrapper(ref ctx.buffer, ref ctx.state); + } + + internal static ulong? ReadUInt64Wrapper(ref ParseContext ctx) + { + return ParsingPrimitivesWrappers.ReadUInt64Wrapper(ref ctx.buffer, ref ctx.state); + } + + internal static ulong? ReadUInt64WrapperSlow(ref ParseContext ctx) + { + return ParsingPrimitivesWrappers.ReadUInt64WrapperSlow(ref ctx.buffer, ref ctx.state); + } + + internal static long? ReadInt64Wrapper(ref ParseContext ctx) + { + return ParsingPrimitivesWrappers.ReadInt64Wrapper(ref ctx.buffer, ref ctx.state); + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs b/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs index 9b179bd7cd60..130bcf00041d 100644 --- a/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs +++ b/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs @@ -47,3 +47,10 @@ "981207041fd5b2da3b498346fcfcd94910d52f25537c4a43ce3fbe17dc7d43e6cbdb4d8f1242dc" + "b6bd9b5906be74da8daa7d7280f97130f318a16c07baf118839b156299a48522f9fae2371c9665" + "c5ae9cb6")] + +[assembly: InternalsVisibleTo("Google.Protobuf.Benchmarks, PublicKey=" + + "002400000480000094000000060200000024000052534131000400000100010025800fbcfc63a1" + + "7c66b303aae80b03a6beaa176bb6bef883be436f2a1579edd80ce23edf151a1f4ced97af83abcd" + + "981207041fd5b2da3b498346fcfcd94910d52f25537c4a43ce3fbe17dc7d43e6cbdb4d8f1242dc" + + "b6bd9b5906be74da8daa7d7280f97130f318a16c07baf118839b156299a48522f9fae2371c9665" + + "c5ae9cb6")] diff --git a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs index c9ba6328b9fb..ef3f1b6b6650 100644 --- a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs @@ -194,7 +194,7 @@ public static partial class DescriptorReflection { /// The protocol compiler can output a FileDescriptorSet containing the .proto /// files it parses. /// - public sealed partial class FileDescriptorSet : pb::IMessage { + public sealed partial class FileDescriptorSet : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FileDescriptorSet()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -299,14 +299,19 @@ public sealed partial class FileDescriptorSet : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { - file_.AddEntriesFrom(input, _repeated_file_codec); + file_.AddEntriesFrom(ref input, _repeated_file_codec); break; } } @@ -318,7 +323,7 @@ public sealed partial class FileDescriptorSet : pb::IMessage /// /// Describes a complete .proto file. /// - public sealed partial class FileDescriptorProto : pb::IMessage { + public sealed partial class FileDescriptorProto : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FileDescriptorProto()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -730,11 +735,16 @@ public sealed partial class FileDescriptorProto : pb::IMessage /// Describes a message type. /// - public sealed partial class DescriptorProto : pb::IMessage { + public sealed partial class DescriptorProto : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DescriptorProto()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1095,34 +1105,39 @@ public sealed partial class DescriptorProto : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Name = input.ReadString(); break; } case 18: { - field_.AddEntriesFrom(input, _repeated_field_codec); + field_.AddEntriesFrom(ref input, _repeated_field_codec); break; } case 26: { - nestedType_.AddEntriesFrom(input, _repeated_nestedType_codec); + nestedType_.AddEntriesFrom(ref input, _repeated_nestedType_codec); break; } case 34: { - enumType_.AddEntriesFrom(input, _repeated_enumType_codec); + enumType_.AddEntriesFrom(ref input, _repeated_enumType_codec); break; } case 42: { - extensionRange_.AddEntriesFrom(input, _repeated_extensionRange_codec); + extensionRange_.AddEntriesFrom(ref input, _repeated_extensionRange_codec); break; } case 50: { - extension_.AddEntriesFrom(input, _repeated_extension_codec); + extension_.AddEntriesFrom(ref input, _repeated_extension_codec); break; } case 58: { @@ -1133,15 +1148,15 @@ public sealed partial class DescriptorProto : pb::IMessage { break; } case 66: { - oneofDecl_.AddEntriesFrom(input, _repeated_oneofDecl_codec); + oneofDecl_.AddEntriesFrom(ref input, _repeated_oneofDecl_codec); break; } case 74: { - reservedRange_.AddEntriesFrom(input, _repeated_reservedRange_codec); + reservedRange_.AddEntriesFrom(ref input, _repeated_reservedRange_codec); break; } case 82: { - reservedName_.AddEntriesFrom(input, _repeated_reservedName_codec); + reservedName_.AddEntriesFrom(ref input, _repeated_reservedName_codec); break; } } @@ -1152,7 +1167,7 @@ public sealed partial class DescriptorProto : pb::IMessage { /// Container for nested types declared in the DescriptorProto message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class ExtensionRange : pb::IMessage { + public sealed partial class ExtensionRange : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ExtensionRange()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -1360,11 +1375,16 @@ public sealed partial class ExtensionRange : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Start = input.ReadInt32(); @@ -1392,7 +1412,7 @@ public sealed partial class ExtensionRange : pb::IMessage { /// fields or extension ranges in the same message. Reserved ranges may /// not overlap. /// - public sealed partial class ReservedRange : pb::IMessage { + public sealed partial class ReservedRange : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ReservedRange()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -1563,11 +1583,16 @@ public sealed partial class ReservedRange : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Start = input.ReadInt32(); @@ -1588,7 +1613,7 @@ public sealed partial class ReservedRange : pb::IMessage { } - public sealed partial class ExtensionRangeOptions : pb::IExtendableMessage { + public sealed partial class ExtensionRangeOptions : pb::IExtendableMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ExtensionRangeOptions()); private pb::UnknownFieldSet _unknownFields; internal pb::ExtensionSet _extensions; @@ -1712,16 +1737,21 @@ public sealed partial class ExtensionRangeOptions : pb::IExtendableMessage /// Describes a field within a message. /// - public sealed partial class FieldDescriptorProto : pb::IMessage { + public sealed partial class FieldDescriptorProto : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FieldDescriptorProto()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -2303,11 +2333,16 @@ public sealed partial class FieldDescriptorProto : pb::IMessage /// Describes a oneof. /// - public sealed partial class OneofDescriptorProto : pb::IMessage { + public sealed partial class OneofDescriptorProto : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneofDescriptorProto()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2594,11 +2629,16 @@ public sealed partial class OneofDescriptorProto : pb::IMessage /// Describes an enum type. /// - public sealed partial class EnumDescriptorProto : pb::IMessage { + public sealed partial class EnumDescriptorProto : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new EnumDescriptorProto()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -2839,18 +2879,23 @@ public sealed partial class EnumDescriptorProto : pb::IMessage - public sealed partial class EnumReservedRange : pb::IMessage { + public sealed partial class EnumReservedRange : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new EnumReservedRange()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -3055,11 +3100,16 @@ public sealed partial class EnumReservedRange : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Start = input.ReadInt32(); @@ -3083,7 +3133,7 @@ public sealed partial class EnumReservedRange : pb::IMessage /// /// Describes a value within an enum. /// - public sealed partial class EnumValueDescriptorProto : pb::IMessage { + public sealed partial class EnumValueDescriptorProto : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new EnumValueDescriptorProto()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -3284,11 +3334,16 @@ public sealed partial class EnumValueDescriptorProto : pb::IMessage /// Describes a service. /// - public sealed partial class ServiceDescriptorProto : pb::IMessage { + public sealed partial class ServiceDescriptorProto : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ServiceDescriptorProto()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -3492,18 +3547,23 @@ public sealed partial class ServiceDescriptorProto : pb::IMessage /// Describes a method of a service. /// - public sealed partial class MethodDescriptorProto : pb::IMessage { + public sealed partial class MethodDescriptorProto : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MethodDescriptorProto()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -3842,11 +3902,16 @@ public sealed partial class MethodDescriptorProto : pb::IMessage { + public sealed partial class FileOptions : pb::IExtendableMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FileOptions()); private pb::UnknownFieldSet _unknownFields; internal pb::ExtensionSet _extensions; @@ -4834,12 +4899,17 @@ public sealed partial class FileOptions : pb::IExtendableMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); } break; case 10: { @@ -4923,7 +4993,7 @@ public sealed partial class FileOptions : pb::IExtendableMessage { break; } case 7994: { - uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec); + uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec); break; } } @@ -4979,7 +5049,7 @@ public enum OptimizeMode { } - public sealed partial class MessageOptions : pb::IExtendableMessage { + public sealed partial class MessageOptions : pb::IExtendableMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MessageOptions()); private pb::UnknownFieldSet _unknownFields; internal pb::ExtensionSet _extensions; @@ -5307,12 +5377,17 @@ public sealed partial class MessageOptions : pb::IExtendableMessage { + public sealed partial class FieldOptions : pb::IExtendableMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FieldOptions()); private pb::UnknownFieldSet _unknownFields; internal pb::ExtensionSet _extensions; @@ -5775,12 +5850,17 @@ public sealed partial class FieldOptions : pb::IExtendableMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); } break; case 8: { @@ -5808,7 +5888,7 @@ public sealed partial class FieldOptions : pb::IExtendableMessage break; } case 7994: { - uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec); + uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec); break; } } @@ -5870,7 +5950,7 @@ public enum JSType { } - public sealed partial class OneofOptions : pb::IExtendableMessage { + public sealed partial class OneofOptions : pb::IExtendableMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new OneofOptions()); private pb::UnknownFieldSet _unknownFields; internal pb::ExtensionSet _extensions; @@ -5994,16 +6074,21 @@ public sealed partial class OneofOptions : pb::IExtendableMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); } break; case 7994: { - uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec); + uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec); break; } } @@ -6034,7 +6119,7 @@ public sealed partial class OneofOptions : pb::IExtendableMessage } - public sealed partial class EnumOptions : pb::IExtendableMessage { + public sealed partial class EnumOptions : pb::IExtendableMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new EnumOptions()); private pb::UnknownFieldSet _unknownFields; internal pb::ExtensionSet _extensions; @@ -6244,12 +6329,17 @@ public sealed partial class EnumOptions : pb::IExtendableMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { uint tag; while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); } break; case 16: { @@ -6261,7 +6351,7 @@ public sealed partial class EnumOptions : pb::IExtendableMessage { break; } case 7994: { - uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec); + uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec); break; } } @@ -6292,7 +6382,7 @@ public sealed partial class EnumOptions : pb::IExtendableMessage { } - public sealed partial class EnumValueOptions : pb::IExtendableMessage { + public sealed partial class EnumValueOptions : pb::IExtendableMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new EnumValueOptions()); private pb::UnknownFieldSet _unknownFields; internal pb::ExtensionSet _extensions; @@ -6461,12 +6551,17 @@ public sealed partial class EnumValueOptions : pb::IExtendableMessage { + public sealed partial class ServiceOptions : pb::IExtendableMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ServiceOptions()); private pb::UnknownFieldSet _unknownFields; internal pb::ExtensionSet _extensions; @@ -6674,12 +6769,17 @@ public sealed partial class ServiceOptions : pb::IExtendableMessage { + public sealed partial class MethodOptions : pb::IExtendableMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MethodOptions()); private pb::UnknownFieldSet _unknownFields; internal pb::ExtensionSet _extensions; @@ -6924,12 +7024,17 @@ public sealed partial class MethodOptions : pb::IExtendableMessage - public sealed partial class UninterpretedOption : pb::IMessage { + public sealed partial class UninterpretedOption : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new UninterpretedOption()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -7334,14 +7439,19 @@ public sealed partial class UninterpretedOption : pb::IMessage - public sealed partial class NamePart : pb::IMessage { + public sealed partial class NamePart : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NamePart()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -7547,11 +7657,16 @@ public sealed partial class NamePart : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { NamePart_ = input.ReadString(); @@ -7576,7 +7691,7 @@ public sealed partial class NamePart : pb::IMessage { /// Encapsulates information about the original source file from which a /// FileDescriptorProto was generated. /// - public sealed partial class SourceCodeInfo : pb::IMessage { + public sealed partial class SourceCodeInfo : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SourceCodeInfo()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -7726,14 +7841,19 @@ public sealed partial class SourceCodeInfo : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { - location_.AddEntriesFrom(input, _repeated_location_codec); + location_.AddEntriesFrom(ref input, _repeated_location_codec); break; } } @@ -7744,7 +7864,7 @@ public sealed partial class SourceCodeInfo : pb::IMessage { /// Container for nested types declared in the SourceCodeInfo message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class Location : pb::IMessage { + public sealed partial class Location : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Location()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -8034,20 +8154,25 @@ public sealed partial class Location : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: case 8: { - path_.AddEntriesFrom(input, _repeated_path_codec); + path_.AddEntriesFrom(ref input, _repeated_path_codec); break; } case 18: case 16: { - span_.AddEntriesFrom(input, _repeated_span_codec); + span_.AddEntriesFrom(ref input, _repeated_span_codec); break; } case 26: { @@ -8059,7 +8184,7 @@ public sealed partial class Location : pb::IMessage { break; } case 50: { - leadingDetachedComments_.AddEntriesFrom(input, _repeated_leadingDetachedComments_codec); + leadingDetachedComments_.AddEntriesFrom(ref input, _repeated_leadingDetachedComments_codec); break; } } @@ -8078,7 +8203,7 @@ public sealed partial class Location : pb::IMessage { /// file. A GeneratedCodeInfo message is associated with only one generated /// source file, but may contain references to different source .proto files. /// - public sealed partial class GeneratedCodeInfo : pb::IMessage { + public sealed partial class GeneratedCodeInfo : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new GeneratedCodeInfo()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -8187,14 +8312,19 @@ public sealed partial class GeneratedCodeInfo : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { - annotation_.AddEntriesFrom(input, _repeated_annotation_codec); + annotation_.AddEntriesFrom(ref input, _repeated_annotation_codec); break; } } @@ -8205,7 +8335,7 @@ public sealed partial class GeneratedCodeInfo : pb::IMessage /// Container for nested types declared in the GeneratedCodeInfo message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static partial class Types { - public sealed partial class Annotation : pb::IMessage { + public sealed partial class Annotation : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Annotation()); private pb::UnknownFieldSet _unknownFields; private int _hasBits0; @@ -8438,15 +8568,20 @@ public sealed partial class Annotation : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: case 8: { - path_.AddEntriesFrom(input, _repeated_path_codec); + path_.AddEntriesFrom(ref input, _repeated_path_codec); break; } case 18: { diff --git a/csharp/src/Google.Protobuf/SegmentedBufferHelper.cs b/csharp/src/Google.Protobuf/SegmentedBufferHelper.cs new file mode 100644 index 000000000000..b5441d34211d --- /dev/null +++ b/csharp/src/Google.Protobuf/SegmentedBufferHelper.cs @@ -0,0 +1,296 @@ +#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 reading from a stream / read only sequence. + /// Parsing from the buffer is a loop of reading from current buffer / refreshing the buffer once done. + /// + [SecuritySafeCritical] + internal struct SegmentedBufferHelper + { + private int? totalLength; + private ReadOnlySequence.Enumerator readOnlySequenceEnumerator; + private CodedInputStream codedInputStream; + + /// + /// Initialize an instance with a coded input 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(CodedInputStream codedInputStream, out SegmentedBufferHelper instance) + { + instance.totalLength = codedInputStream.InternalInputStream == null ? (int?)codedInputStream.InternalBuffer.Length : null; + instance.readOnlySequenceEnumerator = default; + instance.codedInputStream = codedInputStream; + } + + /// + /// Initialize an instance with a read only sequence. + /// 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(ReadOnlySequence sequence, out SegmentedBufferHelper instance, out ReadOnlySpan firstSpan) + { + instance.codedInputStream = null; + if (sequence.IsSingleSegment) + { + firstSpan = sequence.First.Span; + instance.totalLength = firstSpan.Length; + instance.readOnlySequenceEnumerator = default; + } + else + { + instance.readOnlySequenceEnumerator = sequence.GetEnumerator(); + instance.totalLength = (int) sequence.Length; + + // set firstSpan to the first segment + instance.readOnlySequenceEnumerator.MoveNext(); + firstSpan = instance.readOnlySequenceEnumerator.Current.Span; + } + } + + public bool RefillBuffer(ref ReadOnlySpan buffer, ref ParserInternalState state, bool mustSucceed) + { + if (codedInputStream != null) + { + return RefillFromCodedInputStream(ref buffer, ref state, mustSucceed); + } + else + { + return RefillFromReadOnlySequence(ref buffer, ref state, mustSucceed); + } + } + + public int? TotalLength => totalLength; + + public CodedInputStream CodedInputStream => codedInputStream; + + /// + /// Sets currentLimit to (current position) + byteLimit. This is called + /// when descending into a length-delimited embedded message. The previous + /// limit is returned. + /// + /// The old limit. + public static int PushLimit(ref ParserInternalState state, int byteLimit) + { + if (byteLimit < 0) + { + throw InvalidProtocolBufferException.NegativeSize(); + } + byteLimit += state.totalBytesRetired + state.bufferPos; + int oldLimit = state.currentLimit; + if (byteLimit > oldLimit) + { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + state.currentLimit = byteLimit; + + RecomputeBufferSizeAfterLimit(ref state); + + return oldLimit; + } + + /// + /// Discards the current limit, returning the previous limit. + /// + public static void PopLimit(ref ParserInternalState state, int oldLimit) + { + state.currentLimit = oldLimit; + RecomputeBufferSizeAfterLimit(ref state); + } + + /// + /// Returns whether or not all the data before the limit has been read. + /// + /// + public static bool IsReachedLimit(ref ParserInternalState state) + { + if (state.currentLimit == int.MaxValue) + { + return false; + } + int currentAbsolutePosition = state.totalBytesRetired + state.bufferPos; + return currentAbsolutePosition >= state.currentLimit; + } + + /// + /// Returns true if the stream has reached the end of the input. This is the + /// case if either the end of the underlying input source has been reached or + /// the stream has reached a limit created using PushLimit. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsAtEnd(ref ReadOnlySpan buffer, ref ParserInternalState state) + { + return state.bufferPos == state.bufferSize && !state.segmentedBufferHelper.RefillBuffer(ref buffer, ref state, false); + } + + private bool RefillFromReadOnlySequence(ref ReadOnlySpan buffer, ref ParserInternalState state, bool mustSucceed) + { + CheckCurrentBufferIsEmpty(ref state); + + if (state.totalBytesRetired + state.bufferSize == state.currentLimit) + { + // Oops, we hit a limit. + if (mustSucceed) + { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + else + { + return false; + } + } + + state.totalBytesRetired += state.bufferSize; + + state.bufferPos = 0; + state.bufferSize = 0; + while (readOnlySequenceEnumerator.MoveNext()) + { + buffer = readOnlySequenceEnumerator.Current.Span; + state.bufferSize = buffer.Length; + if (buffer.Length != 0) + { + break; + } + } + + if (state.bufferSize == 0) + { + if (mustSucceed) + { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + else + { + return false; + } + } + else + { + RecomputeBufferSizeAfterLimit(ref state); + int totalBytesRead = + state.totalBytesRetired + state.bufferSize + state.bufferSizeAfterLimit; + if (totalBytesRead < 0 || totalBytesRead > state.sizeLimit) + { + throw InvalidProtocolBufferException.SizeLimitExceeded(); + } + return true; + } + } + + private bool RefillFromCodedInputStream(ref ReadOnlySpan buffer, ref ParserInternalState state, bool mustSucceed) + { + CheckCurrentBufferIsEmpty(ref state); + + if (state.totalBytesRetired + state.bufferSize == state.currentLimit) + { + // Oops, we hit a limit. + if (mustSucceed) + { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + else + { + return false; + } + } + + Stream input = codedInputStream.InternalInputStream; + + state.totalBytesRetired += state.bufferSize; + + state.bufferPos = 0; + state.bufferSize = (input == null) ? 0 : input.Read(codedInputStream.InternalBuffer, 0, buffer.Length); + if (state.bufferSize < 0) + { + throw new InvalidOperationException("Stream.Read returned a negative count"); + } + if (state.bufferSize == 0) + { + if (mustSucceed) + { + throw InvalidProtocolBufferException.TruncatedMessage(); + } + else + { + return false; + } + } + else + { + RecomputeBufferSizeAfterLimit(ref state); + int totalBytesRead = + state.totalBytesRetired + state.bufferSize + state.bufferSizeAfterLimit; + if (totalBytesRead < 0 || totalBytesRead > state.sizeLimit) + { + throw InvalidProtocolBufferException.SizeLimitExceeded(); + } + return true; + } + } + + private static void RecomputeBufferSizeAfterLimit(ref ParserInternalState state) + { + state.bufferSize += state.bufferSizeAfterLimit; + int bufferEnd = state.totalBytesRetired + state.bufferSize; + if (bufferEnd > state.currentLimit) + { + // Limit is in current buffer. + state.bufferSizeAfterLimit = bufferEnd - state.currentLimit; + state.bufferSize -= state.bufferSizeAfterLimit; + } + else + { + state.bufferSizeAfterLimit = 0; + } + } + + private static void CheckCurrentBufferIsEmpty(ref ParserInternalState state) + { + if (state.bufferPos < state.bufferSize) + { + throw new InvalidOperationException("RefillBuffer() called when buffer wasn't empty."); + } + } + } +} \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/UnknownFieldSet.cs b/csharp/src/Google.Protobuf/UnknownFieldSet.cs index 7a2b6a00d24a..9ebe70406598 100644 --- a/csharp/src/Google.Protobuf/UnknownFieldSet.cs +++ b/csharp/src/Google.Protobuf/UnknownFieldSet.cs @@ -33,6 +33,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Security; using Google.Protobuf.Reflection; namespace Google.Protobuf @@ -176,47 +177,47 @@ internal UnknownFieldSet AddOrReplaceField(int number, UnknownField field) fields[number] = field; return this; } - + /// - /// Parse a single field from and merge it + /// Parse a single field from and merge it /// into this set. /// - /// The coded input stream containing the field + /// The parse context from which to read the field /// false if the tag is an "end group" tag, true otherwise - private bool MergeFieldFrom(CodedInputStream input) + private bool MergeFieldFrom(ref ParseContext ctx) { - uint tag = input.LastTag; + uint tag = ctx.LastTag; int number = WireFormat.GetTagFieldNumber(tag); switch (WireFormat.GetTagWireType(tag)) { case WireFormat.WireType.Varint: { - ulong uint64 = input.ReadUInt64(); + ulong uint64 = ctx.ReadUInt64(); GetOrAddField(number).AddVarint(uint64); return true; } case WireFormat.WireType.Fixed32: { - uint uint32 = input.ReadFixed32(); + uint uint32 = ctx.ReadFixed32(); GetOrAddField(number).AddFixed32(uint32); return true; } case WireFormat.WireType.Fixed64: { - ulong uint64 = input.ReadFixed64(); + ulong uint64 = ctx.ReadFixed64(); GetOrAddField(number).AddFixed64(uint64); return true; } case WireFormat.WireType.LengthDelimited: { - ByteString bytes = input.ReadBytes(); + ByteString bytes = ctx.ReadBytes(); GetOrAddField(number).AddLengthDelimited(bytes); return true; } case WireFormat.WireType.StartGroup: { UnknownFieldSet set = new UnknownFieldSet(); - input.ReadGroup(number, set); + ParsingPrimitivesMessages.ReadGroup(ref ctx, number, set); GetOrAddField(number).AddGroup(set); return true; } @@ -229,16 +230,16 @@ private bool MergeFieldFrom(CodedInputStream input) } } - internal void MergeGroupFrom(CodedInputStream input) + internal void MergeGroupFrom(ref ParseContext ctx) { while (true) { - uint tag = input.ReadTag(); + uint tag = ctx.ReadTag(); if (tag == 0) { break; } - if (!MergeFieldFrom(input)) + if (!MergeFieldFrom(ref ctx)) { break; } @@ -257,21 +258,45 @@ internal void MergeGroupFrom(CodedInputStream input) public static UnknownFieldSet MergeFieldFrom(UnknownFieldSet unknownFields, CodedInputStream input) { - if (input.DiscardUnknownFields) + ParseContext.Initialize(input, out ParseContext ctx); + try + { + return MergeFieldFrom(unknownFields, ref ctx); + } + finally { - input.SkipLastField(); + ctx.CopyStateTo(input); + } + } + + /// + /// Create a new UnknownFieldSet if unknownFields is null. + /// Parse a single field from and merge it + /// into unknownFields. If is configured to discard unknown fields, + /// will be returned as-is and the field will be skipped. + /// + /// The UnknownFieldSet which need to be merged + /// The parse context from which to read the field + /// The merged UnknownFieldSet + [SecuritySafeCritical] + public static UnknownFieldSet MergeFieldFrom(UnknownFieldSet unknownFields, + ref ParseContext ctx) + { + if (ctx.DiscardUnknownFields) + { + ParsingPrimitivesMessages.SkipLastField(ref ctx.buffer, ref ctx.state); return unknownFields; } if (unknownFields == null) { unknownFields = new UnknownFieldSet(); } - if (!unknownFields.MergeFieldFrom(input)) - { - throw new InvalidProtocolBufferException("Merge an unknown field of end-group tag, indicating that the corresponding start-group was missing."); // match the old code-gen + if (!unknownFields.MergeFieldFrom(ref ctx)) + { + throw new InvalidProtocolBufferException("Merge an unknown field of end-group tag, indicating that the corresponding start-group was missing."); // match the old code-gen } return unknownFields; - } + } /// /// Merges the fields from into this set. diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs index 09e0e29f0de9..c4e744706c08 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs @@ -119,7 +119,7 @@ public static partial class AnyReflection { /// "value": "1.212s" /// } /// - public sealed partial class Any : pb::IMessage { + public sealed partial class Any : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Any()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -288,11 +288,16 @@ public sealed partial class Any : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { TypeUrl = input.ReadString(); diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs index 06a990591940..1f29224916de 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs @@ -64,7 +64,7 @@ public static partial class ApiReflection { /// this message itself. See https://cloud.google.com/apis/design/glossary for /// detailed terminology. /// - public sealed partial class Api : pb::IMessage { + public sealed partial class Api : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Api()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -341,22 +341,27 @@ public sealed partial class Api : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Name = input.ReadString(); break; } case 18: { - methods_.AddEntriesFrom(input, _repeated_methods_codec); + methods_.AddEntriesFrom(ref input, _repeated_methods_codec); break; } case 26: { - options_.AddEntriesFrom(input, _repeated_options_codec); + options_.AddEntriesFrom(ref input, _repeated_options_codec); break; } case 34: { @@ -371,7 +376,7 @@ public sealed partial class Api : pb::IMessage { break; } case 50: { - mixins_.AddEntriesFrom(input, _repeated_mixins_codec); + mixins_.AddEntriesFrom(ref input, _repeated_mixins_codec); break; } case 56: { @@ -387,7 +392,7 @@ public sealed partial class Api : pb::IMessage { /// /// Method represents a method of an API interface. /// - public sealed partial class Method : pb::IMessage { + public sealed partial class Method : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Method()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -657,11 +662,16 @@ public sealed partial class Method : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Name = input.ReadString(); @@ -684,7 +694,7 @@ public sealed partial class Method : pb::IMessage { break; } case 50: { - options_.AddEntriesFrom(input, _repeated_options_codec); + options_.AddEntriesFrom(ref input, _repeated_options_codec); break; } case 56: { @@ -777,7 +787,7 @@ public sealed partial class Method : pb::IMessage { /// ... /// } /// - public sealed partial class Mixin : pb::IMessage { + public sealed partial class Mixin : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Mixin()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -921,11 +931,16 @@ public sealed partial class Mixin : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Name = input.ReadString(); diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs index f0078c4dd4e0..804b82f0fab0 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs @@ -100,7 +100,7 @@ public static partial class DurationReflection { /// be expressed in JSON format as "3.000000001s", and 3 seconds and 1 /// microsecond should be expressed in JSON format as "3.000001s". /// - public sealed partial class Duration : pb::IMessage { + public sealed partial class Duration : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Duration()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -250,11 +250,16 @@ public sealed partial class Duration : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Seconds = input.ReadInt64(); diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs index fa435cd23edf..f73c345dfb14 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs @@ -50,7 +50,7 @@ public static partial class EmptyReflection { /// /// The JSON representation for `Empty` is empty JSON object `{}`. /// - public sealed partial class Empty : pb::IMessage { + public sealed partial class Empty : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Empty()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -139,11 +139,16 @@ public sealed partial class Empty : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; } } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs index 00e1e9faa453..25a2f050a188 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs @@ -240,7 +240,7 @@ public static partial class FieldMaskReflection { /// request should verify the included field paths, and return an /// `INVALID_ARGUMENT` error if any path is unmappable. /// - public sealed partial class FieldMask : pb::IMessage { + public sealed partial class FieldMask : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FieldMask()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -348,14 +348,19 @@ public sealed partial class FieldMask : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { - paths_.AddEntriesFrom(input, _repeated_paths_codec); + paths_.AddEntriesFrom(ref input, _repeated_paths_codec); break; } } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs b/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs index d7076196e0fd..99d40a5be084 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs @@ -44,7 +44,7 @@ public static partial class SourceContextReflection { /// `SourceContext` represents information about the source of a /// protobuf element, like the file in which it is defined. /// - public sealed partial class SourceContext : pb::IMessage { + public sealed partial class SourceContext : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SourceContext()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -161,11 +161,16 @@ public sealed partial class SourceContext : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { FileName = input.ReadString(); diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs index b1dbe239cc9c..84057422c243 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs @@ -77,7 +77,7 @@ public enum NullValue { /// /// The JSON representation for `Struct` is JSON object. /// - public sealed partial class Struct : pb::IMessage { + public sealed partial class Struct : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Struct()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -185,14 +185,19 @@ public sealed partial class Struct : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { - fields_.AddEntriesFrom(input, _map_fields_codec); + fields_.AddEntriesFrom(ref input, _map_fields_codec); break; } } @@ -209,7 +214,7 @@ public sealed partial class Struct : pb::IMessage { /// /// The JSON representation for `Value` is JSON value. /// - public sealed partial class Value : pb::IMessage { + public sealed partial class Value : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Value()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -509,11 +514,16 @@ public enum KindOneofCase { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { kind_ = input.ReadEnum(); @@ -561,7 +571,7 @@ public enum KindOneofCase { /// /// The JSON representation for `ListValue` is JSON array. /// - public sealed partial class ListValue : pb::IMessage { + public sealed partial class ListValue : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ListValue()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -669,14 +679,19 @@ public sealed partial class ListValue : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { - values_.AddEntriesFrom(input, _repeated_values_codec); + values_.AddEntriesFrom(ref input, _repeated_values_codec); break; } } diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs index 12f4812af37f..31cbe95b8900 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs @@ -123,7 +123,7 @@ public static partial class TimestampReflection { /// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D /// ) to obtain a formatter capable of generating timestamps in this format. /// - public sealed partial class Timestamp : pb::IMessage { + public sealed partial class Timestamp : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Timestamp()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -271,11 +271,16 @@ public sealed partial class Timestamp : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Seconds = input.ReadInt64(); diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs index bfd4b8ec8221..3c074f85ec62 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs @@ -94,7 +94,7 @@ public enum Syntax { /// /// A protocol buffer message type. /// - public sealed partial class Type : pb::IMessage { + public sealed partial class Type : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Type()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -324,26 +324,31 @@ public sealed partial class Type : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Name = input.ReadString(); break; } case 18: { - fields_.AddEntriesFrom(input, _repeated_fields_codec); + fields_.AddEntriesFrom(ref input, _repeated_fields_codec); break; } case 26: { - oneofs_.AddEntriesFrom(input, _repeated_oneofs_codec); + oneofs_.AddEntriesFrom(ref input, _repeated_oneofs_codec); break; } case 34: { - options_.AddEntriesFrom(input, _repeated_options_codec); + options_.AddEntriesFrom(ref input, _repeated_options_codec); break; } case 42: { @@ -366,7 +371,7 @@ public sealed partial class Type : pb::IMessage { /// /// A single field of a message type. /// - public sealed partial class Field : pb::IMessage { + public sealed partial class Field : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Field()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -719,11 +724,16 @@ public sealed partial class Field : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Kind = (global::Google.Protobuf.WellKnownTypes.Field.Types.Kind) input.ReadEnum(); @@ -754,7 +764,7 @@ public sealed partial class Field : pb::IMessage { break; } case 74: { - options_.AddEntriesFrom(input, _repeated_options_codec); + options_.AddEntriesFrom(ref input, _repeated_options_codec); break; } case 82: { @@ -885,7 +895,7 @@ public enum Cardinality { /// /// Enum type definition. /// - public sealed partial class Enum : pb::IMessage { + public sealed partial class Enum : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Enum()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1096,22 +1106,27 @@ public sealed partial class Enum : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Name = input.ReadString(); break; } case 18: { - enumvalue_.AddEntriesFrom(input, _repeated_enumvalue_codec); + enumvalue_.AddEntriesFrom(ref input, _repeated_enumvalue_codec); break; } case 26: { - options_.AddEntriesFrom(input, _repeated_options_codec); + options_.AddEntriesFrom(ref input, _repeated_options_codec); break; } case 34: { @@ -1134,7 +1149,7 @@ public sealed partial class Enum : pb::IMessage { /// /// Enum value definition. /// - public sealed partial class EnumValue : pb::IMessage { + public sealed partial class EnumValue : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new EnumValue()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1296,11 +1311,16 @@ public sealed partial class EnumValue : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Name = input.ReadString(); @@ -1311,7 +1331,7 @@ public sealed partial class EnumValue : pb::IMessage { break; } case 26: { - options_.AddEntriesFrom(input, _repeated_options_codec); + options_.AddEntriesFrom(ref input, _repeated_options_codec); break; } } @@ -1324,7 +1344,7 @@ public sealed partial class EnumValue : pb::IMessage { /// A protocol buffer option, which can be attached to a message, field, /// enumeration, etc. /// - public sealed partial class Option : pb::IMessage - public sealed partial class DoubleValue : pb::IMessage { + public sealed partial class DoubleValue : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DoubleValue()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -173,11 +173,16 @@ public sealed partial class DoubleValue : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 9: { Value = input.ReadDouble(); @@ -194,7 +199,7 @@ public sealed partial class DoubleValue : pb::IMessage { /// /// The JSON representation for `FloatValue` is JSON number. /// - public sealed partial class FloatValue : pb::IMessage { + public sealed partial class FloatValue : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FloatValue()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -310,11 +315,16 @@ public sealed partial class FloatValue : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 13: { Value = input.ReadFloat(); @@ -331,7 +341,7 @@ public sealed partial class FloatValue : pb::IMessage { /// /// The JSON representation for `Int64Value` is JSON string. /// - public sealed partial class Int64Value : pb::IMessage { + public sealed partial class Int64Value : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Int64Value()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -447,11 +457,16 @@ public sealed partial class Int64Value : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Value = input.ReadInt64(); @@ -468,7 +483,7 @@ public sealed partial class Int64Value : pb::IMessage { /// /// The JSON representation for `UInt64Value` is JSON string. /// - public sealed partial class UInt64Value : pb::IMessage { + public sealed partial class UInt64Value : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new UInt64Value()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -584,11 +599,16 @@ public sealed partial class UInt64Value : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Value = input.ReadUInt64(); @@ -605,7 +625,7 @@ public sealed partial class UInt64Value : pb::IMessage { /// /// The JSON representation for `Int32Value` is JSON number. /// - public sealed partial class Int32Value : pb::IMessage { + public sealed partial class Int32Value : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Int32Value()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -721,11 +741,16 @@ public sealed partial class Int32Value : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Value = input.ReadInt32(); @@ -742,7 +767,7 @@ public sealed partial class Int32Value : pb::IMessage { /// /// The JSON representation for `UInt32Value` is JSON number. /// - public sealed partial class UInt32Value : pb::IMessage { + public sealed partial class UInt32Value : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new UInt32Value()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -858,11 +883,16 @@ public sealed partial class UInt32Value : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Value = input.ReadUInt32(); @@ -879,7 +909,7 @@ public sealed partial class UInt32Value : pb::IMessage { /// /// The JSON representation for `BoolValue` is JSON `true` and `false`. /// - public sealed partial class BoolValue : pb::IMessage { + public sealed partial class BoolValue : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BoolValue()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -995,11 +1025,16 @@ public sealed partial class BoolValue : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 8: { Value = input.ReadBool(); @@ -1016,7 +1051,7 @@ public sealed partial class BoolValue : pb::IMessage { /// /// The JSON representation for `StringValue` is JSON string. /// - public sealed partial class StringValue : pb::IMessage { + public sealed partial class StringValue : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new StringValue()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1132,11 +1167,16 @@ public sealed partial class StringValue : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Value = input.ReadString(); @@ -1153,7 +1193,7 @@ public sealed partial class StringValue : pb::IMessage { /// /// The JSON representation for `BytesValue` is JSON string. /// - public sealed partial class BytesValue : pb::IMessage { + public sealed partial class BytesValue : pb::IMessage, pb::IBufferMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BytesValue()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -1269,11 +1309,16 @@ public sealed partial class BytesValue : pb::IMessage { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(pb::CodedInputStream input) { + input.ReadRawMessage(this); + } + + [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, input); + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; case 10: { Value = input.ReadBytes(); diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.cc b/src/google/protobuf/compiler/csharp/csharp_map_field.cc index f3f09ea4546b..9f3db7685193 100644 --- a/src/google/protobuf/compiler/csharp/csharp_map_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_map_field.cc @@ -96,7 +96,7 @@ void MapFieldGenerator::GenerateMergingCode(io::Printer* printer) { void MapFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "$name$_.AddEntriesFrom(input, _map_$name$_codec);\n"); + "$name$_.AddEntriesFrom(ref input, _map_$name$_codec);\n"); } void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index d71d2c41db7b..4ff0c7b17a53 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -130,6 +130,7 @@ void MessageGenerator::Generate(io::Printer* printer) { else { printer->Print(vars, "pb::IMessage<$class_name$>"); } + printer->Print(", pb::IBufferMessage"); printer->Print(" {\n"); printer->Indent(); @@ -636,6 +637,13 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { WriteGeneratedCodeAttributes(printer); printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n"); printer->Indent(); + printer->Print("input.ReadRawMessage(this);\n"); + printer->Outdent(); + printer->Print("}\n\n"); + + WriteGeneratedCodeAttributes(printer); + printer->Print("void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {\n"); + printer->Indent(); printer->Print( "uint tag;\n" "while ((tag = input.ReadTag()) != 0) {\n" @@ -651,14 +659,14 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { if (has_extension_ranges_) { printer->Print( "default:\n" - " if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) {\n" - " _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);\n" + " if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) {\n" + " _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);\n" " }\n" " break;\n"); } else { printer->Print( "default:\n" - " _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);\n" + " _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);\n" " break;\n"); } for (int i = 0; i < fields_by_number().size(); i++) { 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 73309a7edd1e..aae7091c6f38 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc @@ -80,7 +80,7 @@ void RepeatedEnumFieldGenerator::GenerateMergingCode(io::Printer* printer) { void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n"); + "$name$_.AddEntriesFrom(ref input, _repeated_$name$_codec);\n"); } void RepeatedEnumFieldGenerator::GenerateSerializationCode(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 4b4b37de1bb4..2e2cfa8fae55 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc @@ -95,7 +95,7 @@ void RepeatedMessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n"); + "$name$_.AddEntriesFrom(ref input, _repeated_$name$_codec);\n"); } void RepeatedMessageFieldGenerator::GenerateSerializationCode(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 c1444ea124aa..d4ff302543bb 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc @@ -80,7 +80,7 @@ void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "$name$_.AddEntriesFrom(input, _repeated_$name$_codec);\n"); + "$name$_.AddEntriesFrom(ref input, _repeated_$name$_codec);\n"); } void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode(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 2183d752c03f..cada81cd9ae8 100644 --- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc @@ -116,7 +116,7 @@ void WrapperFieldGenerator::GenerateMergingCode(io::Printer* printer) { void WrapperFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "$type_name$ value = _single_$name$_codec.Read(input);\n" + "$type_name$ value = _single_$name$_codec.Read(ref input);\n" "if ($has_not_property_check$ || value != $default_value$) {\n" " $property_name$ = value;\n" "}\n"); @@ -250,7 +250,7 @@ void WrapperOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) { void WrapperOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "$property_name$ = _oneof_$name$_codec.Read(input);\n"); + "$property_name$ = _oneof_$name$_codec.Read(ref input);\n"); } void WrapperOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) {