From 047575f20cbdee8fb2f88d78a317ffe6133b93e6 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Mon, 16 Jan 2017 11:23:32 +0000 Subject: Support custom options in C# This consists of: - Changing the codegen for the fixed set of options protos, to parse unknown fields instead of skipping them - Add a new CustomOptions type in the C# support library - Expose CustomOptions properties from the immutable proto wrappers in the support library Only single-value options are currently supported, and fetching options values requires getting the type right and knowing the field number. Both of these can be addressed at a later time. Fixes #2143, at least as a first pass. --- Makefile.am | 4 + csharp/generate_protos.sh | 5 +- csharp/protos/unittest_custom_options_proto3.proto | 338 +++ .../Reflection/CustomOptionsTest.cs | 267 ++ .../TestProtos/UnittestCustomOptionsProto3.cs | 2627 ++++++++++++++++++++ .../Google.Protobuf/Reflection/CustomOptions.cs | 390 +++ .../src/Google.Protobuf/Reflection/Descriptor.cs | 32 +- .../Google.Protobuf/Reflection/EnumDescriptor.cs | 5 + .../Reflection/EnumValueDescriptor.cs | 5 + .../Google.Protobuf/Reflection/FieldDescriptor.cs | 5 + .../Google.Protobuf/Reflection/FileDescriptor.cs | 5 + .../Reflection/MessageDescriptor.cs | 5 + .../Google.Protobuf/Reflection/MethodDescriptor.cs | 5 + .../Google.Protobuf/Reflection/OneofDescriptor.cs | 5 + .../Reflection/ServiceDescriptor.cs | 5 + .../protobuf/compiler/csharp/csharp_helpers.h | 16 + .../protobuf/compiler/csharp/csharp_message.cc | 22 +- 17 files changed, 3727 insertions(+), 14 deletions(-) create mode 100644 csharp/protos/unittest_custom_options_proto3.proto create mode 100644 csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs create mode 100644 csharp/src/Google.Protobuf.Test/TestProtos/UnittestCustomOptionsProto3.cs create mode 100644 csharp/src/Google.Protobuf/Reflection/CustomOptions.cs diff --git a/Makefile.am b/Makefile.am index 6aa7e800..16d96af8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -60,6 +60,7 @@ csharp_EXTRA_DIST= \ csharp/keys/Google.Protobuf.public.snk \ csharp/keys/Google.Protobuf.snk \ csharp/keys/README.md \ + csharp/protos/unittest_custom_options_proto3.proto \ csharp/protos/unittest_issues.proto \ csharp/src/AddressBook/AddPerson.cs \ csharp/src/AddressBook/Addressbook.cs \ @@ -92,6 +93,7 @@ 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/Reflection/CustomOptionsTest.cs \ csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs \ csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs \ csharp/src/Google.Protobuf.Test/Reflection/TypeRegistryTest.cs \ @@ -101,6 +103,7 @@ csharp_EXTRA_DIST= \ csharp/src/Google.Protobuf.Test/TestProtos/ForeignMessagePartial.cs \ csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs \ csharp/src/Google.Protobuf.Test/TestProtos/TestMessagesProto3.cs \ + csharp/src/Google.Protobuf.Test/TestProtos/UnittestCustomOptionsProto3.cs \ csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs \ csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs \ csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs \ @@ -140,6 +143,7 @@ csharp_EXTRA_DIST= \ csharp/src/Google.Protobuf/MessageParser.cs \ csharp/src/Google.Protobuf/ProtoPreconditions.cs \ csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs \ + csharp/src/Google.Protobuf/Reflection/CustomOptions.cs \ csharp/src/Google.Protobuf/Reflection/Descriptor.cs \ csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs \ csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs \ diff --git a/csharp/generate_protos.sh b/csharp/generate_protos.sh index 7cbcf436..d2f47479 100755 --- a/csharp/generate_protos.sh +++ b/csharp/generate_protos.sh @@ -50,9 +50,10 @@ $PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf.Test \ src/google/protobuf/unittest_well_known_types.proto # Different base namespace to the protos above -$PROTOC -Icsharp/protos --csharp_out=csharp/src/Google.Protobuf.Test \ +$PROTOC -Isrc -Icsharp/protos --csharp_out=csharp/src/Google.Protobuf.Test \ --csharp_opt=base_namespace=UnitTest.Issues \ - csharp/protos/unittest_issues.proto + csharp/protos/unittest_issues.proto \ + csharp/protos/unittest_custom_options_proto3.proto # Don't specify a base namespace at all; we just want to make sure the # results end up in TestProtos. diff --git a/csharp/protos/unittest_custom_options_proto3.proto b/csharp/protos/unittest_custom_options_proto3.proto new file mode 100644 index 00000000..9b18b280 --- /dev/null +++ b/csharp/protos/unittest_custom_options_proto3.proto @@ -0,0 +1,338 @@ +// 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. + +// Author: benjy@google.com (Benjy Weinberger) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// A proto file used to test the "custom options" feature of google.protobuf. + +// This file is based on unittest_custom_options.proto in +// src/google/protobuf, but is modified for proto3. It could +// potentially be moved into src/google/protobuf, but currently C# +// is the only language that really needs it, as we don't support +// proto2 syntax. It's cut down significantly as proto3 only supports +// extensions for options. + + +syntax = "proto3"; + +// A custom file option (defined below). +option (file_opt1) = 9876543210; + +import "google/protobuf/descriptor.proto"; + +// We don't put this in a package within proto2 because we need to make sure +// that the generated code doesn't depend on being in the proto2 namespace. +package protobuf_unittest; +option csharp_namespace = "UnitTest.Issues.TestProtos"; + +// Some simple test custom options of various types. + +extend google.protobuf.FileOptions { + uint64 file_opt1 = 7736974; +} + +extend google.protobuf.MessageOptions { + int32 message_opt1 = 7739036; +} + +extend google.protobuf.FieldOptions { + fixed64 field_opt1 = 7740936; +} + +// See https://github.com/google/protobuf/issues/2316 +// extend google.protobuf.OneofOptions { +// int32 oneof_opt1 = 7740111; +// } + +extend google.protobuf.EnumOptions { + sfixed32 enum_opt1 = 7753576; +} + +extend google.protobuf.EnumValueOptions { + int32 enum_value_opt1 = 1560678; +} + +extend google.protobuf.ServiceOptions { + sint64 service_opt1 = 7887650; +} + +enum MethodOpt1 { + METHODOPT1_UNSPECIFIED = 0; + METHODOPT1_VAL1 = 1; + METHODOPT1_VAL2 = 2; +} + +extend google.protobuf.MethodOptions { + MethodOpt1 method_opt1 = 7890860; +} + +// A test message with custom options at all possible locations (and also some +// regular options, to make sure they interact nicely). +message TestMessageWithCustomOptions { + option message_set_wire_format = false; + + option (message_opt1) = -56; + + string field1 = 1 [ctype=CORD, + (field_opt1)=8765432109]; + + oneof AnOneof { +// See https://github.com/google/protobuf/issues/2316 +// option (oneof_opt1) = -99; + int32 oneof_field = 2; + } + + enum AnEnum { + option (enum_opt1) = -789; + ANENUM_UNSPECIFIED = 0; + ANENUM_VAL1 = 1; + ANENUM_VAL2 = 2 [(enum_value_opt1) = 123]; + } +} + + +// A test RPC service with custom options at all possible locations (and also +// some regular options, to make sure they interact nicely). +message CustomOptionFooRequest { +} + +message CustomOptionFooResponse { +} + +message CustomOptionFooClientMessage { +} + +message CustomOptionFooServerMessage { +} + +service TestServiceWithCustomOptions { + option (service_opt1) = -9876543210; + + rpc Foo(CustomOptionFooRequest) returns (CustomOptionFooResponse) { + option (method_opt1) = METHODOPT1_VAL2; + } +} + + + +// Options of every possible field type, so we can test them all exhaustively. + +message DummyMessageContainingEnum { + enum TestEnumType { + TEST_OPTION_ENUM_UNSPECIFIED = 0; + TEST_OPTION_ENUM_TYPE1 = 22; + TEST_OPTION_ENUM_TYPE2 = -23; + } +} + +message DummyMessageInvalidAsOptionType { +} + +extend google.protobuf.MessageOptions { + bool bool_opt = 7706090; + int32 int32_opt = 7705709; + int64 int64_opt = 7705542; + uint32 uint32_opt = 7704880; + uint64 uint64_opt = 7702367; + sint32 sint32_opt = 7701568; + sint64 sint64_opt = 7700863; + fixed32 fixed32_opt = 7700307; + fixed64 fixed64_opt = 7700194; + sfixed32 sfixed32_opt = 7698645; + sfixed64 sfixed64_opt = 7685475; + float float_opt = 7675390; + double double_opt = 7673293; + string string_opt = 7673285; + bytes bytes_opt = 7673238; + DummyMessageContainingEnum.TestEnumType enum_opt = 7673233; + DummyMessageInvalidAsOptionType message_type_opt = 7665967; +} + +message CustomOptionMinIntegerValues { + option (bool_opt) = false; + option (int32_opt) = -0x80000000; + option (int64_opt) = -0x8000000000000000; + option (uint32_opt) = 0; + option (uint64_opt) = 0; + option (sint32_opt) = -0x80000000; + option (sint64_opt) = -0x8000000000000000; + option (fixed32_opt) = 0; + option (fixed64_opt) = 0; + option (sfixed32_opt) = -0x80000000; + option (sfixed64_opt) = -0x8000000000000000; +} + +message CustomOptionMaxIntegerValues { + option (bool_opt) = true; + option (int32_opt) = 0x7FFFFFFF; + option (int64_opt) = 0x7FFFFFFFFFFFFFFF; + option (uint32_opt) = 0xFFFFFFFF; + option (uint64_opt) = 0xFFFFFFFFFFFFFFFF; + option (sint32_opt) = 0x7FFFFFFF; + option (sint64_opt) = 0x7FFFFFFFFFFFFFFF; + option (fixed32_opt) = 0xFFFFFFFF; + option (fixed64_opt) = 0xFFFFFFFFFFFFFFFF; + option (sfixed32_opt) = 0x7FFFFFFF; + option (sfixed64_opt) = 0x7FFFFFFFFFFFFFFF; +} + +message CustomOptionOtherValues { + option (int32_opt) = -100; // To test sign-extension. + option (float_opt) = 12.3456789; + option (double_opt) = 1.234567890123456789; + option (string_opt) = "Hello, \"World\""; + option (bytes_opt) = "Hello\0World"; + option (enum_opt) = TEST_OPTION_ENUM_TYPE2; +} + +message SettingRealsFromPositiveInts { + option (float_opt) = 12; + option (double_opt) = 154; +} + +message SettingRealsFromNegativeInts { + option (float_opt) = -12; + option (double_opt) = -154; +} + +// Options of complex message types, themselves combined and extended in +// various ways. + +message ComplexOptionType1 { + int32 foo = 1; + int32 foo2 = 2; + int32 foo3 = 3; + repeated int32 foo4 = 4; +} + +message ComplexOptionType2 { + ComplexOptionType1 bar = 1; + int32 baz = 2; + + message ComplexOptionType4 { + int32 waldo = 1; + + extend google.protobuf.MessageOptions { + ComplexOptionType4 complex_opt4 = 7633546; + } + } + + ComplexOptionType4 fred = 3; + repeated ComplexOptionType4 barney = 4; +} + +message ComplexOptionType3 { + int32 qux = 1; +} + +extend google.protobuf.MessageOptions { + protobuf_unittest.ComplexOptionType1 complex_opt1 = 7646756; + ComplexOptionType2 complex_opt2 = 7636949; + ComplexOptionType3 complex_opt3 = 7636463; +} + +// Note that we try various different ways of naming the same extension. +message VariousComplexOptions { + option (.protobuf_unittest.complex_opt1).foo = 42; + option (protobuf_unittest.complex_opt1).foo4 = 99; + option (protobuf_unittest.complex_opt1).foo4 = 88; + option (complex_opt2).baz = 987; + option (complex_opt2).bar.foo = 743; + option (ComplexOptionType2.ComplexOptionType4.complex_opt4).waldo = 1971; + option (complex_opt2).fred.waldo = 321; + option (complex_opt2).barney = { waldo: 101 }; + option (complex_opt2).barney = { waldo: 212 }; + option (protobuf_unittest.complex_opt3).qux = 9; +} + +// ------------------------------------------------------ +// Definitions for testing aggregate option parsing. +// See descriptor_unittest.cc. + +// A helper type used to test aggregate option parsing +message Aggregate { + int32 i = 1; + string s = 2; + + // A nested object + Aggregate sub = 3; +} + +// Allow Aggregate to be used as an option at all possible locations +// in the .proto grammer. +extend google.protobuf.FileOptions { Aggregate fileopt = 15478479; } +extend google.protobuf.MessageOptions { Aggregate msgopt = 15480088; } +extend google.protobuf.FieldOptions { Aggregate fieldopt = 15481374; } +extend google.protobuf.EnumOptions { Aggregate enumopt = 15483218; } +extend google.protobuf.EnumValueOptions { Aggregate enumvalopt = 15486921; } +extend google.protobuf.ServiceOptions { Aggregate serviceopt = 15497145; } +extend google.protobuf.MethodOptions { Aggregate methodopt = 15512713; } + +// Try using AggregateOption at different points in the proto grammar +option (fileopt) = { + s: 'FileAnnotation' + // Also test the handling of comments + /* of both types */ i: 100 + + sub { s: 'NestedFileAnnotation' } +}; + +message AggregateMessage { + option (msgopt) = { i:101 s:'MessageAnnotation' }; + int32 fieldname = 1 [(fieldopt) = { s:'FieldAnnotation' }]; +} + +service AggregateService { + option (serviceopt) = { s:'ServiceAnnotation' }; + rpc Method (AggregateMessage) returns (AggregateMessage) { + option (methodopt) = { s:'MethodAnnotation' }; + } +} + +enum AggregateEnum { + option (enumopt) = { s:'EnumAnnotation' }; + UNSPECIFIED = 0; + VALUE = 1 [(enumvalopt) = { s:'EnumValueAnnotation' }]; +} + +// Test custom options for nested type. +message NestedOptionType { + message NestedMessage { + option (message_opt1) = 1001; + int32 nested_field = 1 [(field_opt1) = 1002]; + } + enum NestedEnum { + UNSPECIFIED = 0; + option (enum_opt1) = 1003; + NESTED_ENUM_VALUE = 1 [(enum_value_opt1) = 1004]; + } +} diff --git a/csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs new file mode 100644 index 00000000..b662e8b0 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs @@ -0,0 +1,267 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2017 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.Reflection; +using Google.Protobuf.WellKnownTypes; +using NUnit.Framework; +using System.IO; +using System.Linq; +using UnitTest.Issues.TestProtos; +using static Google.Protobuf.WireFormat; +using static UnitTest.Issues.TestProtos.ComplexOptionType2.Types; +using static UnitTest.Issues.TestProtos.DummyMessageContainingEnum.Types; +using static Google.Protobuf.Test.Reflection.CustomOptionNumber; + +namespace Google.Protobuf.Test.Reflection +{ + // Internal enum to allow us to use "using static" for convenience. + // These are the options defined in unittest_custom_options_proto3.proto + internal enum CustomOptionNumber + { + FileOpt1 = 7736974, + MessageOpt1 = 7739036, + FieldOpt1 = 7740936, + EnumOpt1 = 7753576, + EnumValueOpt1 = 1560678, + ServiceOpt1 = 7887650, + MethodOpt1 = 7890860, + + // All message options... + BoolOpt = 7706090, + Int32Opt = 7705709, + Int64Opt = 7705542, + UInt32Opt = 7704880, + UInt64Opt = 7702367, + SInt32Opt = 7701568, + SInt64Opt = 7700863, + Fixed32Opt = 7700307, + Fixed64Opt = 7700194, + SFixed32Opt = 7698645, + SFixed64Opt = 7685475, + FloatOpt = 7675390, + DoubleOpt = 7673293, + StringOpt = 7673285, + BytesOpt = 7673238, + EnumOpt = 7673233, + MessageTypeOpt = 7665967, + + // Miscellaneous + ComplexOpt4 = 7633546, + ComplexOpt1 = 7646756, + ComplexOpt2 = 7636949, + ComplexOpt3 = 7636463, + + // Aggregates + AggregateFileOpt = 15478479, + AggregateMsgOpt = 15480088, + AggregateFieldOpt = 15481374, + AggregateEnumOpt = 15483218, + AggregateEnumValueOpt = 15486921, + AggregateServiceOpt = 15497145, + AggregateMethodOpt = 15512713, + } + + /// + /// The majority of the testing here is done via parsed descriptors. That's simpler to + /// achieve (and more important) than constructing a CodedInputStream manually. + /// + public class CustomOptionsTest + { + delegate bool OptionFetcher(int field, out T value); + + [Test] + public void EmptyOptionsIsShared() + { + var structOptions = Struct.Descriptor.CustomOptions; + var timestampOptions = Struct.Descriptor.CustomOptions; + Assert.AreSame(structOptions, timestampOptions); + } + + [Test] + public void SimpleIntegerTest() + { + var stream = new MemoryStream(); + var output = new CodedOutputStream(stream); + output.WriteTag(MakeTag(1, WireType.Varint)); + output.WriteInt32(1234567); + output.Flush(); + stream.Position = 0; + var input = new CodedInputStream(stream); + input.ReadTag(); + + var options = CustomOptions.Empty; + options = options.ReadOrSkipUnknownField(input); + + int intValue; + Assert.True(options.TryGetInt32(1, out intValue)); + Assert.AreEqual(1234567, intValue); + + string stringValue; + // No ByteString stored values + Assert.False(options.TryGetString(1, out stringValue)); + // Nothing stored for field 2 + Assert.False(options.TryGetInt32(2, out intValue)); + } + + [Test] + public void SimpleStringTest() + { + var stream = new MemoryStream(); + var output = new CodedOutputStream(stream); + output.WriteTag(MakeTag(1, WireType.LengthDelimited)); + output.WriteString("value"); + output.Flush(); + stream.Position = 0; + var input = new CodedInputStream(stream); + input.ReadTag(); + + var options = CustomOptions.Empty; + options = options.ReadOrSkipUnknownField(input); + + string stringValue; + Assert.True(options.TryGetString(1, out stringValue)); + Assert.AreEqual("value", stringValue); + + int intValue; + // No numeric stored values + Assert.False(options.TryGetInt32(1, out intValue)); + // Nothing stored for field 2 + Assert.False(options.TryGetString(2, out stringValue)); + } + + [Test] + public void ScalarOptions() + { + var options = CustomOptionOtherValues.Descriptor.CustomOptions; + AssertOption(-100, options.TryGetInt32, Int32Opt); + AssertOption(12.3456789f, options.TryGetFloat, FloatOpt); + AssertOption(1.234567890123456789d, options.TryGetDouble, DoubleOpt); + AssertOption("Hello, \"World\"", options.TryGetString, StringOpt); + AssertOption(ByteString.CopyFromUtf8("Hello\0World"), options.TryGetBytes, BytesOpt); + AssertOption((int) TestEnumType.TestOptionEnumType2, options.TryGetInt32, EnumOpt); + } + + [Test] + public void MessageOptions() + { + var options = VariousComplexOptions.Descriptor.CustomOptions; + AssertOption(new ComplexOptionType1 { Foo = 42, Foo4 = { 99, 88 } }, options.TryGetMessage, ComplexOpt1); + AssertOption(new ComplexOptionType2 + { + Baz = 987, Bar = new ComplexOptionType1 { Foo = 743 }, + Fred = new ComplexOptionType4 { Waldo = 321 }, + Barney = { new ComplexOptionType4 { Waldo = 101 }, new ComplexOptionType4 { Waldo = 212 } } + }, + options.TryGetMessage, ComplexOpt2); + AssertOption(new ComplexOptionType3 { Qux = 9 }, options.TryGetMessage, ComplexOpt3); + } + + [Test] + public void OptionLocations() + { + var fileOptions = UnittestCustomOptionsProto3Reflection.Descriptor.CustomOptions; + AssertOption(9876543210UL, fileOptions.TryGetUInt64, FileOpt1); + + var messageOptions = TestMessageWithCustomOptions.Descriptor.CustomOptions; + AssertOption(-56, messageOptions.TryGetInt32, MessageOpt1); + + var fieldOptions = TestMessageWithCustomOptions.Descriptor.Fields["field1"] .CustomOptions; + AssertOption(8765432109UL, fieldOptions.TryGetFixed64, FieldOpt1); + + var enumOptions = TestMessageWithCustomOptions.Descriptor.EnumTypes[0].CustomOptions; + AssertOption(-789, enumOptions.TryGetSFixed32, EnumOpt1); + + var enumValueOptions = TestMessageWithCustomOptions.Descriptor.EnumTypes[0].FindValueByNumber(2).CustomOptions; + AssertOption(123, enumValueOptions.TryGetInt32, EnumValueOpt1); + + var service = UnittestCustomOptionsProto3Reflection.Descriptor.Services + .Single(s => s.Name == "TestServiceWithCustomOptions"); + var serviceOptions = service.CustomOptions; + AssertOption(-9876543210, serviceOptions.TryGetSInt64, ServiceOpt1); + + var methodOptions = service.Methods[0].CustomOptions; + AssertOption((int) UnitTest.Issues.TestProtos.MethodOpt1.Val2, methodOptions.TryGetInt32, CustomOptionNumber.MethodOpt1); + } + + [Test] + public void MinValues() + { + var options = CustomOptionMinIntegerValues.Descriptor.CustomOptions; + AssertOption(false, options.TryGetBool, BoolOpt); + AssertOption(int.MinValue, options.TryGetInt32, Int32Opt); + AssertOption(long.MinValue, options.TryGetInt64, Int64Opt); + AssertOption(uint.MinValue, options.TryGetUInt32, UInt32Opt); + AssertOption(ulong.MinValue, options.TryGetUInt64, UInt64Opt); + AssertOption(int.MinValue, options.TryGetSInt32, SInt32Opt); + AssertOption(long.MinValue, options.TryGetSInt64, SInt64Opt); + AssertOption(uint.MinValue, options.TryGetUInt32, Fixed32Opt); + AssertOption(ulong.MinValue, options.TryGetUInt64, Fixed64Opt); + AssertOption(int.MinValue, options.TryGetInt32, SFixed32Opt); + AssertOption(long.MinValue, options.TryGetInt64, SFixed64Opt); + } + + [Test] + public void MaxValues() + { + var options = CustomOptionMaxIntegerValues.Descriptor.CustomOptions; + AssertOption(true, options.TryGetBool, BoolOpt); + AssertOption(int.MaxValue, options.TryGetInt32, Int32Opt); + AssertOption(long.MaxValue, options.TryGetInt64, Int64Opt); + AssertOption(uint.MaxValue, options.TryGetUInt32, UInt32Opt); + AssertOption(ulong.MaxValue, options.TryGetUInt64, UInt64Opt); + AssertOption(int.MaxValue, options.TryGetSInt32, SInt32Opt); + AssertOption(long.MaxValue, options.TryGetSInt64, SInt64Opt); + AssertOption(uint.MaxValue, options.TryGetFixed32, Fixed32Opt); + AssertOption(ulong.MaxValue, options.TryGetFixed64, Fixed64Opt); + AssertOption(int.MaxValue, options.TryGetSFixed32, SFixed32Opt); + AssertOption(long.MaxValue, options.TryGetSFixed64, SFixed64Opt); + } + + [Test] + public void AggregateOptions() + { + // Just two examples + var messageOptions = AggregateMessage.Descriptor.CustomOptions; + AssertOption(new Aggregate { I = 101, S = "MessageAnnotation" }, messageOptions.TryGetMessage, AggregateMsgOpt); + + var fieldOptions = AggregateMessage.Descriptor.Fields["fieldname"].CustomOptions; + AssertOption(new Aggregate { S = "FieldAnnotation" }, fieldOptions.TryGetMessage, AggregateFieldOpt); + } + + private void AssertOption(T expected, OptionFetcher fetcher, CustomOptionNumber field) + { + T actual; + Assert.IsTrue(fetcher((int) field, out actual)); + Assert.AreEqual(expected, actual); + } + } +} diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/UnittestCustomOptionsProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestCustomOptionsProto3.cs new file mode 100644 index 00000000..ab7cb940 --- /dev/null +++ b/csharp/src/Google.Protobuf.Test/TestProtos/UnittestCustomOptionsProto3.cs @@ -0,0 +1,2627 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: unittest_custom_options_proto3.proto +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace UnitTest.Issues.TestProtos { + + /// Holder for reflection information generated from unittest_custom_options_proto3.proto + public static partial class UnittestCustomOptionsProto3Reflection { + + #region Descriptor + /// File descriptor for unittest_custom_options_proto3.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static UnittestCustomOptionsProto3Reflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "CiR1bml0dGVzdF9jdXN0b21fb3B0aW9uc19wcm90bzMucHJvdG8SEXByb3Rv", + "YnVmX3VuaXR0ZXN0GiBnb29nbGUvcHJvdG9idWYvZGVzY3JpcHRvci5wcm90", + "byLHAQocVGVzdE1lc3NhZ2VXaXRoQ3VzdG9tT3B0aW9ucxIeCgZmaWVsZDEY", + "ASABKAlCDggBweDDHS3hdQoCAAAAEhUKC29uZW9mX2ZpZWxkGAIgASgFSAAi", + "UwoGQW5FbnVtEhYKEkFORU5VTV9VTlNQRUNJRklFRBAAEg8KC0FORU5VTV9W", + "QUwxEAESFgoLQU5FTlVNX1ZBTDIQAhoFsIb6BXsaCMX2yR3r/P//OhAIAODp", + "wh3I//////////8BQgkKB0FuT25lb2YiGAoWQ3VzdG9tT3B0aW9uRm9vUmVx", + "dWVzdCIZChdDdXN0b21PcHRpb25Gb29SZXNwb25zZSIeChxDdXN0b21PcHRp", + "b25Gb29DbGllbnRNZXNzYWdlIh4KHEN1c3RvbU9wdGlvbkZvb1NlcnZlck1l", + "c3NhZ2UijwEKGkR1bW15TWVzc2FnZUNvbnRhaW5pbmdFbnVtInEKDFRlc3RF", + "bnVtVHlwZRIgChxURVNUX09QVElPTl9FTlVNX1VOU1BFQ0lGSUVEEAASGgoW", + "VEVTVF9PUFRJT05fRU5VTV9UWVBFMRAWEiMKFlRFU1RfT1BUSU9OX0VOVU1f", + "VFlQRTIQ6f//////////ASIhCh9EdW1teU1lc3NhZ2VJbnZhbGlkQXNPcHRp", + "b25UeXBlIooBChxDdXN0b21PcHRpb25NaW5JbnRlZ2VyVmFsdWVzOmrQ3rId", + "AOjGsh2AgICA+P////8BsLyyHYCAgICAgICAgAGAk7IdAPj1sB0AgMSwHf//", + "//8P+JewHf///////////wGd9a8dAAAAAJHurx0AAAAAAAAAAK2Nrx0AAACA", + "mdaoHQAAAAAAAACAIpEBChxDdXN0b21PcHRpb25NYXhJbnRlZ2VyVmFsdWVz", + "OnHQ3rIdAejGsh3/////B7C8sh3//////////3+Ak7Id/////w/49bAd////", + "////////AYDEsB3+////D/iXsB3+//////////8BnfWvHf////+R7q8d////", + "//////+tja8d////f5nWqB3/////////fyJuChdDdXN0b21PcHRpb25PdGhl", + "clZhbHVlczpT6MayHZz//////////wH136Md54dFQencoh37WYxCysDzP6rc", + "oh0OSGVsbG8sICJXb3JsZCKy2aIdC0hlbGxvAFdvcmxkiNmiHen/////////", + "/wEiNAocU2V0dGluZ1JlYWxzRnJvbVBvc2l0aXZlSW50czoU9d+jHQAAQEHp", + "3KIdAAAAAABAY0AiNAocU2V0dGluZ1JlYWxzRnJvbU5lZ2F0aXZlSW50czoU", + "9d+jHQAAQMHp3KIdAAAAAABAY8AiSwoSQ29tcGxleE9wdGlvblR5cGUxEgsK", + "A2ZvbxgBIAEoBRIMCgRmb28yGAIgASgFEgwKBGZvbzMYAyABKAUSDAoEZm9v", + "NBgEIAMoBSKBAwoSQ29tcGxleE9wdGlvblR5cGUyEjIKA2JhchgBIAEoCzIl", + "LnByb3RvYnVmX3VuaXR0ZXN0LkNvbXBsZXhPcHRpb25UeXBlMRILCgNiYXoY", + "AiABKAUSRgoEZnJlZBgDIAEoCzI4LnByb3RvYnVmX3VuaXR0ZXN0LkNvbXBs", + "ZXhPcHRpb25UeXBlMi5Db21wbGV4T3B0aW9uVHlwZTQSSAoGYmFybmV5GAQg", + "AygLMjgucHJvdG9idWZfdW5pdHRlc3QuQ29tcGxleE9wdGlvblR5cGUyLkNv", + "bXBsZXhPcHRpb25UeXBlNBqXAQoSQ29tcGxleE9wdGlvblR5cGU0Eg0KBXdh", + "bGRvGAEgASgFMnIKDGNvbXBsZXhfb3B0NBIfLmdvb2dsZS5wcm90b2J1Zi5N", + "ZXNzYWdlT3B0aW9ucxiK9dEDIAEoCzI4LnByb3RvYnVmX3VuaXR0ZXN0LkNv", + "bXBsZXhPcHRpb25UeXBlMi5Db21wbGV4T3B0aW9uVHlwZTQiIQoSQ29tcGxl", + "eE9wdGlvblR5cGUzEgsKA3F1eBgBIAEoBSJsChVWYXJpb3VzQ29tcGxleE9w", + "dGlvbnM6U6LilR0CCCqi4pUdAiBjouKVHQIgWKr9kB0DENsHqv2QHQUKAwjn", + "BdKojx0DCLMPqv2QHQUaAwjBAqr9kB0EIgIIZar9kB0FIgMI1AH63pAdAggJ", + "IkwKCUFnZ3JlZ2F0ZRIJCgFpGAEgASgFEgkKAXMYAiABKAkSKQoDc3ViGAMg", + "ASgLMhwucHJvdG9idWZfdW5pdHRlc3QuQWdncmVnYXRlIlkKEEFnZ3JlZ2F0", + "ZU1lc3NhZ2USKQoJZmllbGRuYW1lGAEgASgFQhbyoYc7ERIPRmllbGRBbm5v", + "dGF0aW9uOhrC0YY7FQhlEhFNZXNzYWdlQW5ub3RhdGlvbiKXAQoQTmVzdGVk", + "T3B0aW9uVHlwZRo7Cg1OZXN0ZWRNZXNzYWdlEiIKDG5lc3RlZF9maWVsZBgB", + "IAEoBUIMweDDHeoDAAAAAAAAOgbg6cId6QciRgoKTmVzdGVkRW51bRIPCgtV", + "TlNQRUNJRklFRBAAEh0KEU5FU1RFRF9FTlVNX1ZBTFVFEAEaBrCG+gXsBxoI", + "xfbJHesDAAAqUgoKTWV0aG9kT3B0MRIaChZNRVRIT0RPUFQxX1VOU1BFQ0lG", + "SUVEEAASEwoPTUVUSE9ET1BUMV9WQUwxEAESEwoPTUVUSE9ET1BUMV9WQUwy", + "EAIqXgoNQWdncmVnYXRlRW51bRIPCgtVTlNQRUNJRklFRBAAEiUKBVZBTFVF", + "EAEaGsr8iTsVEhNFbnVtVmFsdWVBbm5vdGF0aW9uGhWSlYg7EBIORW51bUFu", + "bm90YXRpb24yjgEKHFRlc3RTZXJ2aWNlV2l0aEN1c3RvbU9wdGlvbnMSYwoD", + "Rm9vEikucHJvdG9idWZfdW5pdHRlc3QuQ3VzdG9tT3B0aW9uRm9vUmVxdWVz", + "dBoqLnByb3RvYnVmX3VuaXR0ZXN0LkN1c3RvbU9wdGlvbkZvb1Jlc3BvbnNl", + "IgXg+oweAhoJkLKLHtPbgMtJMpkBChBBZ2dyZWdhdGVTZXJ2aWNlEmsKBk1l", + "dGhvZBIjLnByb3RvYnVmX3VuaXR0ZXN0LkFnZ3JlZ2F0ZU1lc3NhZ2UaIy5w", + "cm90b2J1Zl91bml0dGVzdC5BZ2dyZWdhdGVNZXNzYWdlIhfKyJY7EhIQTWV0", + "aG9kQW5ub3RhdGlvbhoYyvuOOxMSEVNlcnZpY2VBbm5vdGF0aW9uOjIKCWZp", + "bGVfb3B0MRIcLmdvb2dsZS5wcm90b2J1Zi5GaWxlT3B0aW9ucxiOndgDIAEo", + "BDo4CgxtZXNzYWdlX29wdDESHy5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9w", + "dGlvbnMYnK3YAyABKAU6NAoKZmllbGRfb3B0MRIdLmdvb2dsZS5wcm90b2J1", + "Zi5GaWVsZE9wdGlvbnMYiLzYAyABKAY6MgoJZW51bV9vcHQxEhwuZ29vZ2xl", + "LnByb3RvYnVmLkVudW1PcHRpb25zGOie2QMgASgPOjwKD2VudW1fdmFsdWVf", + "b3B0MRIhLmdvb2dsZS5wcm90b2J1Zi5FbnVtVmFsdWVPcHRpb25zGOagXyAB", + "KAU6OAoMc2VydmljZV9vcHQxEh8uZ29vZ2xlLnByb3RvYnVmLlNlcnZpY2VP", + "cHRpb25zGKK24QMgASgSOlUKC21ldGhvZF9vcHQxEh4uZ29vZ2xlLnByb3Rv", + "YnVmLk1ldGhvZE9wdGlvbnMYrM/hAyABKA4yHS5wcm90b2J1Zl91bml0dGVz", + "dC5NZXRob2RPcHQxOjQKCGJvb2xfb3B0Eh8uZ29vZ2xlLnByb3RvYnVmLk1l", + "c3NhZ2VPcHRpb25zGOqr1gMgASgIOjUKCWludDMyX29wdBIfLmdvb2dsZS5w", + "cm90b2J1Zi5NZXNzYWdlT3B0aW9ucxjtqNYDIAEoBTo1CglpbnQ2NF9vcHQS", + "Hy5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9wdGlvbnMYxqfWAyABKAM6NgoK", + "dWludDMyX29wdBIfLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3B0aW9ucxiw", + "otYDIAEoDTo2Cgp1aW50NjRfb3B0Eh8uZ29vZ2xlLnByb3RvYnVmLk1lc3Nh", + "Z2VPcHRpb25zGN+O1gMgASgEOjYKCnNpbnQzMl9vcHQSHy5nb29nbGUucHJv", + "dG9idWYuTWVzc2FnZU9wdGlvbnMYwIjWAyABKBE6NgoKc2ludDY0X29wdBIf", + "Lmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3B0aW9ucxj/gtYDIAEoEjo3Cgtm", + "aXhlZDMyX29wdBIfLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3B0aW9ucxjT", + "/tUDIAEoBzo3CgtmaXhlZDY0X29wdBIfLmdvb2dsZS5wcm90b2J1Zi5NZXNz", + "YWdlT3B0aW9ucxji/dUDIAEoBjo4CgxzZml4ZWQzMl9vcHQSHy5nb29nbGUu", + "cHJvdG9idWYuTWVzc2FnZU9wdGlvbnMY1fHVAyABKA86OAoMc2ZpeGVkNjRf", + "b3B0Eh8uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPcHRpb25zGOOK1QMgASgQ", + "OjUKCWZsb2F0X29wdBIfLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3B0aW9u", + "cxj+u9QDIAEoAjo2Cgpkb3VibGVfb3B0Eh8uZ29vZ2xlLnByb3RvYnVmLk1l", + "c3NhZ2VPcHRpb25zGM2r1AMgASgBOjYKCnN0cmluZ19vcHQSHy5nb29nbGUu", + "cHJvdG9idWYuTWVzc2FnZU9wdGlvbnMYxavUAyABKAk6NQoJYnl0ZXNfb3B0", + "Eh8uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPcHRpb25zGJar1AMgASgMOnAK", + "CGVudW1fb3B0Eh8uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPcHRpb25zGJGr", + "1AMgASgOMjoucHJvdG9idWZfdW5pdHRlc3QuRHVtbXlNZXNzYWdlQ29udGFp", + "bmluZ0VudW0uVGVzdEVudW1UeXBlOnAKEG1lc3NhZ2VfdHlwZV9vcHQSHy5n", + "b29nbGUucHJvdG9idWYuTWVzc2FnZU9wdGlvbnMYr/LTAyABKAsyMi5wcm90", + "b2J1Zl91bml0dGVzdC5EdW1teU1lc3NhZ2VJbnZhbGlkQXNPcHRpb25UeXBl", + "Ol8KDGNvbXBsZXhfb3B0MRIfLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3B0", + "aW9ucxik3NIDIAEoCzIlLnByb3RvYnVmX3VuaXR0ZXN0LkNvbXBsZXhPcHRp", + "b25UeXBlMTpfCgxjb21wbGV4X29wdDISHy5nb29nbGUucHJvdG9idWYuTWVz", + "c2FnZU9wdGlvbnMY1Y/SAyABKAsyJS5wcm90b2J1Zl91bml0dGVzdC5Db21w", + "bGV4T3B0aW9uVHlwZTI6XwoMY29tcGxleF9vcHQzEh8uZ29vZ2xlLnByb3Rv", + "YnVmLk1lc3NhZ2VPcHRpb25zGO+L0gMgASgLMiUucHJvdG9idWZfdW5pdHRl", + "c3QuQ29tcGxleE9wdGlvblR5cGUzOk4KB2ZpbGVvcHQSHC5nb29nbGUucHJv", + "dG9idWYuRmlsZU9wdGlvbnMYz92wByABKAsyHC5wcm90b2J1Zl91bml0dGVz", + "dC5BZ2dyZWdhdGU6UAoGbXNnb3B0Eh8uZ29vZ2xlLnByb3RvYnVmLk1lc3Nh", + "Z2VPcHRpb25zGJjqsAcgASgLMhwucHJvdG9idWZfdW5pdHRlc3QuQWdncmVn", + "YXRlOlAKCGZpZWxkb3B0Eh0uZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9u", + "cxie9LAHIAEoCzIcLnByb3RvYnVmX3VuaXR0ZXN0LkFnZ3JlZ2F0ZTpOCgdl", + "bnVtb3B0EhwuZ29vZ2xlLnByb3RvYnVmLkVudW1PcHRpb25zGNKCsQcgASgL", + "MhwucHJvdG9idWZfdW5pdHRlc3QuQWdncmVnYXRlOlYKCmVudW12YWxvcHQS", + "IS5nb29nbGUucHJvdG9idWYuRW51bVZhbHVlT3B0aW9ucxjJn7EHIAEoCzIc", + "LnByb3RvYnVmX3VuaXR0ZXN0LkFnZ3JlZ2F0ZTpUCgpzZXJ2aWNlb3B0Eh8u", + "Z29vZ2xlLnByb3RvYnVmLlNlcnZpY2VPcHRpb25zGLnvsQcgASgLMhwucHJv", + "dG9idWZfdW5pdHRlc3QuQWdncmVnYXRlOlIKCW1ldGhvZG9wdBIeLmdvb2ds", + "ZS5wcm90b2J1Zi5NZXRob2RPcHRpb25zGInpsgcgASgLMhwucHJvdG9idWZf", + "dW5pdHRlc3QuQWdncmVnYXRlQlWqAhpVbml0VGVzdC5Jc3N1ZXMuVGVzdFBy", + "b3Rvc/DowR3qrcDlJPrshTsqCGQSDkZpbGVBbm5vdGF0aW9uGhYSFE5lc3Rl", + "ZEZpbGVBbm5vdGF0aW9uYgZwcm90bzM=")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { pbr::FileDescriptor.DescriptorProtoFileDescriptor, }, + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::UnitTest.Issues.TestProtos.MethodOpt1), typeof(global::UnitTest.Issues.TestProtos.AggregateEnum), }, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.TestMessageWithCustomOptions), global::UnitTest.Issues.TestProtos.TestMessageWithCustomOptions.Parser, new[]{ "Field1", "OneofField" }, new[]{ "AnOneof" }, new[]{ typeof(global::UnitTest.Issues.TestProtos.TestMessageWithCustomOptions.Types.AnEnum) }, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.CustomOptionFooRequest), global::UnitTest.Issues.TestProtos.CustomOptionFooRequest.Parser, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.CustomOptionFooResponse), global::UnitTest.Issues.TestProtos.CustomOptionFooResponse.Parser, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.CustomOptionFooClientMessage), global::UnitTest.Issues.TestProtos.CustomOptionFooClientMessage.Parser, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.CustomOptionFooServerMessage), global::UnitTest.Issues.TestProtos.CustomOptionFooServerMessage.Parser, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.DummyMessageContainingEnum), global::UnitTest.Issues.TestProtos.DummyMessageContainingEnum.Parser, null, null, new[]{ typeof(global::UnitTest.Issues.TestProtos.DummyMessageContainingEnum.Types.TestEnumType) }, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.DummyMessageInvalidAsOptionType), global::UnitTest.Issues.TestProtos.DummyMessageInvalidAsOptionType.Parser, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.CustomOptionMinIntegerValues), global::UnitTest.Issues.TestProtos.CustomOptionMinIntegerValues.Parser, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.CustomOptionMaxIntegerValues), global::UnitTest.Issues.TestProtos.CustomOptionMaxIntegerValues.Parser, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.CustomOptionOtherValues), global::UnitTest.Issues.TestProtos.CustomOptionOtherValues.Parser, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.SettingRealsFromPositiveInts), global::UnitTest.Issues.TestProtos.SettingRealsFromPositiveInts.Parser, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.SettingRealsFromNegativeInts), global::UnitTest.Issues.TestProtos.SettingRealsFromNegativeInts.Parser, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ComplexOptionType1), global::UnitTest.Issues.TestProtos.ComplexOptionType1.Parser, new[]{ "Foo", "Foo2", "Foo3", "Foo4" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ComplexOptionType2), global::UnitTest.Issues.TestProtos.ComplexOptionType2.Parser, new[]{ "Bar", "Baz", "Fred", "Barney" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4), global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.Parser, new[]{ "Waldo" }, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.ComplexOptionType3), global::UnitTest.Issues.TestProtos.ComplexOptionType3.Parser, new[]{ "Qux" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.VariousComplexOptions), global::UnitTest.Issues.TestProtos.VariousComplexOptions.Parser, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.Aggregate), global::UnitTest.Issues.TestProtos.Aggregate.Parser, new[]{ "I", "S", "Sub" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.AggregateMessage), global::UnitTest.Issues.TestProtos.AggregateMessage.Parser, new[]{ "Fieldname" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NestedOptionType), global::UnitTest.Issues.TestProtos.NestedOptionType.Parser, null, null, new[]{ typeof(global::UnitTest.Issues.TestProtos.NestedOptionType.Types.NestedEnum) }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.NestedOptionType.Types.NestedMessage), global::UnitTest.Issues.TestProtos.NestedOptionType.Types.NestedMessage.Parser, new[]{ "NestedField" }, null, null, null)}) + })); + } + #endregion + + } + #region Enums + public enum MethodOpt1 { + [pbr::OriginalName("METHODOPT1_UNSPECIFIED")] Unspecified = 0, + [pbr::OriginalName("METHODOPT1_VAL1")] Val1 = 1, + [pbr::OriginalName("METHODOPT1_VAL2")] Val2 = 2, + } + + public enum AggregateEnum { + [pbr::OriginalName("UNSPECIFIED")] Unspecified = 0, + [pbr::OriginalName("VALUE")] Value = 1, + } + + #endregion + + #region Messages + /// + /// A test message with custom options at all possible locations (and also some + /// regular options, to make sure they interact nicely). + /// + public sealed partial class TestMessageWithCustomOptions : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestMessageWithCustomOptions()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMessageWithCustomOptions() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMessageWithCustomOptions(TestMessageWithCustomOptions other) : this() { + field1_ = other.field1_; + switch (other.AnOneofCase) { + case AnOneofOneofCase.OneofField: + OneofField = other.OneofField; + break; + } + + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public TestMessageWithCustomOptions Clone() { + return new TestMessageWithCustomOptions(this); + } + + /// Field number for the "field1" field. + public const int Field1FieldNumber = 1; + private string field1_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Field1 { + get { return field1_; } + set { + field1_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "oneof_field" field. + public const int OneofFieldFieldNumber = 2; + /// + /// See https://github.com/google/protobuf/issues/2316 + /// option (oneof_opt1) = -99; + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int OneofField { + get { return anOneofCase_ == AnOneofOneofCase.OneofField ? (int) anOneof_ : 0; } + set { + anOneof_ = value; + anOneofCase_ = AnOneofOneofCase.OneofField; + } + } + + private object anOneof_; + /// Enum of possible cases for the "AnOneof" oneof. + public enum AnOneofOneofCase { + None = 0, + OneofField = 2, + } + private AnOneofOneofCase anOneofCase_ = AnOneofOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public AnOneofOneofCase AnOneofCase { + get { return anOneofCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void ClearAnOneof() { + anOneofCase_ = AnOneofOneofCase.None; + anOneof_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as TestMessageWithCustomOptions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(TestMessageWithCustomOptions other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Field1 != other.Field1) return false; + if (OneofField != other.OneofField) return false; + if (AnOneofCase != other.AnOneofCase) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Field1.Length != 0) hash ^= Field1.GetHashCode(); + if (anOneofCase_ == AnOneofOneofCase.OneofField) hash ^= OneofField.GetHashCode(); + hash ^= (int) anOneofCase_; + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (Field1.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Field1); + } + if (anOneofCase_ == AnOneofOneofCase.OneofField) { + output.WriteRawTag(16); + output.WriteInt32(OneofField); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Field1.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Field1); + } + if (anOneofCase_ == AnOneofOneofCase.OneofField) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(OneofField); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(TestMessageWithCustomOptions other) { + if (other == null) { + return; + } + if (other.Field1.Length != 0) { + Field1 = other.Field1; + } + switch (other.AnOneofCase) { + case AnOneofOneofCase.OneofField: + OneofField = other.OneofField; + break; + } + + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + Field1 = input.ReadString(); + break; + } + case 16: { + OneofField = input.ReadInt32(); + break; + } + } + } + } + + #region Nested types + /// Container for nested types declared in the TestMessageWithCustomOptions message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public enum AnEnum { + [pbr::OriginalName("ANENUM_UNSPECIFIED")] Unspecified = 0, + [pbr::OriginalName("ANENUM_VAL1")] Val1 = 1, + [pbr::OriginalName("ANENUM_VAL2")] Val2 = 2, + } + + } + #endregion + + } + + /// + /// 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 { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionFooRequest()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooRequest(CustomOptionFooRequest other) : this() { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooRequest Clone() { + return new CustomOptionFooRequest(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as CustomOptionFooRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(CustomOptionFooRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(CustomOptionFooRequest other) { + if (other == null) { + return; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + } + } + } + + } + + public sealed partial class CustomOptionFooResponse : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionFooResponse()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooResponse(CustomOptionFooResponse other) : this() { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooResponse Clone() { + return new CustomOptionFooResponse(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as CustomOptionFooResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(CustomOptionFooResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(CustomOptionFooResponse other) { + if (other == null) { + return; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + } + } + } + + } + + public sealed partial class CustomOptionFooClientMessage : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionFooClientMessage()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooClientMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooClientMessage(CustomOptionFooClientMessage other) : this() { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooClientMessage Clone() { + return new CustomOptionFooClientMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as CustomOptionFooClientMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(CustomOptionFooClientMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(CustomOptionFooClientMessage other) { + if (other == null) { + return; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + } + } + } + + } + + public sealed partial class CustomOptionFooServerMessage : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionFooServerMessage()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[4]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooServerMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooServerMessage(CustomOptionFooServerMessage other) : this() { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionFooServerMessage Clone() { + return new CustomOptionFooServerMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as CustomOptionFooServerMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(CustomOptionFooServerMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(CustomOptionFooServerMessage other) { + if (other == null) { + return; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + } + } + } + + } + + public sealed partial class DummyMessageContainingEnum : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DummyMessageContainingEnum()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[5]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DummyMessageContainingEnum() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DummyMessageContainingEnum(DummyMessageContainingEnum other) : this() { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DummyMessageContainingEnum Clone() { + return new DummyMessageContainingEnum(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as DummyMessageContainingEnum); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(DummyMessageContainingEnum other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(DummyMessageContainingEnum other) { + if (other == null) { + return; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + } + } + } + + #region Nested types + /// Container for nested types declared in the DummyMessageContainingEnum message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public enum TestEnumType { + [pbr::OriginalName("TEST_OPTION_ENUM_UNSPECIFIED")] TestOptionEnumUnspecified = 0, + [pbr::OriginalName("TEST_OPTION_ENUM_TYPE1")] TestOptionEnumType1 = 22, + [pbr::OriginalName("TEST_OPTION_ENUM_TYPE2")] TestOptionEnumType2 = -23, + } + + } + #endregion + + } + + public sealed partial class DummyMessageInvalidAsOptionType : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DummyMessageInvalidAsOptionType()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[6]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DummyMessageInvalidAsOptionType() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DummyMessageInvalidAsOptionType(DummyMessageInvalidAsOptionType other) : this() { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public DummyMessageInvalidAsOptionType Clone() { + return new DummyMessageInvalidAsOptionType(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as DummyMessageInvalidAsOptionType); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(DummyMessageInvalidAsOptionType other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(DummyMessageInvalidAsOptionType other) { + if (other == null) { + return; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + } + } + } + + } + + public sealed partial class CustomOptionMinIntegerValues : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionMinIntegerValues()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[7]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionMinIntegerValues() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionMinIntegerValues(CustomOptionMinIntegerValues other) : this() { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionMinIntegerValues Clone() { + return new CustomOptionMinIntegerValues(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as CustomOptionMinIntegerValues); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(CustomOptionMinIntegerValues other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(CustomOptionMinIntegerValues other) { + if (other == null) { + return; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + } + } + } + + } + + public sealed partial class CustomOptionMaxIntegerValues : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionMaxIntegerValues()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[8]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionMaxIntegerValues() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionMaxIntegerValues(CustomOptionMaxIntegerValues other) : this() { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionMaxIntegerValues Clone() { + return new CustomOptionMaxIntegerValues(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as CustomOptionMaxIntegerValues); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(CustomOptionMaxIntegerValues other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(CustomOptionMaxIntegerValues other) { + if (other == null) { + return; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + } + } + } + + } + + public sealed partial class CustomOptionOtherValues : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomOptionOtherValues()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[9]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionOtherValues() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionOtherValues(CustomOptionOtherValues other) : this() { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomOptionOtherValues Clone() { + return new CustomOptionOtherValues(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as CustomOptionOtherValues); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(CustomOptionOtherValues other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(CustomOptionOtherValues other) { + if (other == null) { + return; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + } + } + } + + } + + public sealed partial class SettingRealsFromPositiveInts : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SettingRealsFromPositiveInts()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[10]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SettingRealsFromPositiveInts() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SettingRealsFromPositiveInts(SettingRealsFromPositiveInts other) : this() { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SettingRealsFromPositiveInts Clone() { + return new SettingRealsFromPositiveInts(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as SettingRealsFromPositiveInts); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(SettingRealsFromPositiveInts other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(SettingRealsFromPositiveInts other) { + if (other == null) { + return; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + } + } + } + + } + + public sealed partial class SettingRealsFromNegativeInts : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SettingRealsFromNegativeInts()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[11]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SettingRealsFromNegativeInts() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SettingRealsFromNegativeInts(SettingRealsFromNegativeInts other) : this() { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public SettingRealsFromNegativeInts Clone() { + return new SettingRealsFromNegativeInts(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as SettingRealsFromNegativeInts); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(SettingRealsFromNegativeInts other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(SettingRealsFromNegativeInts other) { + if (other == null) { + return; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + } + } + } + + } + + public sealed partial class ComplexOptionType1 : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ComplexOptionType1()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[12]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType1() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType1(ComplexOptionType1 other) : this() { + foo_ = other.foo_; + foo2_ = other.foo2_; + foo3_ = other.foo3_; + foo4_ = other.foo4_.Clone(); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType1 Clone() { + return new ComplexOptionType1(this); + } + + /// Field number for the "foo" field. + public const int FooFieldNumber = 1; + private int foo_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Foo { + get { return foo_; } + set { + foo_ = value; + } + } + + /// Field number for the "foo2" field. + public const int Foo2FieldNumber = 2; + private int foo2_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Foo2 { + get { return foo2_; } + set { + foo2_ = value; + } + } + + /// Field number for the "foo3" field. + public const int Foo3FieldNumber = 3; + private int foo3_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Foo3 { + get { return foo3_; } + set { + foo3_ = value; + } + } + + /// Field number for the "foo4" field. + public const int Foo4FieldNumber = 4; + private static readonly pb::FieldCodec _repeated_foo4_codec + = pb::FieldCodec.ForInt32(34); + private readonly pbc::RepeatedField foo4_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Foo4 { + get { return foo4_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ComplexOptionType1); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ComplexOptionType1 other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Foo != other.Foo) return false; + if (Foo2 != other.Foo2) return false; + if (Foo3 != other.Foo3) return false; + if(!foo4_.Equals(other.foo4_)) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Foo != 0) hash ^= Foo.GetHashCode(); + if (Foo2 != 0) hash ^= Foo2.GetHashCode(); + if (Foo3 != 0) hash ^= Foo3.GetHashCode(); + hash ^= foo4_.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (Foo != 0) { + output.WriteRawTag(8); + output.WriteInt32(Foo); + } + if (Foo2 != 0) { + output.WriteRawTag(16); + output.WriteInt32(Foo2); + } + if (Foo3 != 0) { + output.WriteRawTag(24); + output.WriteInt32(Foo3); + } + foo4_.WriteTo(output, _repeated_foo4_codec); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Foo != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Foo); + } + if (Foo2 != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Foo2); + } + if (Foo3 != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Foo3); + } + size += foo4_.CalculateSize(_repeated_foo4_codec); + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ComplexOptionType1 other) { + if (other == null) { + return; + } + if (other.Foo != 0) { + Foo = other.Foo; + } + if (other.Foo2 != 0) { + Foo2 = other.Foo2; + } + if (other.Foo3 != 0) { + Foo3 = other.Foo3; + } + foo4_.Add(other.foo4_); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 8: { + Foo = input.ReadInt32(); + break; + } + case 16: { + Foo2 = input.ReadInt32(); + break; + } + case 24: { + Foo3 = input.ReadInt32(); + break; + } + case 34: + case 32: { + foo4_.AddEntriesFrom(input, _repeated_foo4_codec); + break; + } + } + } + } + + } + + public sealed partial class ComplexOptionType2 : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ComplexOptionType2()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[13]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType2() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType2(ComplexOptionType2 other) : this() { + Bar = other.bar_ != null ? other.Bar.Clone() : null; + baz_ = other.baz_; + Fred = other.fred_ != null ? other.Fred.Clone() : null; + barney_ = other.barney_.Clone(); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType2 Clone() { + return new ComplexOptionType2(this); + } + + /// Field number for the "bar" field. + public const int BarFieldNumber = 1; + private global::UnitTest.Issues.TestProtos.ComplexOptionType1 bar_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::UnitTest.Issues.TestProtos.ComplexOptionType1 Bar { + get { return bar_; } + set { + bar_ = value; + } + } + + /// Field number for the "baz" field. + public const int BazFieldNumber = 2; + private int baz_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Baz { + get { return baz_; } + set { + baz_ = value; + } + } + + /// Field number for the "fred" field. + public const int FredFieldNumber = 3; + private global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4 fred_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4 Fred { + get { return fred_; } + set { + fred_ = value; + } + } + + /// Field number for the "barney" field. + public const int BarneyFieldNumber = 4; + private static readonly pb::FieldCodec _repeated_barney_codec + = pb::FieldCodec.ForMessage(34, global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.Parser); + private readonly pbc::RepeatedField barney_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pbc::RepeatedField Barney { + get { return barney_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ComplexOptionType2); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ComplexOptionType2 other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Bar, other.Bar)) return false; + if (Baz != other.Baz) return false; + if (!object.Equals(Fred, other.Fred)) return false; + if(!barney_.Equals(other.barney_)) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (bar_ != null) hash ^= Bar.GetHashCode(); + if (Baz != 0) hash ^= Baz.GetHashCode(); + if (fred_ != null) hash ^= Fred.GetHashCode(); + hash ^= barney_.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (bar_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Bar); + } + if (Baz != 0) { + output.WriteRawTag(16); + output.WriteInt32(Baz); + } + if (fred_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Fred); + } + barney_.WriteTo(output, _repeated_barney_codec); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (bar_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Bar); + } + if (Baz != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Baz); + } + if (fred_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Fred); + } + size += barney_.CalculateSize(_repeated_barney_codec); + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ComplexOptionType2 other) { + if (other == null) { + return; + } + if (other.bar_ != null) { + if (bar_ == null) { + bar_ = new global::UnitTest.Issues.TestProtos.ComplexOptionType1(); + } + Bar.MergeFrom(other.Bar); + } + if (other.Baz != 0) { + Baz = other.Baz; + } + if (other.fred_ != null) { + if (fred_ == null) { + fred_ = new global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4(); + } + Fred.MergeFrom(other.Fred); + } + barney_.Add(other.barney_); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + if (bar_ == null) { + bar_ = new global::UnitTest.Issues.TestProtos.ComplexOptionType1(); + } + input.ReadMessage(bar_); + break; + } + case 16: { + Baz = input.ReadInt32(); + break; + } + case 26: { + if (fred_ == null) { + fred_ = new global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4(); + } + input.ReadMessage(fred_); + break; + } + case 34: { + barney_.AddEntriesFrom(input, _repeated_barney_codec); + break; + } + } + } + } + + #region Nested types + /// Container 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 { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ComplexOptionType4()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.ComplexOptionType2.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType4() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType4(ComplexOptionType4 other) : this() { + waldo_ = other.waldo_; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType4 Clone() { + return new ComplexOptionType4(this); + } + + /// Field number for the "waldo" field. + public const int WaldoFieldNumber = 1; + private int waldo_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Waldo { + get { return waldo_; } + set { + waldo_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ComplexOptionType4); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ComplexOptionType4 other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Waldo != other.Waldo) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Waldo != 0) hash ^= Waldo.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (Waldo != 0) { + output.WriteRawTag(8); + output.WriteInt32(Waldo); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Waldo != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Waldo); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ComplexOptionType4 other) { + if (other == null) { + return; + } + if (other.Waldo != 0) { + Waldo = other.Waldo; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 8: { + Waldo = input.ReadInt32(); + break; + } + } + } + } + + } + + } + #endregion + + } + + public sealed partial class ComplexOptionType3 : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ComplexOptionType3()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[14]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType3() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType3(ComplexOptionType3 other) : this() { + qux_ = other.qux_; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public ComplexOptionType3 Clone() { + return new ComplexOptionType3(this); + } + + /// Field number for the "qux" field. + public const int QuxFieldNumber = 1; + private int qux_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Qux { + get { return qux_; } + set { + qux_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as ComplexOptionType3); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(ComplexOptionType3 other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Qux != other.Qux) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Qux != 0) hash ^= Qux.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (Qux != 0) { + output.WriteRawTag(8); + output.WriteInt32(Qux); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Qux != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Qux); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(ComplexOptionType3 other) { + if (other == null) { + return; + } + if (other.Qux != 0) { + Qux = other.Qux; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 8: { + Qux = input.ReadInt32(); + break; + } + } + } + } + + } + + /// + /// Note that we try various different ways of naming the same extension. + /// + public sealed partial class VariousComplexOptions : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new VariousComplexOptions()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[15]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public VariousComplexOptions() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public VariousComplexOptions(VariousComplexOptions other) : this() { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public VariousComplexOptions Clone() { + return new VariousComplexOptions(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as VariousComplexOptions); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(VariousComplexOptions other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(VariousComplexOptions other) { + if (other == null) { + return; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + } + } + } + + } + + /// + /// A helper type used to test aggregate option parsing + /// + public sealed partial class Aggregate : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Aggregate()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[16]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Aggregate() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Aggregate(Aggregate other) : this() { + i_ = other.i_; + s_ = other.s_; + Sub = other.sub_ != null ? other.Sub.Clone() : null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Aggregate Clone() { + return new Aggregate(this); + } + + /// Field number for the "i" field. + public const int IFieldNumber = 1; + private int i_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int I { + get { return i_; } + set { + i_ = value; + } + } + + /// Field number for the "s" field. + public const int SFieldNumber = 2; + private string s_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string S { + get { return s_; } + set { + s_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "sub" field. + public const int SubFieldNumber = 3; + private global::UnitTest.Issues.TestProtos.Aggregate sub_; + /// + /// A nested object + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::UnitTest.Issues.TestProtos.Aggregate Sub { + get { return sub_; } + set { + sub_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Aggregate); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Aggregate other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (I != other.I) return false; + if (S != other.S) return false; + if (!object.Equals(Sub, other.Sub)) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (I != 0) hash ^= I.GetHashCode(); + if (S.Length != 0) hash ^= S.GetHashCode(); + if (sub_ != null) hash ^= Sub.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (I != 0) { + output.WriteRawTag(8); + output.WriteInt32(I); + } + if (S.Length != 0) { + output.WriteRawTag(18); + output.WriteString(S); + } + if (sub_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Sub); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (I != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(I); + } + if (S.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(S); + } + if (sub_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Sub); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Aggregate other) { + if (other == null) { + return; + } + if (other.I != 0) { + I = other.I; + } + if (other.S.Length != 0) { + S = other.S; + } + if (other.sub_ != null) { + if (sub_ == null) { + sub_ = new global::UnitTest.Issues.TestProtos.Aggregate(); + } + Sub.MergeFrom(other.Sub); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 8: { + I = input.ReadInt32(); + break; + } + case 18: { + S = input.ReadString(); + break; + } + case 26: { + if (sub_ == null) { + sub_ = new global::UnitTest.Issues.TestProtos.Aggregate(); + } + input.ReadMessage(sub_); + break; + } + } + } + } + + } + + public sealed partial class AggregateMessage : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new AggregateMessage()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[17]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public AggregateMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public AggregateMessage(AggregateMessage other) : this() { + fieldname_ = other.fieldname_; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public AggregateMessage Clone() { + return new AggregateMessage(this); + } + + /// Field number for the "fieldname" field. + public const int FieldnameFieldNumber = 1; + private int fieldname_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Fieldname { + get { return fieldname_; } + set { + fieldname_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as AggregateMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(AggregateMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Fieldname != other.Fieldname) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Fieldname != 0) hash ^= Fieldname.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (Fieldname != 0) { + output.WriteRawTag(8); + output.WriteInt32(Fieldname); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Fieldname != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Fieldname); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(AggregateMessage other) { + if (other == null) { + return; + } + if (other.Fieldname != 0) { + Fieldname = other.Fieldname; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 8: { + Fieldname = input.ReadInt32(); + break; + } + } + } + } + + } + + /// + /// Test custom options for nested type. + /// + public sealed partial class NestedOptionType : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedOptionType()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Reflection.Descriptor.MessageTypes[18]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedOptionType() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedOptionType(NestedOptionType other) : this() { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedOptionType Clone() { + return new NestedOptionType(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedOptionType); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedOptionType other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedOptionType other) { + if (other == null) { + return; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + } + } + } + + #region Nested types + /// Container for nested types declared in the NestedOptionType message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static partial class Types { + public enum NestedEnum { + [pbr::OriginalName("UNSPECIFIED")] Unspecified = 0, + [pbr::OriginalName("NESTED_ENUM_VALUE")] Value = 1, + } + + public sealed partial class NestedMessage : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NestedMessage()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::UnitTest.Issues.TestProtos.NestedOptionType.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage(NestedMessage other) : this() { + nestedField_ = other.nestedField_; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public NestedMessage Clone() { + return new NestedMessage(this); + } + + /// Field number for the "nested_field" field. + public const int NestedFieldFieldNumber = 1; + private int nestedField_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int NestedField { + get { return nestedField_; } + set { + nestedField_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as NestedMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(NestedMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (NestedField != other.NestedField) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (NestedField != 0) hash ^= NestedField.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (NestedField != 0) { + output.WriteRawTag(8); + output.WriteInt32(NestedField); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (NestedField != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(NestedField); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(NestedMessage other) { + if (other == null) { + return; + } + if (other.NestedField != 0) { + NestedField = other.NestedField; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 8: { + NestedField = input.ReadInt32(); + break; + } + } + } + } + + } + + } + #endregion + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/csharp/src/Google.Protobuf/Reflection/CustomOptions.cs b/csharp/src/Google.Protobuf/Reflection/CustomOptions.cs new file mode 100644 index 00000000..88b3ec00 --- /dev/null +++ b/csharp/src/Google.Protobuf/Reflection/CustomOptions.cs @@ -0,0 +1,390 @@ +#region Copyright notice and license +// Protocol Buffers - Google's data interchange format +// Copyright 2017 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.Collections.Generic; + +namespace Google.Protobuf.Reflection +{ + /// + /// Container for a set of custom options specified within a message, field etc. + /// + /// + /// + /// This type is publicly immutable, but internally mutable. It is only populated + /// by the descriptor parsing code - by the time any user code is able to see an instance, + /// it will be fully initialized. + /// + /// + /// If an option is requested using the incorrect method, an answer may still be returned: all + /// of the numeric types are represented internally using 64-bit integers, for example. It is up to + /// the caller to ensure that they make the appropriate method call for the option they're interested in. + /// Note that enum options are simply stored as integers, so the value should be fetched using + /// and then cast appropriately. + /// + /// + /// Repeated options are currently not supported. Asking for a single value of an option + /// which was actually repeated will return the last value, except for message types where + /// all the set values are merged together. + /// + /// + public sealed class CustomOptions + { + /// + /// Singleton for all descriptors with an empty set of options. + /// + internal static readonly CustomOptions Empty = new CustomOptions(); + + /// + /// A sequence of values per field. This needs to be per field rather than per tag to allow correct deserialization + /// of repeated fields which could be "int, ByteString, int" - unlikely as that is. The fact that values are boxed + /// is unfortunate; we might be able to use a struct instead, and we could combine uint and ulong values. + /// + private readonly Dictionary> valuesByField = new Dictionary>(); + + private CustomOptions() { } + + /// + /// Retrieves a Boolean value for the specified option field. + /// + /// The field to fetch the value for. + /// The output variable to populate. + /// true if a suitable value for the field was found; false otherwise. + public bool TryGetBool(int field, out bool value) + { + ulong? tmp = GetLastNumericValue(field); + value = tmp == 1UL; + return tmp != null; + } + + /// + /// Retrieves a signed 32-bit integer value for the specified option field. + /// + /// The field to fetch the value for. + /// The output variable to populate. + /// true if a suitable value for the field was found; false otherwise. + public bool TryGetInt32(int field, out int value) + { + ulong? tmp = GetLastNumericValue(field); + value = (int) tmp.GetValueOrDefault(); + return tmp != null; + } + + /// + /// Retrieves a signed 64-bit integer value for the specified option field. + /// + /// The field to fetch the value for. + /// The output variable to populate. + /// true if a suitable value for the field was found; false otherwise. + public bool TryGetInt64(int field, out long value) + { + ulong? tmp = GetLastNumericValue(field); + value = (long) tmp.GetValueOrDefault(); + return tmp != null; + } + + /// + /// Retrieves an unsigned 32-bit integer value for the specified option field, + /// assuming a fixed-length representation. + /// + /// The field to fetch the value for. + /// The output variable to populate. + /// true if a suitable value for the field was found; false otherwise. + public bool TryGetFixed32(int field, out uint value) => TryGetUInt32(field, out value); + + /// + /// Retrieves an unsigned 64-bit integer value for the specified option field, + /// assuming a fixed-length representation. + /// + /// The field to fetch the value for. + /// The output variable to populate. + /// true if a suitable value for the field was found; false otherwise. + public bool TryGetFixed64(int field, out ulong value) => TryGetUInt64(field, out value); + + /// + /// Retrieves a signed 32-bit integer value for the specified option field, + /// assuming a fixed-length representation. + /// + /// The field to fetch the value for. + /// The output variable to populate. + /// true if a suitable value for the field was found; false otherwise. + public bool TryGetSFixed32(int field, out int value) => TryGetInt32(field, out value); + + /// + /// Retrieves a signed 64-bit integer value for the specified option field, + /// assuming a fixed-length representation. + /// + /// The field to fetch the value for. + /// The output variable to populate. + /// true if a suitable value for the field was found; false otherwise. + public bool TryGetSFixed64(int field, out long value) => TryGetInt64(field, out value); + + /// + /// Retrieves a signed 32-bit integer value for the specified option field, + /// assuming a zigzag encoding. + /// + /// The field to fetch the value for. + /// The output variable to populate. + /// true if a suitable value for the field was found; false otherwise. + public bool TryGetSInt32(int field, out int value) + { + ulong? tmp = GetLastNumericValue(field); + value = CodedInputStream.DecodeZigZag32((uint) tmp.GetValueOrDefault()); + return tmp != null; + } + + /// + /// Retrieves a signed 64-bit integer value for the specified option field, + /// assuming a zigzag encoding. + /// + /// The field to fetch the value for. + /// The output variable to populate. + /// true if a suitable value for the field was found; false otherwise. + public bool TryGetSInt64(int field, out long value) + { + ulong? tmp = GetLastNumericValue(field); + value = CodedInputStream.DecodeZigZag64(tmp.GetValueOrDefault()); + return tmp != null; + } + + /// + /// Retrieves an unsigned 32-bit integer value for the specified option field. + /// + /// The field to fetch the value for. + /// The output variable to populate. + /// true if a suitable value for the field was found; false otherwise. + public bool TryGetUInt32(int field, out uint value) + { + ulong? tmp = GetLastNumericValue(field); + value = (uint) tmp.GetValueOrDefault(); + return tmp != null; + } + + /// + /// Retrieves an unsigned 64-bit integer value for the specified option field. + /// + /// The field to fetch the value for. + /// The output variable to populate. + /// true if a suitable value for the field was found; false otherwise. + public bool TryGetUInt64(int field, out ulong value) + { + ulong? tmp = GetLastNumericValue(field); + value = tmp.GetValueOrDefault(); + return tmp != null; + } + + /// + /// Retrieves a 32-bit floating point value for the specified option field. + /// + /// The field to fetch the value for. + /// The output variable to populate. + /// true if a suitable value for the field was found; false otherwise. + public bool TryGetFloat(int field, out float value) + { + ulong? tmp = GetLastNumericValue(field); + int int32 = (int) tmp.GetValueOrDefault(); + byte[] bytes = BitConverter.GetBytes(int32); + value = BitConverter.ToSingle(bytes, 0); + return tmp != null; + } + + /// + /// Retrieves a 64-bit floating point value for the specified option field. + /// + /// The field to fetch the value for. + /// The output variable to populate. + /// true if a suitable value for the field was found; false otherwise. + public bool TryGetDouble(int field, out double value) + { + ulong? tmp = GetLastNumericValue(field); + value = BitConverter.Int64BitsToDouble((long) tmp.GetValueOrDefault()); + return tmp != null; + } + + /// + /// Retrieves a string value for the specified option field. + /// + /// The field to fetch the value for. + /// The output variable to populate. + /// true if a suitable value for the field was found; false otherwise. + public bool TryGetString(int field, out string value) + { + ByteString bytes = GetLastByteStringValue(field); + value = bytes?.ToStringUtf8(); + return bytes != null; + } + + /// + /// Retrieves a bytes value for the specified option field. + /// + /// The field to fetch the value for. + /// The output variable to populate. + /// true if a suitable value for the field was found; false otherwise. + public bool TryGetBytes(int field, out ByteString value) + { + ByteString bytes = GetLastByteStringValue(field); + value = bytes; + return bytes != null; + } + + /// + /// Retrieves a message value for the specified option field. + /// + /// The field to fetch the value for. + /// The output variable to populate. + /// true if a suitable value for the field was found; false otherwise. + public bool TryGetMessage(int field, out T value) where T : class, IMessage, new() + { + value = null; + List values; + if (!valuesByField.TryGetValue(field, out values)) + { + return false; + } + foreach (FieldValue fieldValue in values) + { + if (fieldValue.ByteString != null) + { + if (value == null) + { + value = new T(); + } + value.MergeFrom(fieldValue.ByteString); + } + } + return value != null; + } + + private ulong? GetLastNumericValue(int field) + { + List values; + if (!valuesByField.TryGetValue(field, out values)) + { + return null; + } + for (int i = values.Count - 1; i >= 0; i--) + { + // A non-bytestring value is a numeric value + if (values[i].ByteString == null) + { + return values[i].Number; + } + } + return null; + } + + private ByteString GetLastByteStringValue(int field) + { + List values; + if (!valuesByField.TryGetValue(field, out values)) + { + return null; + } + for (int i = values.Count - 1; i >= 0; i--) + { + if (values[i].ByteString != null) + { + return values[i].ByteString; + } + } + return null; + } + + /// + /// Reads an unknown field, either parsing it and storing it or skipping it. + /// + /// + /// If the current set of options is empty and we manage to read a field, a new set of options + /// will be created and returned. Otherwise, the return value is this. This allows + /// us to start with a singleton empty set of options and just create new ones where necessary. + /// + /// Input stream to read from. + /// The resulting set of custom options, either this or a new set. + internal CustomOptions ReadOrSkipUnknownField(CodedInputStream input) + { + var tag = input.LastTag; + var field = WireFormat.GetTagFieldNumber(tag); + switch (WireFormat.GetTagWireType(tag)) + { + case WireFormat.WireType.LengthDelimited: + return AddValue(field, new FieldValue(input.ReadBytes())); + case WireFormat.WireType.Fixed32: + return AddValue(field, new FieldValue(input.ReadFixed32())); + case WireFormat.WireType.Fixed64: + return AddValue(field, new FieldValue(input.ReadFixed64())); + case WireFormat.WireType.Varint: + return AddValue(field, new FieldValue(input.ReadRawVarint64())); + // For StartGroup, EndGroup or any wire format we don't understand, + // just use the normal behavior (call SkipLastField). + default: + input.SkipLastField(); + return this; + } + } + + private CustomOptions AddValue(int field, FieldValue value) + { + var ret = valuesByField.Count == 0 ? new CustomOptions() : this; + List valuesForField; + if (!ret.valuesByField.TryGetValue(field, out valuesForField)) + { + // Expect almost all + valuesForField = new List(1); + ret.valuesByField[field] = valuesForField; + } + valuesForField.Add(value); + return ret; + } + + /// + /// All field values can be stored as a byte string or a 64-bit integer. + /// This struct avoids unnecessary boxing. + /// + private struct FieldValue + { + internal ulong Number { get; } + internal ByteString ByteString { get; } + + internal FieldValue(ulong number) + { + Number = number; + ByteString = null; + } + + internal FieldValue(ByteString byteString) + { + Number = 0; + ByteString = byteString; + } + } + } +} diff --git a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs index d743e516..ceab9b06 100644 --- a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs @@ -2779,6 +2779,8 @@ namespace Google.Protobuf.Reflection { get { return Descriptor; } } + internal CustomOptions CustomOptions{ get; private set; } = CustomOptions.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public FileOptions() { OnConstruction(); @@ -3299,7 +3301,7 @@ namespace Google.Protobuf.Reflection { while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + CustomOptions = CustomOptions.ReadOrSkipUnknownField(input); break; case 10: { JavaPackage = input.ReadString(); @@ -3411,6 +3413,8 @@ namespace Google.Protobuf.Reflection { get { return Descriptor; } } + internal CustomOptions CustomOptions{ get; private set; } = CustomOptions.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public MessageOptions() { OnConstruction(); @@ -3646,7 +3650,7 @@ namespace Google.Protobuf.Reflection { while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + CustomOptions = CustomOptions.ReadOrSkipUnknownField(input); break; case 8: { MessageSetWireFormat = input.ReadBool(); @@ -3689,6 +3693,8 @@ namespace Google.Protobuf.Reflection { get { return Descriptor; } } + internal CustomOptions CustomOptions{ get; private set; } = CustomOptions.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public FieldOptions() { OnConstruction(); @@ -3980,7 +3986,7 @@ namespace Google.Protobuf.Reflection { while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + CustomOptions = CustomOptions.ReadOrSkipUnknownField(input); break; case 8: { ctype_ = (global::Google.Protobuf.Reflection.FieldOptions.Types.CType) input.ReadEnum(); @@ -4062,6 +4068,8 @@ namespace Google.Protobuf.Reflection { get { return Descriptor; } } + internal CustomOptions CustomOptions{ get; private set; } = CustomOptions.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public OneofOptions() { OnConstruction(); @@ -4147,7 +4155,7 @@ namespace Google.Protobuf.Reflection { while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + CustomOptions = CustomOptions.ReadOrSkipUnknownField(input); break; case 7994: { uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec); @@ -4174,6 +4182,8 @@ namespace Google.Protobuf.Reflection { get { return Descriptor; } } + internal CustomOptions CustomOptions{ get; private set; } = CustomOptions.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public EnumOptions() { OnConstruction(); @@ -4317,7 +4327,7 @@ namespace Google.Protobuf.Reflection { while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + CustomOptions = CustomOptions.ReadOrSkipUnknownField(input); break; case 16: { AllowAlias = input.ReadBool(); @@ -4352,6 +4362,8 @@ namespace Google.Protobuf.Reflection { get { return Descriptor; } } + internal CustomOptions CustomOptions{ get; private set; } = CustomOptions.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public EnumValueOptions() { OnConstruction(); @@ -4467,7 +4479,7 @@ namespace Google.Protobuf.Reflection { while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + CustomOptions = CustomOptions.ReadOrSkipUnknownField(input); break; case 8: { Deprecated = input.ReadBool(); @@ -4498,6 +4510,8 @@ namespace Google.Protobuf.Reflection { get { return Descriptor; } } + internal CustomOptions CustomOptions{ get; private set; } = CustomOptions.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public ServiceOptions() { OnConstruction(); @@ -4613,7 +4627,7 @@ namespace Google.Protobuf.Reflection { while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + CustomOptions = CustomOptions.ReadOrSkipUnknownField(input); break; case 264: { Deprecated = input.ReadBool(); @@ -4644,6 +4658,8 @@ namespace Google.Protobuf.Reflection { get { return Descriptor; } } + internal CustomOptions CustomOptions{ get; private set; } = CustomOptions.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public MethodOptions() { OnConstruction(); @@ -4783,7 +4799,7 @@ namespace Google.Protobuf.Reflection { while ((tag = input.ReadTag()) != 0) { switch(tag) { default: - input.SkipLastField(); + CustomOptions = CustomOptions.ReadOrSkipUnknownField(input); break; case 264: { Deprecated = input.ReadBool(); diff --git a/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs index c732c93a..89c73a61 100644 --- a/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs @@ -112,5 +112,10 @@ namespace Google.Protobuf.Reflection { return File.DescriptorPool.FindSymbol(FullName + "." + name); } + + /// + /// The (possibly empty) set of custom options for this enum. + /// + public CustomOptions CustomOptions => Proto.Options?.CustomOptions ?? CustomOptions.Empty; } } \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs index b212ce96..8b838c68 100644 --- a/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs @@ -66,5 +66,10 @@ namespace Google.Protobuf.Reflection /// Returns the enum descriptor that this value is part of. /// public EnumDescriptor EnumDescriptor { get { return enumDescriptor; } } + + /// + /// The (possibly empty) set of custom options for this enum value. + /// + public CustomOptions CustomOptions => Proto.Options?.CustomOptions ?? CustomOptions.Empty; } } \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs index ed15d0e1..2a3d5c7a 100644 --- a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs @@ -250,6 +250,11 @@ namespace Google.Protobuf.Reflection } } + /// + /// The (possibly empty) set of custom options for this field. + /// + public CustomOptions CustomOptions => Proto.Options?.CustomOptions ?? CustomOptions.Empty; + /// /// Look up and cross-link all field types etc. /// diff --git a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs index 94efea9e..9124beee 100644 --- a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs @@ -329,5 +329,10 @@ namespace Google.Protobuf.Reflection /// The file descriptor for descriptor.proto. /// public static FileDescriptor DescriptorProtoFileDescriptor { get { return DescriptorReflection.Descriptor; } } + + /// + /// The (possibly empty) set of custom options for this file. + /// + public CustomOptions CustomOptions => Proto.Options?.CustomOptions ?? CustomOptions.Empty; } } diff --git a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs index 7a1cb9d5..4a0922e8 100644 --- a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs @@ -220,6 +220,11 @@ namespace Google.Protobuf.Reflection public T FindDescriptor(string name) where T : class, IDescriptor => File.DescriptorPool.FindSymbol(FullName + "." + name); + /// + /// The (possibly empty) set of custom options for this message. + /// + public CustomOptions CustomOptions => Proto.Options?.CustomOptions ?? CustomOptions.Empty; + /// /// Looks up and cross-links all fields and nested types. /// diff --git a/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs index f9539f6c..19d7f8a0 100644 --- a/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs @@ -67,6 +67,11 @@ namespace Google.Protobuf.Reflection /// public bool IsServerStreaming { get { return proto.ServerStreaming; } } + /// + /// The (possibly empty) set of custom options for this method. + /// + public CustomOptions CustomOptions => Proto.Options?.CustomOptions ?? CustomOptions.Empty; + internal MethodDescriptor(MethodDescriptorProto proto, FileDescriptor file, ServiceDescriptor parent, int index) : base(file, parent.FullName + "." + proto.Name, index) diff --git a/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs index 22020acf..5906c2e3 100644 --- a/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs @@ -90,6 +90,11 @@ namespace Google.Protobuf.Reflection /// public OneofAccessor Accessor { get { return accessor; } } + /// + /// The (possibly empty) set of custom options for this oneof. + /// + public CustomOptions CustomOptions => proto.Options?.CustomOptions ?? CustomOptions.Empty; + internal void CrossLink() { List fieldCollection = new List(); diff --git a/csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs index cc0a5010..fe5c072c 100644 --- a/csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs @@ -78,6 +78,11 @@ namespace Google.Protobuf.Reflection return File.DescriptorPool.FindSymbol(FullName + "." + name); } + /// + /// The (possibly empty) set of custom options for this service. + /// + public CustomOptions CustomOptions => Proto.Options?.CustomOptions ?? CustomOptions.Empty; + internal void CrossLink() { foreach (MethodDescriptor method in methods) diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h index 1563ca7e..c317ad0e 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.h +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h @@ -120,6 +120,22 @@ inline bool IsDescriptorProto(const FileDescriptor* descriptor) { return descriptor->name() == "google/protobuf/descriptor.proto"; } +// Determines whether the given message is an options message within descriptor.proto. +inline bool IsDescriptorOptionMessage(const Descriptor* descriptor) { + if (!IsDescriptorProto(descriptor->file())) { + return false; + } + const string name = descriptor->full_name(); + return name == "google.protobuf.FileOptions" || + name == "google.protobuf.MessageOptions" || + name == "google.protobuf.FieldOptions" || + name == "google.protobuf.OneofOptions" || + name == "google.protobuf.EnumOptions" || + name == "google.protobuf.EnumValueOptions" || + name == "google.protobuf.ServiceOptions" || + name == "google.protobuf.MethodOptions"; +} + inline bool IsWrapperType(const FieldDescriptor* descriptor) { return descriptor->type() == FieldDescriptor::TYPE_MESSAGE && descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto"; diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index b0cc6694..0f00a438 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -151,6 +151,12 @@ void MessageGenerator::Generate(io::Printer* printer) { " get { return Descriptor; }\n" "}\n" "\n"); + // CustomOptions property, only for options messages + if (IsDescriptorOptionMessage(descriptor_)) { + printer->Print( + "internal CustomOptions CustomOptions{ get; private set; } = CustomOptions.Empty;\n" + "\n"); + } // Parameterless constructor and partial OnConstruction method. WriteGeneratedCodeAttributes(printer); @@ -475,10 +481,18 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { " switch(tag) {\n"); printer->Indent(); printer->Indent(); - printer->Print( - "default:\n" - " input.SkipLastField();\n" // We're not storing the data, but we still need to consume it. - " break;\n"); + // Option messages need to store unknown fields so that options can be parsed later. + if (IsDescriptorOptionMessage(descriptor_)) { + printer->Print( + "default:\n" + " CustomOptions = CustomOptions.ReadOrSkipUnknownField(input);\n" + " break;\n"); + } else { + printer->Print( + "default:\n" + " input.SkipLastField();\n" // We're not storing the data, but we still need to consume it. + " break;\n"); + } for (int i = 0; i < fields_by_number().size(); i++) { const FieldDescriptor* field = fields_by_number()[i]; internal::WireFormatLite::WireType wt = -- cgit v1.2.3