Merge pull request #5936 from ObsidianMinor/csharp/proto2-feature/finale

C# Proto2 feature : Finale
This commit is contained in:
Jan Tattermusch 2019-09-03 12:15:39 +02:00 committed by GitHub
commit 37bf540fd0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 32216 additions and 443 deletions

View File

@ -68,9 +68,12 @@ csharp_EXTRA_DIST= \
csharp/protos/map_unittest_proto3.proto \
csharp/protos/unittest_custom_options_proto3.proto \
csharp/protos/unittest_import_public_proto3.proto \
csharp/protos/unittest_import_public.proto \
csharp/protos/unittest_import_proto3.proto \
csharp/protos/unittest_import.proto \
csharp/protos/unittest_issues.proto \
csharp/protos/unittest_proto3.proto \
csharp/protos/unittest.proto \
csharp/src/AddressBook/AddPerson.cs \
csharp/src/AddressBook/Addressbook.cs \
csharp/src/AddressBook/AddressBook.csproj \
@ -100,9 +103,11 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs \
csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs \
csharp/src/Google.Protobuf.Test/EqualityTester.cs \
csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs \
csharp/src/Google.Protobuf.Test/FieldCodecTest.cs \
csharp/src/Google.Protobuf.Test/FieldMaskTreeTest.cs \
csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs \
csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs \
csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj \
csharp/src/Google.Protobuf.Test/IssuesTest.cs \
csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs \
@ -119,13 +124,17 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf.Test/TestCornerCases.cs \
csharp/src/Google.Protobuf.Test/TestProtos/ForeignMessagePartial.cs \
csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs \
csharp/src/Google.Protobuf.Test/TestProtos/TestMessagesProto2.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/UnittestImportPublic.cs \
csharp/src/Google.Protobuf.Test/TestProtos/UnittestImport.cs \
csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs \
csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs \
csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs \
csharp/src/Google.Protobuf.Test/TestProtos/Unittest.cs \
csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs \
csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs \
csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs \

View File

@ -52,8 +52,12 @@ $PROTOC -Isrc -Icsharp/protos \
csharp/protos/unittest_proto3.proto \
csharp/protos/unittest_import_proto3.proto \
csharp/protos/unittest_import_public_proto3.proto \
csharp/protos/unittest.proto \
csharp/protos/unittest_import.proto \
csharp/protos/unittest_import_public.proto \
src/google/protobuf/unittest_well_known_types.proto \
src/google/protobuf/test_messages_proto3.proto
src/google/protobuf/test_messages_proto3.proto \
src/google/protobuf/test_messages_proto2.proto
# AddressBook sample protos
$PROTOC -Iexamples -Isrc --csharp_out=csharp/src/AddressBook \

1113
csharp/protos/unittest.proto Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,69 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: kenton@google.com (Kenton Varda)
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
// A proto file which is imported by unittest.proto to test importing.
syntax = "proto2";
// 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.
// In test_util.h we do
// "using namespace unittest_import = protobuf_unittest_import".
package protobuf_unittest_import_proto2;
option optimize_for = SPEED;
option cc_enable_arenas = true;
option csharp_namespace = "Google.Protobuf.TestProtos.Proto2";
// Test public import
import public "unittest_import_public.proto";
message ImportMessage {
optional int32 d = 1;
}
enum ImportEnum {
IMPORT_FOO = 7;
IMPORT_BAR = 8;
IMPORT_BAZ = 9;
}
// To use an enum in a map, it must has the first value as 0.
enum ImportEnumForMap {
UNKNOWN = 0;
FOO = 1;
BAR = 2;
}

View File

@ -0,0 +1,41 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: liujisi@google.com (Pherl Liu)
syntax = "proto2";
package protobuf_unittest_import_proto2;
option csharp_namespace = "Google.Protobuf.TestProtos.Proto2";
message PublicImportMessage {
optional int32 e = 1;
}

View File

@ -48,7 +48,9 @@ namespace Google.Protobuf.Conformance
// This way we get the binary streams instead of readers/writers.
var input = new BinaryReader(Console.OpenStandardInput());
var output = new BinaryWriter(Console.OpenStandardOutput());
var typeRegistry = TypeRegistry.FromMessages(ProtobufTestMessages.Proto3.TestAllTypesProto3.Descriptor);
var typeRegistry = TypeRegistry.FromMessages(
ProtobufTestMessages.Proto3.TestAllTypesProto3.Descriptor,
ProtobufTestMessages.Proto2.TestAllTypesProto2.Descriptor);
int count = 0;
while (RunTest(input, output, typeRegistry))
@ -81,7 +83,7 @@ namespace Google.Protobuf.Conformance
private static ConformanceResponse PerformRequest(ConformanceRequest request, TypeRegistry typeRegistry)
{
ProtobufTestMessages.Proto3.TestAllTypesProto3 message;
IMessage message;
try
{
switch (request.PayloadCase)
@ -101,7 +103,13 @@ namespace Google.Protobuf.Conformance
}
else if (request.MessageType.Equals("protobuf_test_messages.proto2.TestAllTypesProto2"))
{
return new ConformanceResponse { Skipped = "CSharp doesn't support proto2" };
ExtensionRegistry registry = new ExtensionRegistry()
{
ProtobufTestMessages.Proto2.TestMessagesProto2Extensions.ExtensionInt32,
ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension1.Extensions.MessageSetExtension,
ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.MessageSetCorrectExtension2.Extensions.MessageSetExtension
};
message = ProtobufTestMessages.Proto2.TestAllTypesProto2.Parser.WithExtensionRegistry(registry).ParseFrom(request.ProtobufPayload);
}
else
{

View File

@ -0,0 +1,102 @@
using Google.Protobuf.TestProtos.Proto2;
using NUnit.Framework;
using static Google.Protobuf.TestProtos.Proto2.UnittestExtensions;
namespace Google.Protobuf
{
public class ExtensionSetTest
{
[Test]
public void EmptyExtensionSet()
{
ExtensionSet<TestAllExtensions> extensions = new ExtensionSet<TestAllExtensions>();
Assert.AreEqual(0, extensions.CalculateSize());
}
[Test]
public void MergeExtensionSet()
{
ExtensionSet<TestAllExtensions> extensions = null;
ExtensionSet.Set(ref extensions, OptionalBoolExtension, true);
ExtensionSet<TestAllExtensions> other = null;
Assert.IsFalse(ExtensionSet.Has(ref other, OptionalBoolExtension));
ExtensionSet.MergeFrom(ref other, extensions);
Assert.IsTrue(ExtensionSet.Has(ref other, OptionalBoolExtension));
}
[Test]
public void TestMergeCodedInput()
{
var message = new TestAllExtensions();
message.SetExtension(OptionalBoolExtension, true);
var serialized = message.ToByteArray();
var other = TestAllExtensions.Parser
.WithExtensionRegistry(new ExtensionRegistry() { OptionalBoolExtension })
.ParseFrom(serialized);
Assert.AreEqual(message, other);
Assert.AreEqual(message.CalculateSize(), other.CalculateSize());
}
[Test]
public void TestMergeMessage()
{
var message = new TestAllExtensions();
message.SetExtension(OptionalBoolExtension, true);
var other = new TestAllExtensions();
Assert.AreNotEqual(message, other);
Assert.AreNotEqual(message.CalculateSize(), other.CalculateSize());
other.MergeFrom(message);
Assert.AreEqual(message, other);
Assert.AreEqual(message.CalculateSize(), other.CalculateSize());
}
[Test]
public void TestEquals()
{
var message = new TestAllExtensions();
message.SetExtension(OptionalBoolExtension, true);
var other = new TestAllExtensions();
Assert.AreNotEqual(message, other);
Assert.AreNotEqual(message.CalculateSize(), other.CalculateSize());
other.SetExtension(OptionalBoolExtension, true);
Assert.AreEqual(message, other);
Assert.AreEqual(message.CalculateSize(), other.CalculateSize());
}
[Test]
public void TestHashCode()
{
var message = new TestAllExtensions();
var hashCode = message.GetHashCode();
message.SetExtension(OptionalBoolExtension, true);
Assert.AreNotEqual(hashCode, message.GetHashCode());
}
[Test]
public void TestClone()
{
var message = new TestAllExtensions();
message.SetExtension(OptionalBoolExtension, true);
var other = message.Clone();
Assert.AreEqual(message, other);
Assert.AreEqual(message.CalculateSize(), message.CalculateSize());
}
}
}

View File

@ -0,0 +1,368 @@
using Google.Protobuf.TestProtos.Proto2;
using Proto2 = Google.Protobuf.TestProtos.Proto2;
using NUnit.Framework;
using static Google.Protobuf.TestProtos.Proto2.UnittestExtensions;
namespace Google.Protobuf
{
/// <summary>
/// Tests around the generated TestAllTypes message in unittest.proto
/// </summary>
public partial class GeneratedMessageTest
{
[Test]
public void DefaultProto2Values()
{
var message = new TestAllTypes();
Assert.AreEqual(false, message.OptionalBool);
Assert.AreEqual(ByteString.Empty, message.OptionalBytes);
Assert.AreEqual(0.0, message.OptionalDouble);
Assert.AreEqual(0, message.OptionalFixed32);
Assert.AreEqual(0L, message.OptionalFixed64);
Assert.AreEqual(0.0f, message.OptionalFloat);
Assert.AreEqual(ForeignEnum.ForeignFoo, message.OptionalForeignEnum);
Assert.IsNull(message.OptionalForeignMessage);
Assert.AreEqual(ImportEnum.ImportFoo, message.OptionalImportEnum);
Assert.IsNull(message.OptionalImportMessage);
Assert.AreEqual(0, message.OptionalInt32);
Assert.AreEqual(0L, message.OptionalInt64);
Assert.AreEqual(Proto2.TestAllTypes.Types.NestedEnum.Foo, message.OptionalNestedEnum);
Assert.IsNull(message.OptionalNestedMessage);
Assert.IsNull(message.OptionalPublicImportMessage);
Assert.AreEqual(0, message.OptionalSfixed32);
Assert.AreEqual(0L, message.OptionalSfixed64);
Assert.AreEqual(0, message.OptionalSint32);
Assert.AreEqual(0L, message.OptionalSint64);
Assert.AreEqual("", message.OptionalString);
Assert.AreEqual(0U, message.OptionalUint32);
Assert.AreEqual(0UL, message.OptionalUint64);
// Repeated fields
Assert.AreEqual(0, message.RepeatedBool.Count);
Assert.AreEqual(0, message.RepeatedBytes.Count);
Assert.AreEqual(0, message.RepeatedDouble.Count);
Assert.AreEqual(0, message.RepeatedFixed32.Count);
Assert.AreEqual(0, message.RepeatedFixed64.Count);
Assert.AreEqual(0, message.RepeatedFloat.Count);
Assert.AreEqual(0, message.RepeatedForeignEnum.Count);
Assert.AreEqual(0, message.RepeatedForeignMessage.Count);
Assert.AreEqual(0, message.RepeatedImportEnum.Count);
Assert.AreEqual(0, message.RepeatedImportMessage.Count);
Assert.AreEqual(0, message.RepeatedNestedEnum.Count);
Assert.AreEqual(0, message.RepeatedNestedMessage.Count);
Assert.AreEqual(0, message.RepeatedSfixed32.Count);
Assert.AreEqual(0, message.RepeatedSfixed64.Count);
Assert.AreEqual(0, message.RepeatedSint32.Count);
Assert.AreEqual(0, message.RepeatedSint64.Count);
Assert.AreEqual(0, message.RepeatedString.Count);
Assert.AreEqual(0, message.RepeatedUint32.Count);
Assert.AreEqual(0, message.RepeatedUint64.Count);
// Oneof fields
Assert.AreEqual(Proto2.TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
Assert.AreEqual(0, message.OneofUint32);
Assert.AreEqual("", message.OneofString);
Assert.AreEqual(ByteString.Empty, message.OneofBytes);
Assert.IsNull(message.OneofNestedMessage);
Assert.AreEqual(true, message.DefaultBool);
Assert.AreEqual(ByteString.CopyFromUtf8("world"), message.DefaultBytes);
Assert.AreEqual("123", message.DefaultCord);
Assert.AreEqual(52e3, message.DefaultDouble);
Assert.AreEqual(47, message.DefaultFixed32);
Assert.AreEqual(48, message.DefaultFixed64);
Assert.AreEqual(51.5, message.DefaultFloat);
Assert.AreEqual(ForeignEnum.ForeignBar, message.DefaultForeignEnum);
Assert.AreEqual(ImportEnum.ImportBar, message.DefaultImportEnum);
Assert.AreEqual(41, message.DefaultInt32);
Assert.AreEqual(42, message.DefaultInt64);
Assert.AreEqual(Proto2.TestAllTypes.Types.NestedEnum.Bar, message.DefaultNestedEnum);
Assert.AreEqual(49, message.DefaultSfixed32);
Assert.AreEqual(-50, message.DefaultSfixed64);
Assert.AreEqual(-45, message.DefaultSint32);
Assert.AreEqual(46, message.DefaultSint64);
Assert.AreEqual("hello", message.DefaultString);
Assert.AreEqual("abc", message.DefaultStringPiece);
Assert.AreEqual(43, message.DefaultUint32);
Assert.AreEqual(44, message.DefaultUint64);
Assert.False(message.HasDefaultBool);
Assert.False(message.HasDefaultBytes);
Assert.False(message.HasDefaultCord);
Assert.False(message.HasDefaultDouble);
Assert.False(message.HasDefaultFixed32);
Assert.False(message.HasDefaultFixed64);
Assert.False(message.HasDefaultFloat);
Assert.False(message.HasDefaultForeignEnum);
Assert.False(message.HasDefaultImportEnum);
Assert.False(message.HasDefaultInt32);
Assert.False(message.HasDefaultInt64);
Assert.False(message.HasDefaultNestedEnum);
Assert.False(message.HasDefaultSfixed32);
Assert.False(message.HasDefaultSfixed64);
Assert.False(message.HasDefaultSint32);
Assert.False(message.HasDefaultSint64);
Assert.False(message.HasDefaultString);
Assert.False(message.HasDefaultStringPiece);
Assert.False(message.HasDefaultUint32);
Assert.False(message.HasDefaultUint64);
}
[Test]
public void DefaultExtensionValues()
{
var message = new TestAllExtensions();
Assert.AreEqual(false, message.GetExtension(OptionalBoolExtension));
Assert.AreEqual(ByteString.Empty, message.GetExtension(OptionalBytesExtension));
Assert.AreEqual(0.0, message.GetExtension(OptionalDoubleExtension));
Assert.AreEqual(0, message.GetExtension(OptionalFixed32Extension));
Assert.AreEqual(0L, message.GetExtension(OptionalFixed64Extension));
Assert.AreEqual(0.0f, message.GetExtension(OptionalFloatExtension));
Assert.AreEqual(ForeignEnum.ForeignFoo, message.GetExtension(OptionalForeignEnumExtension));
Assert.IsNull(message.GetExtension(OptionalForeignMessageExtension));
Assert.AreEqual(ImportEnum.ImportFoo, message.GetExtension(OptionalImportEnumExtension));
Assert.IsNull(message.GetExtension(OptionalImportMessageExtension));
Assert.AreEqual(0, message.GetExtension(OptionalInt32Extension));
Assert.AreEqual(0L, message.GetExtension(OptionalInt64Extension));
Assert.AreEqual(Proto2.TestAllTypes.Types.NestedEnum.Foo, message.GetExtension(OptionalNestedEnumExtension));
Assert.IsNull(message.GetExtension(OptionalNestedMessageExtension));
Assert.IsNull(message.GetExtension(OptionalPublicImportMessageExtension));
Assert.AreEqual(0, message.GetExtension(OptionalSfixed32Extension));
Assert.AreEqual(0L, message.GetExtension(OptionalSfixed64Extension));
Assert.AreEqual(0, message.GetExtension(OptionalSint32Extension));
Assert.AreEqual(0L, message.GetExtension(OptionalSint64Extension));
Assert.AreEqual("", message.GetExtension(OptionalStringExtension));
Assert.AreEqual(0U, message.GetExtension(OptionalUint32Extension));
Assert.AreEqual(0UL, message.GetExtension(OptionalUint64Extension));
// Repeated fields
Assert.IsNull(message.GetExtension(RepeatedBoolExtension));
Assert.IsNull(message.GetExtension(RepeatedBytesExtension));
Assert.IsNull(message.GetExtension(RepeatedDoubleExtension));
Assert.IsNull(message.GetExtension(RepeatedFixed32Extension));
Assert.IsNull(message.GetExtension(RepeatedFixed64Extension));
Assert.IsNull(message.GetExtension(RepeatedFloatExtension));
Assert.IsNull(message.GetExtension(RepeatedForeignEnumExtension));
Assert.IsNull(message.GetExtension(RepeatedForeignMessageExtension));
Assert.IsNull(message.GetExtension(RepeatedImportEnumExtension));
Assert.IsNull(message.GetExtension(RepeatedImportMessageExtension));
Assert.IsNull(message.GetExtension(RepeatedNestedEnumExtension));
Assert.IsNull(message.GetExtension(RepeatedNestedMessageExtension));
Assert.IsNull(message.GetExtension(RepeatedSfixed32Extension));
Assert.IsNull(message.GetExtension(RepeatedSfixed64Extension));
Assert.IsNull(message.GetExtension(RepeatedSint32Extension));
Assert.IsNull(message.GetExtension(RepeatedSint64Extension));
Assert.IsNull(message.GetExtension(RepeatedStringExtension));
Assert.IsNull(message.GetExtension(RepeatedUint32Extension));
Assert.IsNull(message.GetExtension(RepeatedUint64Extension));
// Oneof fields
Assert.AreEqual(0, message.GetExtension(OneofUint32Extension));
Assert.AreEqual("", message.GetExtension(OneofStringExtension));
Assert.AreEqual(ByteString.Empty, message.GetExtension(OneofBytesExtension));
Assert.IsNull(message.GetExtension(OneofNestedMessageExtension));
Assert.AreEqual(true, message.GetExtension(DefaultBoolExtension));
Assert.AreEqual(ByteString.CopyFromUtf8("world"), message.GetExtension(DefaultBytesExtension));
Assert.AreEqual("123", message.GetExtension(DefaultCordExtension));
Assert.AreEqual(52e3, message.GetExtension(DefaultDoubleExtension));
Assert.AreEqual(47, message.GetExtension(DefaultFixed32Extension));
Assert.AreEqual(48, message.GetExtension(DefaultFixed64Extension));
Assert.AreEqual(51.5, message.GetExtension(DefaultFloatExtension));
Assert.AreEqual(ForeignEnum.ForeignBar, message.GetExtension(DefaultForeignEnumExtension));
Assert.AreEqual(ImportEnum.ImportBar, message.GetExtension(DefaultImportEnumExtension));
Assert.AreEqual(41, message.GetExtension(DefaultInt32Extension));
Assert.AreEqual(42, message.GetExtension(DefaultInt64Extension));
Assert.AreEqual(Proto2.TestAllTypes.Types.NestedEnum.Bar, message.GetExtension(DefaultNestedEnumExtension));
Assert.AreEqual(49, message.GetExtension(DefaultSfixed32Extension));
Assert.AreEqual(-50, message.GetExtension(DefaultSfixed64Extension));
Assert.AreEqual(-45, message.GetExtension(DefaultSint32Extension));
Assert.AreEqual(46, message.GetExtension(DefaultSint64Extension));
Assert.AreEqual("hello", message.GetExtension(DefaultStringExtension));
Assert.AreEqual("abc", message.GetExtension(DefaultStringPieceExtension));
Assert.AreEqual(43, message.GetExtension(DefaultUint32Extension));
Assert.AreEqual(44, message.GetExtension(DefaultUint64Extension));
Assert.False(message.HasExtension(DefaultBoolExtension));
Assert.False(message.HasExtension(DefaultBytesExtension));
Assert.False(message.HasExtension(DefaultCordExtension));
Assert.False(message.HasExtension(DefaultDoubleExtension));
Assert.False(message.HasExtension(DefaultFixed32Extension));
Assert.False(message.HasExtension(DefaultFixed64Extension));
Assert.False(message.HasExtension(DefaultFloatExtension));
Assert.False(message.HasExtension(DefaultForeignEnumExtension));
Assert.False(message.HasExtension(DefaultImportEnumExtension));
Assert.False(message.HasExtension(DefaultInt32Extension));
Assert.False(message.HasExtension(DefaultInt64Extension));
Assert.False(message.HasExtension(DefaultNestedEnumExtension));
Assert.False(message.HasExtension(DefaultSfixed32Extension));
Assert.False(message.HasExtension(DefaultSfixed64Extension));
Assert.False(message.HasExtension(DefaultSint32Extension));
Assert.False(message.HasExtension(DefaultSint64Extension));
Assert.False(message.HasExtension(DefaultStringExtension));
Assert.False(message.HasExtension(DefaultStringPieceExtension));
Assert.False(message.HasExtension(DefaultUint32Extension));
Assert.False(message.HasExtension(DefaultUint64Extension));
}
[Test]
public void FieldPresence()
{
var message = new TestAllTypes();
Assert.False(message.HasOptionalBool);
Assert.False(message.OptionalBool);
message.OptionalBool = true;
Assert.True(message.HasOptionalBool);
Assert.True(message.OptionalBool);
message.OptionalBool = false;
Assert.True(message.HasOptionalBool);
Assert.False(message.OptionalBool);
message.ClearOptionalBool();
Assert.False(message.HasOptionalBool);
Assert.False(message.OptionalBool);
Assert.False(message.HasDefaultBool);
Assert.True(message.DefaultBool);
message.DefaultBool = false;
Assert.True(message.HasDefaultBool);
Assert.False(message.DefaultBool);
message.DefaultBool = true;
Assert.True(message.HasDefaultBool);
Assert.True(message.DefaultBool);
message.ClearDefaultBool();
Assert.False(message.HasDefaultBool);
Assert.True(message.DefaultBool);
}
[Test]
public void RequiredFields()
{
var message = new TestRequired();
Assert.False(message.IsInitialized());
message.A = 1;
message.B = 2;
message.C = 3;
Assert.True(message.IsInitialized());
}
[Test]
public void RequiredFieldsInExtensions()
{
var message = new TestAllExtensions();
Assert.True(message.IsInitialized());
message.SetExtension(TestRequired.Extensions.Single, new TestRequired());
Assert.False(message.IsInitialized());
var extensionMessage = message.GetExtension(TestRequired.Extensions.Single);
extensionMessage.A = 1;
extensionMessage.B = 2;
extensionMessage.C = 3;
Assert.True(message.IsInitialized());
message.GetOrInitializeExtension(TestRequired.Extensions.Multi);
Assert.True(message.IsInitialized());
message.GetExtension(TestRequired.Extensions.Multi).Add(new TestRequired());
Assert.False(message.IsInitialized());
extensionMessage = message.GetExtension(TestRequired.Extensions.Multi)[0];
extensionMessage.A = 1;
extensionMessage.B = 2;
extensionMessage.C = 3;
Assert.True(message.IsInitialized());
message.SetExtension(UnittestExtensions.OptionalBoolExtension, true);
Assert.True(message.IsInitialized());
message.GetOrInitializeExtension(UnittestExtensions.RepeatedBoolExtension).Add(true);
Assert.True(message.IsInitialized());
}
[Test]
public void RequiredFieldInNestedMessageMapValue()
{
var message = new TestRequiredMap();
message.Foo.Add(0, new TestRequiredMap.Types.NestedMessage());
Assert.False(message.IsInitialized());
message.Foo[0].RequiredInt32 = 12;
Assert.True(message.IsInitialized());
}
[Test]
public void RoundTrip_Groups()
{
var message = new TestAllTypes
{
OptionalGroup = new TestAllTypes.Types.OptionalGroup
{
A = 10
},
RepeatedGroup =
{
new TestAllTypes.Types.RepeatedGroup { A = 10 },
new TestAllTypes.Types.RepeatedGroup { A = 20 },
new TestAllTypes.Types.RepeatedGroup { A = 30 }
}
};
byte[] bytes = message.ToByteArray();
TestAllTypes parsed = Proto2.TestAllTypes.Parser.ParseFrom(bytes);
Assert.AreEqual(message, parsed);
}
[Test]
public void RoundTrip_ExtensionGroups()
{
var message = new TestAllExtensions();
message.SetExtension(UnittestExtensions.OptionalGroupExtension, new OptionalGroup_extension { A = 10 });
message.GetOrInitializeExtension(UnittestExtensions.RepeatedGroupExtension).AddRange(new[]
{
new RepeatedGroup_extension { A = 10 },
new RepeatedGroup_extension { A = 20 },
new RepeatedGroup_extension { A = 30 }
});
byte[] bytes = message.ToByteArray();
TestAllExtensions extendable_parsed = TestAllExtensions.Parser.WithExtensionRegistry(new ExtensionRegistry() { UnittestExtensions.OptionalGroupExtension, UnittestExtensions.RepeatedGroupExtension }).ParseFrom(bytes);
Assert.AreEqual(message, extendable_parsed);
}
[Test]
public void RoundTrip_NestedExtensionGroup()
{
var message = new TestGroupExtension();
message.SetExtension(TestNestedExtension.Extensions.OptionalGroupExtension, new TestNestedExtension.Types.OptionalGroup_extension { A = 10 });
byte[] bytes = message.ToByteArray();
TestGroupExtension extendable_parsed = TestGroupExtension.Parser.WithExtensionRegistry(new ExtensionRegistry() { TestNestedExtension.Extensions.OptionalGroupExtension }).ParseFrom(bytes);
Assert.AreEqual(message, extendable_parsed);
}
}
}

View File

@ -33,6 +33,7 @@
using System;
using System.IO;
using Google.Protobuf.TestProtos;
using Proto2 = Google.Protobuf.TestProtos.Proto2;
using NUnit.Framework;
using System.Collections;
using System.Collections.Generic;
@ -44,7 +45,7 @@ namespace Google.Protobuf
/// <summary>
/// Tests around the generated TestAllTypes message.
/// </summary>
public class GeneratedMessageTest
public partial class GeneratedMessageTest
{
[Test]
public void EmptyMessageFieldDistinctFromMissingMessageField()

View File

@ -33,64 +33,19 @@
using Google.Protobuf.Reflection;
using Google.Protobuf.WellKnownTypes;
using NUnit.Framework;
using System;
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.UnittestCustomOptionsProto3Extensions;
using static UnitTest.Issues.TestProtos.DummyMessageContainingEnum.Types;
using static Google.Protobuf.Test.Reflection.CustomOptionNumber;
#pragma warning disable CS0618
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,
OneofOpt1 = 7740111,
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,
}
/// <summary>
/// The majority of the testing here is done via parsed descriptors. That's simpler to
/// achieve (and more important) than constructing a CodedInputStream manually.
@ -99,23 +54,41 @@ namespace Google.Protobuf.Test.Reflection
{
delegate bool OptionFetcher<T>(int field, out T value);
OptionFetcher<E> EnumFetcher<E>(CustomOptions options)
{
return (int i, out E v) => {
if (options.TryGetInt32(i, out int value))
{
v = (E)(object)value;
return true;
}
else
{
v = default(E);
return false;
}
};
}
[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);
var d = CustomOptionOtherValues.Descriptor;
var options = d.CustomOptions;
AssertOption(-100, options.TryGetInt32, Int32Opt, d.GetOption);
AssertOption(12.3456789f, options.TryGetFloat, FloatOpt, d.GetOption);
AssertOption(1.234567890123456789d, options.TryGetDouble, DoubleOpt, d.GetOption);
AssertOption("Hello, \"World\"", options.TryGetString, StringOpt, d.GetOption);
AssertOption(ByteString.CopyFromUtf8("Hello\0World"), options.TryGetBytes, BytesOpt, d.GetOption);
AssertOption(TestEnumType.TestOptionEnumType2, EnumFetcher<TestEnumType>(options), EnumOpt, d.GetOption);
}
[Test]
public void MessageOptions()
{
var options = VariousComplexOptions.Descriptor.CustomOptions;
AssertOption(new ComplexOptionType1 { Foo = 42, Foo4 = { 99, 88 } }, options.TryGetMessage, ComplexOpt1);
var d = VariousComplexOptions.Descriptor;
var options = d.CustomOptions;
AssertOption(new ComplexOptionType1 { Foo = 42, Foo4 = { 99, 88 } }, options.TryGetMessage, ComplexOpt1, d.GetOption);
AssertOption(new ComplexOptionType2
{
Baz = 987,
@ -123,72 +96,74 @@ namespace Google.Protobuf.Test.Reflection
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);
options.TryGetMessage, ComplexOpt2, d.GetOption);
AssertOption(new ComplexOptionType3 { Qux = 9 }, options.TryGetMessage, ComplexOpt3, d.GetOption);
}
[Test]
public void OptionLocations()
{
var fileOptions = UnittestCustomOptionsProto3Reflection.Descriptor.CustomOptions;
AssertOption(9876543210UL, fileOptions.TryGetUInt64, FileOpt1);
AssertOption(9876543210UL, fileOptions.TryGetUInt64, FileOpt1, UnittestCustomOptionsProto3Reflection.Descriptor.GetOption);
var messageOptions = TestMessageWithCustomOptions.Descriptor.CustomOptions;
AssertOption(-56, messageOptions.TryGetInt32, MessageOpt1);
AssertOption(-56, messageOptions.TryGetInt32, MessageOpt1, TestMessageWithCustomOptions.Descriptor.GetOption);
var fieldOptions = TestMessageWithCustomOptions.Descriptor.Fields["field1"].CustomOptions;
AssertOption(8765432109UL, fieldOptions.TryGetFixed64, FieldOpt1);
AssertOption(8765432109UL, fieldOptions.TryGetFixed64, FieldOpt1, TestMessageWithCustomOptions.Descriptor.Fields["field1"].GetOption);
var oneofOptions = TestMessageWithCustomOptions.Descriptor.Oneofs[0].CustomOptions;
AssertOption(-99, oneofOptions.TryGetInt32, OneofOpt1);
AssertOption(-99, oneofOptions.TryGetInt32, OneofOpt1, TestMessageWithCustomOptions.Descriptor.Oneofs[0].GetOption);
var enumOptions = TestMessageWithCustomOptions.Descriptor.EnumTypes[0].CustomOptions;
AssertOption(-789, enumOptions.TryGetSFixed32, EnumOpt1);
AssertOption(-789, enumOptions.TryGetSFixed32, EnumOpt1, TestMessageWithCustomOptions.Descriptor.EnumTypes[0].GetOption);
var enumValueOptions = TestMessageWithCustomOptions.Descriptor.EnumTypes[0].FindValueByNumber(2).CustomOptions;
AssertOption(123, enumValueOptions.TryGetInt32, EnumValueOpt1);
AssertOption(123, enumValueOptions.TryGetInt32, EnumValueOpt1, TestMessageWithCustomOptions.Descriptor.EnumTypes[0].FindValueByNumber(2).GetOption);
var service = UnittestCustomOptionsProto3Reflection.Descriptor.Services
.Single(s => s.Name == "TestServiceWithCustomOptions");
var serviceOptions = service.CustomOptions;
AssertOption(-9876543210, serviceOptions.TryGetSInt64, ServiceOpt1);
AssertOption(-9876543210, serviceOptions.TryGetSInt64, ServiceOpt1, service.GetOption);
var methodOptions = service.Methods[0].CustomOptions;
AssertOption((int)UnitTest.Issues.TestProtos.MethodOpt1.Val2, methodOptions.TryGetInt32, CustomOptionNumber.MethodOpt1);
AssertOption(UnitTest.Issues.TestProtos.MethodOpt1.Val2, EnumFetcher<UnitTest.Issues.TestProtos.MethodOpt1>(methodOptions), UnittestCustomOptionsProto3Extensions.MethodOpt1, service.Methods[0].GetOption);
}
[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);
var d = CustomOptionMinIntegerValues.Descriptor;
var options = d.CustomOptions;
AssertOption(false, options.TryGetBool, BoolOpt, d.GetOption);
AssertOption(int.MinValue, options.TryGetInt32, Int32Opt, d.GetOption);
AssertOption(long.MinValue, options.TryGetInt64, Int64Opt, d.GetOption);
AssertOption(uint.MinValue, options.TryGetUInt32, Uint32Opt, d.GetOption);
AssertOption(ulong.MinValue, options.TryGetUInt64, Uint64Opt, d.GetOption);
AssertOption(int.MinValue, options.TryGetSInt32, Sint32Opt, d.GetOption);
AssertOption(long.MinValue, options.TryGetSInt64, Sint64Opt, d.GetOption);
AssertOption(uint.MinValue, options.TryGetUInt32, Fixed32Opt, d.GetOption);
AssertOption(ulong.MinValue, options.TryGetUInt64, Fixed64Opt, d.GetOption);
AssertOption(int.MinValue, options.TryGetInt32, Sfixed32Opt, d.GetOption);
AssertOption(long.MinValue, options.TryGetInt64, Sfixed64Opt, d.GetOption);
}
[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);
var d = CustomOptionMaxIntegerValues.Descriptor;
var options = d.CustomOptions;
AssertOption(true, options.TryGetBool, BoolOpt, d.GetOption);
AssertOption(int.MaxValue, options.TryGetInt32, Int32Opt, d.GetOption);
AssertOption(long.MaxValue, options.TryGetInt64, Int64Opt, d.GetOption);
AssertOption(uint.MaxValue, options.TryGetUInt32, Uint32Opt, d.GetOption);
AssertOption(ulong.MaxValue, options.TryGetUInt64, Uint64Opt, d.GetOption);
AssertOption(int.MaxValue, options.TryGetSInt32, Sint32Opt, d.GetOption);
AssertOption(long.MaxValue, options.TryGetSInt64, Sint64Opt, d.GetOption);
AssertOption(uint.MaxValue, options.TryGetFixed32, Fixed32Opt, d.GetOption);
AssertOption(ulong.MaxValue, options.TryGetFixed64, Fixed64Opt, d.GetOption);
AssertOption(int.MaxValue, options.TryGetSFixed32, Sfixed32Opt, d.GetOption);
AssertOption(long.MaxValue, options.TryGetSFixed64, Sfixed64Opt, d.GetOption);
}
[Test]
@ -196,17 +171,19 @@ namespace Google.Protobuf.Test.Reflection
{
// Just two examples
var messageOptions = AggregateMessage.Descriptor.CustomOptions;
AssertOption(new Aggregate { I = 101, S = "MessageAnnotation" }, messageOptions.TryGetMessage, AggregateMsgOpt);
AssertOption(new Aggregate { I = 101, S = "MessageAnnotation" }, messageOptions.TryGetMessage, Msgopt, AggregateMessage.Descriptor.GetOption);
var fieldOptions = AggregateMessage.Descriptor.Fields["fieldname"].CustomOptions;
AssertOption(new Aggregate { S = "FieldAnnotation" }, fieldOptions.TryGetMessage, AggregateFieldOpt);
AssertOption(new Aggregate { S = "FieldAnnotation" }, fieldOptions.TryGetMessage, Fieldopt, AggregateMessage.Descriptor.Fields["fieldname"].GetOption);
}
private void AssertOption<T>(T expected, OptionFetcher<T> fetcher, CustomOptionNumber field)
private void AssertOption<T, D>(T expected, OptionFetcher<T> fetcher, Extension<D, T> extension, Func<Extension<D, T>, T> descriptorOptionFetcher) where D : IExtendableMessage<D>
{
T actual;
Assert.IsTrue(fetcher((int)field, out actual));
Assert.AreEqual(expected, actual);
T customOptionsValue;
T extensionValue = descriptorOptionFetcher(extension);
Assert.IsTrue(fetcher(extension.FieldNumber, out customOptionsValue));
Assert.AreEqual(expected, customOptionsValue);
Assert.AreEqual(expected, extensionValue);
}
}
}

View File

@ -31,11 +31,14 @@
#endregion
using Google.Protobuf.TestProtos;
using Proto2 = Google.Protobuf.TestProtos.Proto2;
using NUnit.Framework;
using System;
using System.Collections;
using System.Collections.Generic;
using static Google.Protobuf.TestProtos.Proto2.UnittestExtensions;
namespace Google.Protobuf.Reflection
{
public class FieldAccessTest
@ -44,36 +47,36 @@ namespace Google.Protobuf.Reflection
public void GetValue()
{
var message = SampleMessages.CreateFullTestAllTypes();
var fields = TestAllTypes.Descriptor.Fields;
Assert.AreEqual(message.SingleBool, fields[TestAllTypes.SingleBoolFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleBytes, fields[TestAllTypes.SingleBytesFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleDouble, fields[TestAllTypes.SingleDoubleFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleFixed32, fields[TestAllTypes.SingleFixed32FieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleFixed64, fields[TestAllTypes.SingleFixed64FieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleFloat, fields[TestAllTypes.SingleFloatFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleForeignEnum, fields[TestAllTypes.SingleForeignEnumFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleForeignMessage, fields[TestAllTypes.SingleForeignMessageFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleImportEnum, fields[TestAllTypes.SingleImportEnumFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleImportMessage, fields[TestAllTypes.SingleImportMessageFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleInt32, fields[TestAllTypes.SingleInt32FieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleInt64, fields[TestAllTypes.SingleInt64FieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleNestedEnum, fields[TestAllTypes.SingleNestedEnumFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleNestedMessage, fields[TestAllTypes.SingleNestedMessageFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SinglePublicImportMessage, fields[TestAllTypes.SinglePublicImportMessageFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleSint32, fields[TestAllTypes.SingleSint32FieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleSint64, fields[TestAllTypes.SingleSint64FieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleString, fields[TestAllTypes.SingleStringFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleSfixed32, fields[TestAllTypes.SingleSfixed32FieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleSfixed64, fields[TestAllTypes.SingleSfixed64FieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleUint32, fields[TestAllTypes.SingleUint32FieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleUint64, fields[TestAllTypes.SingleUint64FieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.OneofBytes, fields[TestAllTypes.OneofBytesFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.OneofString, fields[TestAllTypes.OneofStringFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.OneofNestedMessage, fields[TestAllTypes.OneofNestedMessageFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.OneofUint32, fields[TestAllTypes.OneofUint32FieldNumber].Accessor.GetValue(message));
var fields = TestProtos.TestAllTypes.Descriptor.Fields;
Assert.AreEqual(message.SingleBool, fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleBytes, fields[TestProtos.TestAllTypes.SingleBytesFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleDouble, fields[TestProtos.TestAllTypes.SingleDoubleFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleFixed32, fields[TestProtos.TestAllTypes.SingleFixed32FieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleFixed64, fields[TestProtos.TestAllTypes.SingleFixed64FieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleFloat, fields[TestProtos.TestAllTypes.SingleFloatFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleForeignEnum, fields[TestProtos.TestAllTypes.SingleForeignEnumFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleForeignMessage, fields[TestProtos.TestAllTypes.SingleForeignMessageFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleImportEnum, fields[TestProtos.TestAllTypes.SingleImportEnumFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleImportMessage, fields[TestProtos.TestAllTypes.SingleImportMessageFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleInt32, fields[TestProtos.TestAllTypes.SingleInt32FieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleInt64, fields[TestProtos.TestAllTypes.SingleInt64FieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleNestedEnum, fields[TestProtos.TestAllTypes.SingleNestedEnumFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleNestedMessage, fields[TestProtos.TestAllTypes.SingleNestedMessageFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SinglePublicImportMessage, fields[TestProtos.TestAllTypes.SinglePublicImportMessageFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleSint32, fields[TestProtos.TestAllTypes.SingleSint32FieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleSint64, fields[TestProtos.TestAllTypes.SingleSint64FieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleString, fields[TestProtos.TestAllTypes.SingleStringFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleSfixed32, fields[TestProtos.TestAllTypes.SingleSfixed32FieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleSfixed64, fields[TestProtos.TestAllTypes.SingleSfixed64FieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleUint32, fields[TestProtos.TestAllTypes.SingleUint32FieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.SingleUint64, fields[TestProtos.TestAllTypes.SingleUint64FieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.OneofBytes, fields[TestProtos.TestAllTypes.OneofBytesFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.OneofString, fields[TestProtos.TestAllTypes.OneofStringFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.OneofNestedMessage, fields[TestProtos.TestAllTypes.OneofNestedMessageFieldNumber].Accessor.GetValue(message));
Assert.AreEqual(message.OneofUint32, fields[TestProtos.TestAllTypes.OneofUint32FieldNumber].Accessor.GetValue(message));
// Just one example for repeated fields - they're all just returning the list
var list = (IList) fields[TestAllTypes.RepeatedInt32FieldNumber].Accessor.GetValue(message);
var list = (IList) fields[TestProtos.TestAllTypes.RepeatedInt32FieldNumber].Accessor.GetValue(message);
Assert.AreEqual(message.RepeatedInt32, list);
Assert.AreEqual(message.RepeatedInt32[0], list[0]); // Just in case there was any doubt...
@ -85,18 +88,122 @@ namespace Google.Protobuf.Reflection
Assert.AreEqual("value1", dictionary["key1"]);
}
[Test]
public void GetValue_IncorrectType()
{
IMessage message = SampleMessages.CreateFullTestAllTypes();
var fields = message.Descriptor.Fields;
Assert.Throws<InvalidCastException>(() => fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].Accessor.GetValue(new TestMap()));
}
[Test]
public void HasValue_Proto3()
{
IMessage message = SampleMessages.CreateFullTestAllTypes();
var fields = message.Descriptor.Fields;
Assert.Throws<InvalidOperationException>(() => fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].Accessor.HasValue(message));
}
[Test]
public void HasValue()
{
IMessage message = new Proto2.TestAllTypes();
var fields = message.Descriptor.Fields;
var accessor = fields[Proto2.TestAllTypes.OptionalBoolFieldNumber].Accessor;
Assert.False(accessor.HasValue(message));
accessor.SetValue(message, true);
Assert.True(accessor.HasValue(message));
accessor.Clear(message);
Assert.False(accessor.HasValue(message));
}
[Test]
public void SetValue_SingleFields()
{
// Just a sample (primitives, messages, enums, strings, byte strings)
var message = SampleMessages.CreateFullTestAllTypes();
var fields = TestProtos.TestAllTypes.Descriptor.Fields;
fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].Accessor.SetValue(message, false);
fields[TestProtos.TestAllTypes.SingleInt32FieldNumber].Accessor.SetValue(message, 500);
fields[TestProtos.TestAllTypes.SingleStringFieldNumber].Accessor.SetValue(message, "It's a string");
fields[TestProtos.TestAllTypes.SingleBytesFieldNumber].Accessor.SetValue(message, ByteString.CopyFrom(99, 98, 97));
fields[TestProtos.TestAllTypes.SingleForeignEnumFieldNumber].Accessor.SetValue(message, ForeignEnum.ForeignFoo);
fields[TestProtos.TestAllTypes.SingleForeignMessageFieldNumber].Accessor.SetValue(message, new ForeignMessage { C = 12345 });
fields[TestProtos.TestAllTypes.SingleDoubleFieldNumber].Accessor.SetValue(message, 20150701.5);
var expected = new TestAllTypes(SampleMessages.CreateFullTestAllTypes())
{
SingleBool = false,
SingleInt32 = 500,
SingleString = "It's a string",
SingleBytes = ByteString.CopyFrom(99, 98, 97),
SingleForeignEnum = ForeignEnum.ForeignFoo,
SingleForeignMessage = new ForeignMessage { C = 12345 },
SingleDouble = 20150701.5
};
Assert.AreEqual(expected, message);
}
[Test]
public void SetValue_SingleFields_WrongType()
{
IMessage message = SampleMessages.CreateFullTestAllTypes();
var fields = message.Descriptor.Fields;
Assert.Throws<InvalidCastException>(() => fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].Accessor.SetValue(message, "This isn't a bool"));
}
[Test]
public void SetValue_MapFields()
{
IMessage message = new TestMap();
var fields = message.Descriptor.Fields;
Assert.Throws<InvalidOperationException>(() => fields[TestMap.MapStringStringFieldNumber].Accessor.SetValue(message, new Dictionary<string, string>()));
}
[Test]
public void SetValue_RepeatedFields()
{
IMessage message = SampleMessages.CreateFullTestAllTypes();
var fields = message.Descriptor.Fields;
Assert.Throws<InvalidOperationException>(() => fields[TestProtos.TestAllTypes.RepeatedDoubleFieldNumber].Accessor.SetValue(message, new double[10]));
}
[Test]
public void Oneof()
{
var message = new TestAllTypes();
var descriptor = TestProtos.TestAllTypes.Descriptor;
Assert.AreEqual(1, descriptor.Oneofs.Count);
var oneof = descriptor.Oneofs[0];
Assert.AreEqual("oneof_field", oneof.Name);
Assert.IsNull(oneof.Accessor.GetCaseFieldDescriptor(message));
message.OneofString = "foo";
Assert.AreSame(descriptor.Fields[TestProtos.TestAllTypes.OneofStringFieldNumber], oneof.Accessor.GetCaseFieldDescriptor(message));
message.OneofUint32 = 10;
Assert.AreSame(descriptor.Fields[TestProtos.TestAllTypes.OneofUint32FieldNumber], oneof.Accessor.GetCaseFieldDescriptor(message));
oneof.Accessor.Clear(message);
Assert.AreEqual(TestProtos.TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
}
[Test]
public void Clear()
{
var message = SampleMessages.CreateFullTestAllTypes();
var fields = TestAllTypes.Descriptor.Fields;
fields[TestAllTypes.SingleBoolFieldNumber].Accessor.Clear(message);
fields[TestAllTypes.SingleInt32FieldNumber].Accessor.Clear(message);
fields[TestAllTypes.SingleStringFieldNumber].Accessor.Clear(message);
fields[TestAllTypes.SingleBytesFieldNumber].Accessor.Clear(message);
fields[TestAllTypes.SingleForeignEnumFieldNumber].Accessor.Clear(message);
fields[TestAllTypes.SingleForeignMessageFieldNumber].Accessor.Clear(message);
fields[TestAllTypes.RepeatedDoubleFieldNumber].Accessor.Clear(message);
var fields = TestProtos.TestAllTypes.Descriptor.Fields;
fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].Accessor.Clear(message);
fields[TestProtos.TestAllTypes.SingleInt32FieldNumber].Accessor.Clear(message);
fields[TestProtos.TestAllTypes.SingleStringFieldNumber].Accessor.Clear(message);
fields[TestProtos.TestAllTypes.SingleBytesFieldNumber].Accessor.Clear(message);
fields[TestProtos.TestAllTypes.SingleForeignEnumFieldNumber].Accessor.Clear(message);
fields[TestProtos.TestAllTypes.SingleForeignMessageFieldNumber].Accessor.Clear(message);
fields[TestProtos.TestAllTypes.RepeatedDoubleFieldNumber].Accessor.Clear(message);
var expected = new TestAllTypes(SampleMessages.CreateFullTestAllTypes())
{
@ -118,101 +225,44 @@ namespace Google.Protobuf.Reflection
Assert.AreEqual(0, mapMessage.MapStringString.Count);
}
[Test]
public void SetValue_SingleFields()
{
// Just a sample (primitives, messages, enums, strings, byte strings)
var message = SampleMessages.CreateFullTestAllTypes();
var fields = TestAllTypes.Descriptor.Fields;
fields[TestAllTypes.SingleBoolFieldNumber].Accessor.SetValue(message, false);
fields[TestAllTypes.SingleInt32FieldNumber].Accessor.SetValue(message, 500);
fields[TestAllTypes.SingleStringFieldNumber].Accessor.SetValue(message, "It's a string");
fields[TestAllTypes.SingleBytesFieldNumber].Accessor.SetValue(message, ByteString.CopyFrom(99, 98, 97));
fields[TestAllTypes.SingleForeignEnumFieldNumber].Accessor.SetValue(message, ForeignEnum.ForeignFoo);
fields[TestAllTypes.SingleForeignMessageFieldNumber].Accessor.SetValue(message, new ForeignMessage { C = 12345 });
fields[TestAllTypes.SingleDoubleFieldNumber].Accessor.SetValue(message, 20150701.5);
var expected = new TestAllTypes(SampleMessages.CreateFullTestAllTypes())
{
SingleBool = false,
SingleInt32 = 500,
SingleString = "It's a string",
SingleBytes = ByteString.CopyFrom(99, 98, 97),
SingleForeignEnum = ForeignEnum.ForeignFoo,
SingleForeignMessage = new ForeignMessage { C = 12345 },
SingleDouble = 20150701.5
};
Assert.AreEqual(expected, message);
}
[Test]
public void SetValue_SingleFields_WrongType()
{
IMessage message = SampleMessages.CreateFullTestAllTypes();
var fields = message.Descriptor.Fields;
Assert.Throws<InvalidCastException>(() => fields[TestAllTypes.SingleBoolFieldNumber].Accessor.SetValue(message, "This isn't a bool"));
}
[Test]
public void SetValue_MapFields()
{
IMessage message = new TestMap();
var fields = message.Descriptor.Fields;
Assert.Throws<InvalidOperationException>(() => fields[TestMap.MapStringStringFieldNumber].Accessor.SetValue(message, new Dictionary<string, string>()));
}
[Test]
public void SetValue_RepeatedFields()
{
IMessage message = SampleMessages.CreateFullTestAllTypes();
var fields = message.Descriptor.Fields;
Assert.Throws<InvalidOperationException>(() => fields[TestAllTypes.RepeatedDoubleFieldNumber].Accessor.SetValue(message, new double[10]));
}
[Test]
public void GetValue_IncorrectType()
{
IMessage message = SampleMessages.CreateFullTestAllTypes();
var fields = message.Descriptor.Fields;
Assert.Throws<InvalidCastException>(() => fields[TestAllTypes.SingleBoolFieldNumber].Accessor.GetValue(new TestMap()));
}
[Test]
public void Oneof()
{
var message = new TestAllTypes();
var descriptor = TestAllTypes.Descriptor;
Assert.AreEqual(1, descriptor.Oneofs.Count);
var oneof = descriptor.Oneofs[0];
Assert.AreEqual("oneof_field", oneof.Name);
Assert.IsNull(oneof.Accessor.GetCaseFieldDescriptor(message));
message.OneofString = "foo";
Assert.AreSame(descriptor.Fields[TestAllTypes.OneofStringFieldNumber], oneof.Accessor.GetCaseFieldDescriptor(message));
message.OneofUint32 = 10;
Assert.AreSame(descriptor.Fields[TestAllTypes.OneofUint32FieldNumber], oneof.Accessor.GetCaseFieldDescriptor(message));
oneof.Accessor.Clear(message);
Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
}
[Test]
public void FieldDescriptor_ByName()
{
var descriptor = TestAllTypes.Descriptor;
var descriptor = TestProtos.TestAllTypes.Descriptor;
Assert.AreSame(
descriptor.Fields[TestAllTypes.SingleBoolFieldNumber],
descriptor.Fields[TestProtos.TestAllTypes.SingleBoolFieldNumber],
descriptor.Fields["single_bool"]);
}
[Test]
public void FieldDescriptor_NotFound()
{
var descriptor = TestAllTypes.Descriptor;
var descriptor = TestProtos.TestAllTypes.Descriptor;
Assert.Throws<KeyNotFoundException>(() => descriptor.Fields[999999].ToString());
Assert.Throws<KeyNotFoundException>(() => descriptor.Fields["not found"].ToString());
}
[Test]
public void GetExtensionValue()
{
var message = SampleMessages.CreateFullTestAllExtensions();
// test that the reflector works, since the reflector just runs through IExtendableMessage
Assert.AreEqual(message.GetExtension(OptionalBoolExtension), Proto2.TestAllExtensions.Descriptor.FindFieldByNumber(OptionalBoolExtension.FieldNumber).Accessor.GetValue(message));
}
[Test]
public void GetRepeatedExtensionValue()
{
// check to make sure repeated accessor uses GetOrRegister
var message = new Proto2.TestAllExtensions();
Assert.IsNull(message.GetExtension(RepeatedBoolExtension));
Assert.IsNotNull(Proto2.TestAllExtensions.Descriptor.FindFieldByNumber(RepeatedBoolExtension.FieldNumber).Accessor.GetValue(message));
Assert.IsNotNull(message.GetExtension(RepeatedBoolExtension));
message.ClearExtension(RepeatedBoolExtension);
Assert.IsNull(message.GetExtension(RepeatedBoolExtension));
}
}
}

View File

@ -32,6 +32,9 @@
using System;
using Google.Protobuf.TestProtos;
using Proto2 = Google.Protobuf.TestProtos.Proto2;
using static Google.Protobuf.TestProtos.Proto2.UnittestExtensions;
namespace Google.Protobuf
{
@ -60,7 +63,7 @@ namespace Google.Protobuf
SingleImportMessage = new ImportMessage { D = 20 },
SingleInt32 = 100,
SingleInt64 = 3210987654321,
SingleNestedEnum = TestAllTypes.Types.NestedEnum.Foo,
SingleNestedEnum = TestProtos.TestAllTypes.Types.NestedEnum.Foo,
SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 35 },
SinglePublicImportMessage = new PublicImportMessage { E = 54 },
SingleSfixed32 = -123,
@ -82,7 +85,7 @@ namespace Google.Protobuf
RepeatedImportMessage = { new ImportMessage { D = 20 }, new ImportMessage { D = 25 } },
RepeatedInt32 = { 100, 200 },
RepeatedInt64 = { 3210987654321, Int64.MaxValue },
RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.Foo, TestAllTypes.Types.NestedEnum.Neg },
RepeatedNestedEnum = { TestProtos.TestAllTypes.Types.NestedEnum.Foo, TestProtos.TestAllTypes.Types.NestedEnum.Neg },
RepeatedNestedMessage = { new TestAllTypes.Types.NestedMessage { Bb = 35 }, new TestAllTypes.Types.NestedMessage { Bb = 10 } },
RepeatedPublicImportMessage = { new PublicImportMessage { E = 54 }, new PublicImportMessage { E = -1 } },
RepeatedSfixed32 = { -123, 123 },
@ -95,5 +98,110 @@ namespace Google.Protobuf
OneofString = "Oneof string"
};
}
public static Proto2.TestAllTypes CreateFullTestAllTypesProto2()
{
return new Proto2.TestAllTypes
{
OptionalBool = true,
OptionalBytes = ByteString.CopyFrom(1, 2, 3, 4),
OptionalDouble = 23.5,
OptionalFixed32 = 23,
OptionalFixed64 = 1234567890123,
OptionalFloat = 12.25f,
OptionalForeignEnum = Proto2.ForeignEnum.ForeignBar,
OptionalForeignMessage = new Proto2.ForeignMessage { C = 10 },
OptionalImportEnum = Proto2.ImportEnum.ImportBaz,
OptionalImportMessage = new Proto2.ImportMessage { D = 20 },
OptionalInt32 = 100,
OptionalInt64 = 3210987654321,
OptionalNestedEnum = Proto2.TestAllTypes.Types.NestedEnum.Foo,
OptionalNestedMessage = new Proto2.TestAllTypes.Types.NestedMessage { Bb = 35 },
OptionalPublicImportMessage = new Proto2.PublicImportMessage { E = 54 },
OptionalSfixed32 = -123,
OptionalSfixed64 = -12345678901234,
OptionalSint32 = -456,
OptionalSint64 = -12345678901235,
OptionalString = "test",
OptionalUint32 = UInt32.MaxValue,
OptionalUint64 = UInt64.MaxValue,
OptionalGroup = new Proto2.TestAllTypes.Types.OptionalGroup { A = 10 },
RepeatedBool = { true, false },
RepeatedBytes = { ByteString.CopyFrom(1, 2, 3, 4), ByteString.CopyFrom(5, 6), ByteString.CopyFrom(new byte[1000]) },
RepeatedDouble = { -12.25, 23.5 },
RepeatedFixed32 = { UInt32.MaxValue, 23 },
RepeatedFixed64 = { UInt64.MaxValue, 1234567890123 },
RepeatedFloat = { 100f, 12.25f },
RepeatedForeignEnum = { Proto2.ForeignEnum.ForeignFoo, Proto2.ForeignEnum.ForeignBar },
RepeatedForeignMessage = { new Proto2.ForeignMessage(), new Proto2.ForeignMessage { C = 10 } },
RepeatedImportEnum = { Proto2.ImportEnum.ImportBaz, Proto2.ImportEnum.ImportFoo },
RepeatedImportMessage = { new Proto2.ImportMessage { D = 20 }, new Proto2.ImportMessage { D = 25 } },
RepeatedInt32 = { 100, 200 },
RepeatedInt64 = { 3210987654321, Int64.MaxValue },
RepeatedNestedEnum = { Proto2.TestAllTypes.Types.NestedEnum.Foo, Proto2.TestAllTypes.Types.NestedEnum.Neg },
RepeatedNestedMessage = { new Proto2.TestAllTypes.Types.NestedMessage { Bb = 35 }, new Proto2.TestAllTypes.Types.NestedMessage { Bb = 10 } },
RepeatedSfixed32 = { -123, 123 },
RepeatedSfixed64 = { -12345678901234, 12345678901234 },
RepeatedSint32 = { -456, 100 },
RepeatedSint64 = { -12345678901235, 123 },
RepeatedString = { "foo", "bar" },
RepeatedUint32 = { UInt32.MaxValue, UInt32.MinValue },
RepeatedUint64 = { UInt64.MaxValue, UInt32.MinValue },
RepeatedGroup = { new Proto2.TestAllTypes.Types.RepeatedGroup { A = 10 }, new Proto2.TestAllTypes.Types.RepeatedGroup { A = 20 } },
OneofString = "Oneof string"
};
}
public static Proto2.TestAllExtensions CreateFullTestAllExtensions()
{
var message = new Proto2.TestAllExtensions();
message.SetExtension(OptionalBoolExtension, true);
message.SetExtension(OptionalBytesExtension, ByteString.CopyFrom(1, 2, 3, 4));
message.SetExtension(OptionalDoubleExtension, 23.5);
message.SetExtension(OptionalFixed32Extension, 23u);
message.SetExtension(OptionalFixed64Extension, 1234567890123u);
message.SetExtension(OptionalFloatExtension, 12.25f);
message.SetExtension(OptionalForeignEnumExtension, Proto2.ForeignEnum.ForeignBar);
message.SetExtension(OptionalForeignMessageExtension, new Proto2.ForeignMessage { C = 10 });
message.SetExtension(OptionalImportEnumExtension, Proto2.ImportEnum.ImportBaz);
message.SetExtension(OptionalImportMessageExtension, new Proto2.ImportMessage { D = 20 });
message.SetExtension(OptionalInt32Extension, 100);
message.SetExtension(OptionalInt64Extension, 3210987654321);
message.SetExtension(OptionalNestedEnumExtension, Proto2.TestAllTypes.Types.NestedEnum.Foo);
message.SetExtension(OptionalNestedMessageExtension, new Proto2.TestAllTypes.Types.NestedMessage { Bb = 35 });
message.SetExtension(OptionalPublicImportMessageExtension, new Proto2.PublicImportMessage { E = 54 });
message.SetExtension(OptionalSfixed32Extension, -123);
message.SetExtension(OptionalSfixed64Extension, -12345678901234);
message.SetExtension(OptionalSint32Extension, -456);
message.SetExtension(OptionalSint64Extension, -12345678901235);
message.SetExtension(OptionalStringExtension, "test");
message.SetExtension(OptionalUint32Extension, UInt32.MaxValue);
message.SetExtension(OptionalUint64Extension, UInt64.MaxValue);
message.SetExtension(OptionalGroupExtension, new Proto2.OptionalGroup_extension { A = 10 });
message.GetOrInitializeExtension(RepeatedBoolExtension).AddRange(new[] { true, false });
message.GetOrInitializeExtension(RepeatedBytesExtension).AddRange(new[] { ByteString.CopyFrom(1, 2, 3, 4), ByteString.CopyFrom(5, 6), ByteString.CopyFrom(new byte[1000]) });
message.GetOrInitializeExtension(RepeatedDoubleExtension).AddRange(new[] { -12.25, 23.5 });
message.GetOrInitializeExtension(RepeatedFixed32Extension).AddRange(new[] { UInt32.MaxValue, 23u });
message.GetOrInitializeExtension(RepeatedFixed64Extension).AddRange(new[] { UInt64.MaxValue, 1234567890123ul });
message.GetOrInitializeExtension(RepeatedFloatExtension).AddRange(new[] { 100f, 12.25f });
message.GetOrInitializeExtension(RepeatedForeignEnumExtension).AddRange(new[] { Proto2.ForeignEnum.ForeignFoo, Proto2.ForeignEnum.ForeignBar });
message.GetOrInitializeExtension(RepeatedForeignMessageExtension).AddRange(new[] { new Proto2.ForeignMessage(), new Proto2.ForeignMessage { C = 10 } });
message.GetOrInitializeExtension(RepeatedImportEnumExtension).AddRange(new[] { Proto2.ImportEnum.ImportBaz, Proto2.ImportEnum.ImportFoo });
message.GetOrInitializeExtension(RepeatedImportMessageExtension).AddRange(new[] { new Proto2.ImportMessage { D = 20 }, new Proto2.ImportMessage { D = 25 } });
message.GetOrInitializeExtension(RepeatedInt32Extension).AddRange(new[] { 100, 200 });
message.GetOrInitializeExtension(RepeatedInt64Extension).AddRange(new[] { 3210987654321, Int64.MaxValue });
message.GetOrInitializeExtension(RepeatedNestedEnumExtension).AddRange(new[] { Proto2.TestAllTypes.Types.NestedEnum.Foo, Proto2.TestAllTypes.Types.NestedEnum.Neg });
message.GetOrInitializeExtension(RepeatedNestedMessageExtension).AddRange(new[] { new Proto2.TestAllTypes.Types.NestedMessage { Bb = 35 }, new Proto2.TestAllTypes.Types.NestedMessage { Bb = 10 } });
message.GetOrInitializeExtension(RepeatedSfixed32Extension).AddRange(new[] { -123, 123 });
message.GetOrInitializeExtension(RepeatedSfixed64Extension).AddRange(new[] { -12345678901234, 12345678901234 });
message.GetOrInitializeExtension(RepeatedSint32Extension).AddRange(new[] { -456, 100 });
message.GetOrInitializeExtension(RepeatedSint64Extension).AddRange(new[] { -12345678901235, 123 });
message.GetOrInitializeExtension(RepeatedStringExtension).AddRange(new[] { "foo", "bar" });
message.GetOrInitializeExtension(RepeatedUint32Extension).AddRange(new[] { UInt32.MaxValue, UInt32.MinValue });
message.GetOrInitializeExtension(RepeatedUint64Extension).AddRange(new[] { UInt64.MaxValue, UInt32.MinValue });
message.GetOrInitializeExtension(RepeatedGroupExtension).AddRange(new[] { new Proto2.RepeatedGroup_extension { A = 10 }, new Proto2.RepeatedGroup_extension { A = 20 } });
message.SetExtension(OneofStringExtension, "Oneof string");
return message;
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -165,7 +165,7 @@ namespace UnitTest.Issues.TestProtos {
}
/// <summary>Holder for extension identifiers generated from the top level of unittest_custom_options_proto3.proto</summary>
internal static partial class UnittestCustomOptionsProto3Extensions {
public static partial class UnittestCustomOptionsProto3Extensions {
public static readonly pb::Extension<global::Google.Protobuf.Reflection.FileOptions, ulong> FileOpt1 =
new pb::Extension<global::Google.Protobuf.Reflection.FileOptions, ulong>(7736974, pb::FieldCodec.ForUInt64(61895792, 0UL));
public static readonly pb::Extension<global::Google.Protobuf.Reflection.MessageOptions, int> MessageOpt1 =
@ -2138,7 +2138,7 @@ namespace UnitTest.Issues.TestProtos {
#region Extensions
/// <summary>Container for extensions for other messages declared in the ComplexOptionType4 message type.</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
internal static partial class Extensions {
public static partial class Extensions {
public static readonly pb::Extension<global::Google.Protobuf.Reflection.MessageOptions, global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4> ComplexOpt4 =
new pb::Extension<global::Google.Protobuf.Reflection.MessageOptions, global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4>(7633546, pb::FieldCodec.ForMessage(61068370, global::UnitTest.Issues.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.Parser));
}

View File

@ -0,0 +1,210 @@
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: unittest_import.proto
// </auto-generated>
#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 Google.Protobuf.TestProtos.Proto2 {
/// <summary>Holder for reflection information generated from unittest_import.proto</summary>
public static partial class UnittestImportReflection {
#region Descriptor
/// <summary>File descriptor for unittest_import.proto</summary>
public static pbr::FileDescriptor Descriptor {
get { return descriptor; }
}
private static pbr::FileDescriptor descriptor;
static UnittestImportReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"ChV1bml0dGVzdF9pbXBvcnQucHJvdG8SH3Byb3RvYnVmX3VuaXR0ZXN0X2lt",
"cG9ydF9wcm90bzIaHHVuaXR0ZXN0X2ltcG9ydF9wdWJsaWMucHJvdG8iGgoN",
"SW1wb3J0TWVzc2FnZRIJCgFkGAEgASgFKjwKCkltcG9ydEVudW0SDgoKSU1Q",
"T1JUX0ZPTxAHEg4KCklNUE9SVF9CQVIQCBIOCgpJTVBPUlRfQkFaEAkqMQoQ",
"SW1wb3J0RW51bUZvck1hcBILCgdVTktOT1dOEAASBwoDRk9PEAESBwoDQkFS",
"EAJCKUgB+AEBqgIhR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3MuUHJvdG8y",
"UAA="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.Proto2.UnittestImportPublicReflection.Descriptor, },
new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.Proto2.ImportEnum), typeof(global::Google.Protobuf.TestProtos.Proto2.ImportEnumForMap), }, null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.ImportMessage), global::Google.Protobuf.TestProtos.Proto2.ImportMessage.Parser, new[]{ "D" }, null, null, null, null)
}));
}
#endregion
}
#region Enums
public enum ImportEnum {
[pbr::OriginalName("IMPORT_FOO")] ImportFoo = 7,
[pbr::OriginalName("IMPORT_BAR")] ImportBar = 8,
[pbr::OriginalName("IMPORT_BAZ")] ImportBaz = 9,
}
/// <summary>
/// To use an enum in a map, it must has the first value as 0.
/// </summary>
public enum ImportEnumForMap {
[pbr::OriginalName("UNKNOWN")] Unknown = 0,
[pbr::OriginalName("FOO")] Foo = 1,
[pbr::OriginalName("BAR")] Bar = 2,
}
#endregion
#region Messages
public sealed partial class ImportMessage : pb::IMessage<ImportMessage> {
private static readonly pb::MessageParser<ImportMessage> _parser = new pb::MessageParser<ImportMessage>(() => new ImportMessage());
private pb::UnknownFieldSet _unknownFields;
private int _hasBits0;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ImportMessage> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
get { return global::Google.Protobuf.TestProtos.Proto2.UnittestImportReflection.Descriptor.MessageTypes[0]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public ImportMessage() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public ImportMessage(ImportMessage other) : this() {
_hasBits0 = other._hasBits0;
d_ = other.d_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public ImportMessage Clone() {
return new ImportMessage(this);
}
/// <summary>Field number for the "d" field.</summary>
public const int DFieldNumber = 1;
private readonly static int DDefaultValue = 0;
private int d_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int D {
get { if ((_hasBits0 & 1) != 0) { return d_; } else { return DDefaultValue; } }
set {
_hasBits0 |= 1;
d_ = value;
}
}
/// <summary>Gets whether the "d" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasD {
get { return (_hasBits0 & 1) != 0; }
}
/// <summary>Clears the value of the "d" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearD() {
_hasBits0 &= ~1;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as ImportMessage);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Equals(ImportMessage other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (D != other.D) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (HasD) hash ^= D.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
if (HasD) {
output.WriteRawTag(8);
output.WriteInt32(D);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
if (HasD) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(D);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(ImportMessage other) {
if (other == null) {
return;
}
if (other.HasD) {
D = other.D;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
D = input.ReadInt32();
break;
}
}
}
}
}
#endregion
}
#endregion Designer generated code

View File

@ -0,0 +1,188 @@
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: unittest_import_public.proto
// </auto-generated>
#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 Google.Protobuf.TestProtos.Proto2 {
/// <summary>Holder for reflection information generated from unittest_import_public.proto</summary>
public static partial class UnittestImportPublicReflection {
#region Descriptor
/// <summary>File descriptor for unittest_import_public.proto</summary>
public static pbr::FileDescriptor Descriptor {
get { return descriptor; }
}
private static pbr::FileDescriptor descriptor;
static UnittestImportPublicReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"Chx1bml0dGVzdF9pbXBvcnRfcHVibGljLnByb3RvEh9wcm90b2J1Zl91bml0",
"dGVzdF9pbXBvcnRfcHJvdG8yIiAKE1B1YmxpY0ltcG9ydE1lc3NhZ2USCQoB",
"ZRgBIAEoBUIkqgIhR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3MuUHJvdG8y"));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.TestProtos.Proto2.PublicImportMessage), global::Google.Protobuf.TestProtos.Proto2.PublicImportMessage.Parser, new[]{ "E" }, null, null, null, null)
}));
}
#endregion
}
#region Messages
public sealed partial class PublicImportMessage : pb::IMessage<PublicImportMessage> {
private static readonly pb::MessageParser<PublicImportMessage> _parser = new pb::MessageParser<PublicImportMessage>(() => new PublicImportMessage());
private pb::UnknownFieldSet _unknownFields;
private int _hasBits0;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<PublicImportMessage> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
get { return global::Google.Protobuf.TestProtos.Proto2.UnittestImportPublicReflection.Descriptor.MessageTypes[0]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public PublicImportMessage() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public PublicImportMessage(PublicImportMessage other) : this() {
_hasBits0 = other._hasBits0;
e_ = other.e_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public PublicImportMessage Clone() {
return new PublicImportMessage(this);
}
/// <summary>Field number for the "e" field.</summary>
public const int EFieldNumber = 1;
private readonly static int EDefaultValue = 0;
private int e_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int E {
get { if ((_hasBits0 & 1) != 0) { return e_; } else { return EDefaultValue; } }
set {
_hasBits0 |= 1;
e_ = value;
}
}
/// <summary>Gets whether the "e" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasE {
get { return (_hasBits0 & 1) != 0; }
}
/// <summary>Clears the value of the "e" field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearE() {
_hasBits0 &= ~1;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as PublicImportMessage);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Equals(PublicImportMessage other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (E != other.E) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (HasE) hash ^= E.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
if (HasE) {
output.WriteRawTag(8);
output.WriteInt32(E);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
if (HasE) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(E);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(PublicImportMessage other) {
if (other == null) {
return;
}
if (other.HasE) {
E = other.E;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
E = input.ReadInt32();
break;
}
}
}
}
}
#endregion
}
#endregion Designer generated code

View File

@ -33,12 +33,25 @@
using System;
using System.IO;
using Google.Protobuf.TestProtos;
using Proto2 = Google.Protobuf.TestProtos.Proto2;
using NUnit.Framework;
namespace Google.Protobuf
{
public class UnknownFieldSetTest
{
public class Data
{
public static System.Collections.IEnumerable Messages
{
get
{
yield return SampleMessages.CreateFullTestAllTypesProto2();
yield return SampleMessages.CreateFullTestAllTypes();
}
}
}
[Test]
public void EmptyUnknownFieldSet()
{
@ -60,24 +73,23 @@ namespace Google.Protobuf
}
[Test]
public void TestMergeCodedInput()
[TestCaseSource(typeof(Data), "Messages")]
public void TestMergeCodedInput(IMessage message)
{
var message = SampleMessages.CreateFullTestAllTypes();
var emptyMessage = new TestEmptyMessage();
emptyMessage.MergeFrom(message.ToByteArray());
Assert.AreEqual(message.CalculateSize(), emptyMessage.CalculateSize());
Assert.AreEqual(message.ToByteArray(), emptyMessage.ToByteArray());
var newMessage = new TestAllTypes();
newMessage.MergeFrom(emptyMessage.ToByteArray());
var newMessage = message.Descriptor.Parser.ParseFrom(emptyMessage.ToByteArray());
Assert.AreEqual(message, newMessage);
Assert.AreEqual(message.CalculateSize(), newMessage.CalculateSize());
}
[Test]
public void TestMergeMessage()
[TestCaseSource(typeof(Data), "Messages")]
public void TestMergeMessage(IMessage message)
{
var message = SampleMessages.CreateFullTestAllTypes();
var emptyMessage = new TestEmptyMessage();
var otherEmptyMessage = new TestEmptyMessage();
emptyMessage.MergeFrom(message.ToByteArray());
@ -88,9 +100,9 @@ namespace Google.Protobuf
}
[Test]
public void TestEquals()
[TestCaseSource(typeof(Data), "Messages")]
public void TestEquals(IMessage message)
{
var message = SampleMessages.CreateFullTestAllTypes();
var emptyMessage = new TestEmptyMessage();
var otherEmptyMessage = new TestEmptyMessage();
Assert.AreEqual(emptyMessage, otherEmptyMessage);
@ -101,9 +113,9 @@ namespace Google.Protobuf
}
[Test]
public void TestHashCode()
[TestCaseSource(typeof(Data), "Messages")]
public void TestHashCode(IMessage message)
{
var message = SampleMessages.CreateFullTestAllTypes();
var emptyMessage = new TestEmptyMessage();
int hashCode = emptyMessage.GetHashCode();
emptyMessage.MergeFrom(message.ToByteArray());
@ -111,7 +123,8 @@ namespace Google.Protobuf
}
[Test]
public void TestClone()
[TestCaseSource(typeof(Data), "Messages")]
public void TestClone(IMessage message)
{
var emptyMessage = new TestEmptyMessage();
var otherEmptyMessage = new TestEmptyMessage();
@ -119,7 +132,6 @@ namespace Google.Protobuf
Assert.AreEqual(emptyMessage.CalculateSize(), otherEmptyMessage.CalculateSize());
Assert.AreEqual(emptyMessage.ToByteArray(), otherEmptyMessage.ToByteArray());
var message = SampleMessages.CreateFullTestAllTypes();
emptyMessage.MergeFrom(message.ToByteArray());
otherEmptyMessage = emptyMessage.Clone();
Assert.AreEqual(message.CalculateSize(), otherEmptyMessage.CalculateSize());
@ -127,9 +139,9 @@ namespace Google.Protobuf
}
[Test]
public void TestDiscardUnknownFields()
[TestCaseSource(typeof(Data), "Messages")]
public void TestDiscardUnknownFields(IMessage message)
{
var message = SampleMessages.CreateFullTestAllTypes();
var goldenEmptyMessage = new TestEmptyMessage();
byte[] data = message.ToByteArray();
int fullSize = message.CalculateSize();

View File

@ -148,6 +148,10 @@ namespace Google.Protobuf.Collections
{
var sizeCalculator = codec.ValueSizeCalculator;
int size = count * CodedOutputStream.ComputeRawVarint32Size(tag);
if (codec.EndTag != 0)
{
size += count * CodedOutputStream.ComputeRawVarint32Size(codec.EndTag);
}
for (int i = 0; i < count; i++)
{
size += sizeCalculator(array[i]);

View File

@ -89,7 +89,7 @@ namespace Google.Protobuf
/// <summary>
/// Gets the value of the specified repeated extension, registering it if it doesn't exist
/// </summary>
public static RepeatedField<TValue> GetOrRegister<TTarget, TValue>(ref ExtensionSet<TTarget> set, RepeatedExtension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
public static RepeatedField<TValue> GetOrInitialize<TTarget, TValue>(ref ExtensionSet<TTarget> set, RepeatedExtension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
{
IExtensionValue value;
if (set == null)
@ -115,6 +115,8 @@ namespace Google.Protobuf
/// </summary>
public static void Set<TTarget, TValue>(ref ExtensionSet<TTarget> set, Extension<TTarget, TValue> extension, TValue value) where TTarget : IExtendableMessage<TTarget>
{
ProtoPreconditions.CheckNotNullUnconstrained(value, nameof(value));
IExtensionValue extensionValue;
if (set == null)
{
@ -330,5 +332,10 @@ namespace Google.Protobuf
value.WriteTo(stream);
}
}
internal bool IsInitialized()
{
return ValuesByNumber.Values.All(v => v.IsInitialized());
}
}
}

View File

@ -32,6 +32,7 @@
using Google.Protobuf.Collections;
using System;
using System.Linq;
namespace Google.Protobuf
{
@ -41,11 +42,11 @@ namespace Google.Protobuf
void MergeFrom(IExtensionValue value);
void WriteTo(CodedOutputStream output);
int CalculateSize();
bool IsInitialized();
}
internal sealed class ExtensionValue<T> : IExtensionValue
{
private bool hasValue;
private T field;
private FieldCodec<T> codec;
@ -57,10 +58,6 @@ namespace Google.Protobuf
public int CalculateSize()
{
if (!hasValue)
{
return 0;
}
return codec.CalculateSizeWithTag(field);
}
@ -68,7 +65,6 @@ namespace Google.Protobuf
{
return new ExtensionValue<T>(codec)
{
hasValue = hasValue,
field = field is IDeepCloneable<T> ? (field as IDeepCloneable<T>).Clone() : field
};
}
@ -80,7 +76,6 @@ namespace Google.Protobuf
return other is ExtensionValue<T>
&& codec.Equals((other as ExtensionValue<T>).codec)
&& hasValue.Equals((other as ExtensionValue<T>).hasValue)
&& Equals(field, (other as ExtensionValue<T>).field);
// we check for equality in the codec since we could have equal field values however the values could be written in different ways
}
@ -90,7 +85,6 @@ namespace Google.Protobuf
unchecked
{
int hash = 17;
hash = hash * 31 + hasValue.GetHashCode();
hash = hash * 31 + field.GetHashCode();
hash = hash * 31 + codec.GetHashCode();
return hash;
@ -99,7 +93,6 @@ namespace Google.Protobuf
public void MergeFrom(CodedInputStream input)
{
hasValue = true;
codec.ValueMerger(input, ref field);
}
@ -108,16 +101,11 @@ namespace Google.Protobuf
if (value is ExtensionValue<T>)
{
var extensionValue = value as ExtensionValue<T>;
if (extensionValue.hasValue)
{
hasValue |= codec.FieldMerger(ref field, extensionValue.field);
}
codec.FieldMerger(ref field, extensionValue.field);
}
}
public void WriteTo(CodedOutputStream output)
{
if (hasValue)
{
output.WriteTag(codec.Tag);
codec.ValueWriter(output, field);
@ -126,17 +114,25 @@ namespace Google.Protobuf
output.WriteTag(codec.EndTag);
}
}
}
public T GetValue() => field;
public void SetValue(T value)
{
hasValue = true;
field = value;
}
public bool HasValue => hasValue;
public bool IsInitialized()
{
if (field is IMessage)
{
return (field as IMessage).IsInitialized();
}
else
{
return true;
}
}
}
internal sealed class RepeatedExtensionValue<T> : IExtensionValue
@ -203,5 +199,26 @@ namespace Google.Protobuf
}
public RepeatedField<T> GetValue() => field;
public bool IsInitialized()
{
for (int i = 0; i < field.Count; i++)
{
var element = field[i];
if (element is IMessage)
{
if (!(element as IMessage).IsInitialized())
{
return false;
}
}
else
{
break;
}
}
return true;
}
}
}

View File

@ -218,7 +218,7 @@ namespace Google.Protobuf
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<string> ForString(uint tag, string defaultValue)
{
return new FieldCodec<string>(input => input.ReadString(), (output, value) => output.WriteString(value), CodedOutputStream.ComputeStringSize, tag);
return new FieldCodec<string>(input => input.ReadString(), (output, value) => output.WriteString(value), CodedOutputStream.ComputeStringSize, tag, defaultValue);
}
/// <summary>
@ -229,7 +229,7 @@ namespace Google.Protobuf
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<ByteString> ForBytes(uint tag, ByteString defaultValue)
{
return new FieldCodec<ByteString>(input => input.ReadBytes(), (output, value) => output.WriteBytes(value), CodedOutputStream.ComputeBytesSize, tag);
return new FieldCodec<ByteString>(input => input.ReadBytes(), (output, value) => output.WriteBytes(value), CodedOutputStream.ComputeBytesSize, tag, defaultValue);
}
/// <summary>
@ -240,7 +240,7 @@ namespace Google.Protobuf
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<bool> ForBool(uint tag, bool defaultValue)
{
return new FieldCodec<bool>(input => input.ReadBool(), (output, value) => output.WriteBool(value), CodedOutputStream.BoolSize, tag);
return new FieldCodec<bool>(input => input.ReadBool(), (output, value) => output.WriteBool(value), CodedOutputStream.BoolSize, tag, defaultValue);
}
/// <summary>
@ -251,7 +251,7 @@ namespace Google.Protobuf
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<int> ForInt32(uint tag, int defaultValue)
{
return new FieldCodec<int>(input => input.ReadInt32(), (output, value) => output.WriteInt32(value), CodedOutputStream.ComputeInt32Size, tag);
return new FieldCodec<int>(input => input.ReadInt32(), (output, value) => output.WriteInt32(value), CodedOutputStream.ComputeInt32Size, tag, defaultValue);
}
/// <summary>
@ -262,7 +262,7 @@ namespace Google.Protobuf
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<int> ForSInt32(uint tag, int defaultValue)
{
return new FieldCodec<int>(input => input.ReadSInt32(), (output, value) => output.WriteSInt32(value), CodedOutputStream.ComputeSInt32Size, tag);
return new FieldCodec<int>(input => input.ReadSInt32(), (output, value) => output.WriteSInt32(value), CodedOutputStream.ComputeSInt32Size, tag, defaultValue);
}
/// <summary>
@ -273,7 +273,7 @@ namespace Google.Protobuf
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<uint> ForFixed32(uint tag, uint defaultValue)
{
return new FieldCodec<uint>(input => input.ReadFixed32(), (output, value) => output.WriteFixed32(value), 4, tag);
return new FieldCodec<uint>(input => input.ReadFixed32(), (output, value) => output.WriteFixed32(value), 4, tag, defaultValue);
}
/// <summary>
@ -284,7 +284,7 @@ namespace Google.Protobuf
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<int> ForSFixed32(uint tag, int defaultValue)
{
return new FieldCodec<int>(input => input.ReadSFixed32(), (output, value) => output.WriteSFixed32(value), 4, tag);
return new FieldCodec<int>(input => input.ReadSFixed32(), (output, value) => output.WriteSFixed32(value), 4, tag, defaultValue);
}
/// <summary>
@ -295,7 +295,7 @@ namespace Google.Protobuf
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<uint> ForUInt32(uint tag, uint defaultValue)
{
return new FieldCodec<uint>(input => input.ReadUInt32(), (output, value) => output.WriteUInt32(value), CodedOutputStream.ComputeUInt32Size, tag);
return new FieldCodec<uint>(input => input.ReadUInt32(), (output, value) => output.WriteUInt32(value), CodedOutputStream.ComputeUInt32Size, tag, defaultValue);
}
/// <summary>
@ -306,7 +306,7 @@ namespace Google.Protobuf
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<long> ForInt64(uint tag, long defaultValue)
{
return new FieldCodec<long>(input => input.ReadInt64(), (output, value) => output.WriteInt64(value), CodedOutputStream.ComputeInt64Size, tag);
return new FieldCodec<long>(input => input.ReadInt64(), (output, value) => output.WriteInt64(value), CodedOutputStream.ComputeInt64Size, tag, defaultValue);
}
/// <summary>
@ -317,7 +317,7 @@ namespace Google.Protobuf
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<long> ForSInt64(uint tag, long defaultValue)
{
return new FieldCodec<long>(input => input.ReadSInt64(), (output, value) => output.WriteSInt64(value), CodedOutputStream.ComputeSInt64Size, tag);
return new FieldCodec<long>(input => input.ReadSInt64(), (output, value) => output.WriteSInt64(value), CodedOutputStream.ComputeSInt64Size, tag, defaultValue);
}
/// <summary>
@ -328,7 +328,7 @@ namespace Google.Protobuf
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<ulong> ForFixed64(uint tag, ulong defaultValue)
{
return new FieldCodec<ulong>(input => input.ReadFixed64(), (output, value) => output.WriteFixed64(value), 8, tag);
return new FieldCodec<ulong>(input => input.ReadFixed64(), (output, value) => output.WriteFixed64(value), 8, tag, defaultValue);
}
/// <summary>
@ -339,7 +339,7 @@ namespace Google.Protobuf
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<long> ForSFixed64(uint tag, long defaultValue)
{
return new FieldCodec<long>(input => input.ReadSFixed64(), (output, value) => output.WriteSFixed64(value), 8, tag);
return new FieldCodec<long>(input => input.ReadSFixed64(), (output, value) => output.WriteSFixed64(value), 8, tag, defaultValue);
}
/// <summary>
@ -350,7 +350,7 @@ namespace Google.Protobuf
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<ulong> ForUInt64(uint tag, ulong defaultValue)
{
return new FieldCodec<ulong>(input => input.ReadUInt64(), (output, value) => output.WriteUInt64(value), CodedOutputStream.ComputeUInt64Size, tag);
return new FieldCodec<ulong>(input => input.ReadUInt64(), (output, value) => output.WriteUInt64(value), CodedOutputStream.ComputeUInt64Size, tag, defaultValue);
}
/// <summary>
@ -361,7 +361,7 @@ namespace Google.Protobuf
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<float> ForFloat(uint tag, float defaultValue)
{
return new FieldCodec<float>(input => input.ReadFloat(), (output, value) => output.WriteFloat(value), CodedOutputStream.FloatSize, tag);
return new FieldCodec<float>(input => input.ReadFloat(), (output, value) => output.WriteFloat(value), CodedOutputStream.FloatSize, tag, defaultValue);
}
/// <summary>
@ -372,7 +372,7 @@ namespace Google.Protobuf
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<double> ForDouble(uint tag, double defaultValue)
{
return new FieldCodec<double>(input => input.ReadDouble(), (output, value) => output.WriteDouble(value), CodedOutputStream.DoubleSize, tag);
return new FieldCodec<double>(input => input.ReadDouble(), (output, value) => output.WriteDouble(value), CodedOutputStream.DoubleSize, tag, defaultValue);
}
// Enums are tricky. We can probably use expression trees to build these delegates automatically,
@ -391,7 +391,7 @@ namespace Google.Protobuf
return new FieldCodec<T>(input => fromInt32(
input.ReadEnum()),
(output, value) => output.WriteEnum(toInt32(value)),
value => CodedOutputStream.ComputeEnumSize(toInt32(value)), tag);
value => CodedOutputStream.ComputeEnumSize(toInt32(value)), tag, defaultValue);
}
/// <summary>
@ -402,8 +402,15 @@ namespace Google.Protobuf
/// <returns>A codec for the given tag.</returns>
public static FieldCodec<T> ForMessage<T>(uint tag, MessageParser<T> parser) where T : class, IMessage<T>
{
return new FieldCodec<T>(input => { T message = parser.CreateTemplate(); input.ReadMessage(message); return message; },
(output, value) => output.WriteMessage(value), (CodedInputStream i, ref T v) =>
return new FieldCodec<T>(
input =>
{
T message = parser.CreateTemplate();
input.ReadMessage(message);
return message;
},
(output, value) => output.WriteMessage(value),
(CodedInputStream i, ref T v) =>
{
if (v == null)
{
@ -427,7 +434,8 @@ namespace Google.Protobuf
v.MergeFrom(v2);
}
return true;
}, message => CodedOutputStream.ComputeMessageSize(message), tag);
},
message => CodedOutputStream.ComputeMessageSize(message), tag);
}
/// <summary>
@ -439,8 +447,16 @@ namespace Google.Protobuf
/// <returns>A codec for given tag</returns>
public static FieldCodec<T> ForGroup<T>(uint startTag, uint endTag, MessageParser<T> parser) where T : class, IMessage<T>
{
return new FieldCodec<T>(input => { T message = parser.CreateTemplate(); input.ReadGroup(message); return message; },
(output, value) => output.WriteGroup(value), (CodedInputStream i, ref T v) => {
return new FieldCodec<T>(
input =>
{
T message = parser.CreateTemplate();
input.ReadGroup(message);
return message;
},
(output, value) => output.WriteGroup(value),
(CodedInputStream i, ref T v) =>
{
if (v == null)
{
v = parser.CreateTemplate();
@ -463,7 +479,8 @@ namespace Google.Protobuf
v.MergeFrom(v2);
}
return true;
}, message => CodedOutputStream.ComputeGroupSize(message), startTag, endTag);
},
message => CodedOutputStream.ComputeGroupSize(message), startTag, endTag);
}
/// <summary>
@ -689,7 +706,8 @@ namespace Google.Protobuf
Func<CodedInputStream, T> reader,
Action<CodedOutputStream, T> writer,
int fixedSize,
uint tag) : this(reader, writer, _ => fixedSize, tag)
uint tag,
T defaultValue) : this(reader, writer, _ => fixedSize, tag, defaultValue)
{
FixedSize = fixedSize;
}
@ -699,7 +717,7 @@ namespace Google.Protobuf
Action<CodedOutputStream, T> writer,
Func<T, int> sizeCalculator,
uint tag,
uint endTag = 0) : this(reader, writer, (CodedInputStream i, ref T v) => v = reader(i), (ref T v, T v2) => { v = v2; return true; }, sizeCalculator, tag, endTag, DefaultDefault)
T defaultValue) : this(reader, writer, (CodedInputStream i, ref T v) => v = reader(i), (ref T v, T v2) => { v = v2; return true; }, sizeCalculator, tag, 0, defaultValue)
{
}
@ -731,6 +749,7 @@ namespace Google.Protobuf
ValueSizeCalculator = sizeCalculator;
FixedSize = 0;
Tag = tag;
EndTag = endTag;
DefaultValue = defaultValue;
tagSize = CodedOutputStream.ComputeRawVarint32Size(tag);
if (endTag != 0)

View File

@ -35,7 +35,8 @@ using Google.Protobuf.Collections;
namespace Google.Protobuf
{
/// <summary>
/// Generic interface for a Protocol Buffers message containing one or more extensions, where the type parameter is expected to be the same type as the implementation class
/// Generic interface for a Protocol Buffers message containing one or more extensions, where the type parameter is expected to be the same type as the implementation class.
/// This interface is experiemental and is subject to change.
/// </summary>
public interface IExtendableMessage<T> : IMessage<T> where T : IExtendableMessage<T>
{
@ -46,14 +47,14 @@ namespace Google.Protobuf
/// <summary>
/// Gets the value of the specified repeated extension or null if the extension isn't registered in this set.
/// For a version of this method that never returns null, use <see cref="IExtendableMessage{T}.GetOrRegisterExtension{TValue}(RepeatedExtension{T, TValue})"/>
/// For a version of this method that never returns null, use <see cref="IExtendableMessage{T}.GetOrInitializeExtension{TValue}(RepeatedExtension{T, TValue})"/>
/// </summary>
RepeatedField<TValue> GetExtension<TValue>(RepeatedExtension<T, TValue> extension);
/// <summary>
/// Gets the value of the specified repeated extension, registering it if it isn't
/// Gets the value of the specified repeated extension, registering it if it hasn't already been registered.
/// </summary>
RepeatedField<TValue> GetOrRegisterExtension<TValue>(RepeatedExtension<T, TValue> extension);
RepeatedField<TValue> GetOrInitializeExtension<TValue>(RepeatedExtension<T, TValue> extension);
/// <summary>
/// Sets the value of the specified extension

View File

@ -148,20 +148,33 @@ namespace Google.Protobuf
/// </summary>
public static bool IsInitialized(this IMessage message)
{
if (message.Descriptor.File.Proto.Syntax != "proto2")
if (message.Descriptor.File.Syntax == Syntax.Proto3)
{
return true;
}
if (!message.Descriptor.IsExtensionsInitialized(message))
{
return false;
}
return message.Descriptor
.Fields
.InDeclarationOrder()
.All(f =>
{
if (f.IsMap)
{
var valueField = f.MessageType.Fields[2];
if (valueField.FieldType == FieldType.Message)
{
var map = (IDictionary)f.Accessor.GetValue(message);
return map.Values.OfType<IMessage>().All(IsInitialized);
return map.Values.Cast<IMessage>().All(IsInitialized);
}
else
{
return true;
}
}
else if (f.IsRepeated && f.FieldType == FieldType.Message || f.FieldType == FieldType.Group)
{

View File

@ -254,12 +254,9 @@ namespace Google.Protobuf.Reflection
if (extensionValue is ExtensionValue<T>)
{
ExtensionValue<T> single = extensionValue as ExtensionValue<T>;
if (single.HasValue)
{
value = single.GetValue();
return true;
}
}
else if (extensionValue is RepeatedExtensionValue<T>)
{
RepeatedExtensionValue<T> repeated = extensionValue as RepeatedExtensionValue<T>;
@ -278,14 +275,11 @@ namespace Google.Protobuf.Reflection
var typeInfo = type.GetTypeInfo();
var typeArgs = typeInfo.GenericTypeArguments;
if (typeArgs.Length == 1 && typeArgs[0].GetTypeInfo().IsEnum)
{
if ((bool)typeInfo.GetDeclaredProperty(nameof(ExtensionValue<T>.HasValue)).GetValue(extensionValue))
{
value = (T)typeInfo.GetDeclaredMethod(nameof(ExtensionValue<T>.GetValue)).Invoke(extensionValue, EmptyParameters);
return true;
}
}
}
else if (type.GetGenericTypeDefinition() == typeof(RepeatedExtensionValue<>))
{
var typeInfo = type.GetTypeInfo();

View File

@ -12,7 +12,7 @@ using scg = global::System.Collections.Generic;
namespace Google.Protobuf.Reflection {
/// <summary>Holder for reflection information generated from google/protobuf/descriptor.proto</summary>
internal static partial class DescriptorReflection {
public static partial class DescriptorReflection {
#region Descriptor
/// <summary>File descriptor for google/protobuf/descriptor.proto</summary>
@ -193,7 +193,7 @@ namespace Google.Protobuf.Reflection {
/// The protocol compiler can output a FileDescriptorSet containing the .proto
/// files it parses.
/// </summary>
internal sealed partial class FileDescriptorSet : pb::IMessage<FileDescriptorSet> {
public sealed partial class FileDescriptorSet : pb::IMessage<FileDescriptorSet> {
private static readonly pb::MessageParser<FileDescriptorSet> _parser = new pb::MessageParser<FileDescriptorSet>(() => new FileDescriptorSet());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -317,7 +317,7 @@ namespace Google.Protobuf.Reflection {
/// <summary>
/// Describes a complete .proto file.
/// </summary>
internal sealed partial class FileDescriptorProto : pb::IMessage<FileDescriptorProto> {
public sealed partial class FileDescriptorProto : pb::IMessage<FileDescriptorProto> {
private static readonly pb::MessageParser<FileDescriptorProto> _parser = new pb::MessageParser<FileDescriptorProto>(() => new FileDescriptorProto());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -800,7 +800,7 @@ namespace Google.Protobuf.Reflection {
/// <summary>
/// Describes a message type.
/// </summary>
internal sealed partial class DescriptorProto : pb::IMessage<DescriptorProto> {
public sealed partial class DescriptorProto : pb::IMessage<DescriptorProto> {
private static readonly pb::MessageParser<DescriptorProto> _parser = new pb::MessageParser<DescriptorProto>(() => new DescriptorProto());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -1151,7 +1151,7 @@ namespace Google.Protobuf.Reflection {
/// <summary>Container for nested types declared in the DescriptorProto message type.</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static partial class Types {
internal sealed partial class ExtensionRange : pb::IMessage<ExtensionRange> {
public sealed partial class ExtensionRange : pb::IMessage<ExtensionRange> {
private static readonly pb::MessageParser<ExtensionRange> _parser = new pb::MessageParser<ExtensionRange>(() => new ExtensionRange());
private pb::UnknownFieldSet _unknownFields;
private int _hasBits0;
@ -1391,7 +1391,7 @@ namespace Google.Protobuf.Reflection {
/// fields or extension ranges in the same message. Reserved ranges may
/// not overlap.
/// </summary>
internal sealed partial class ReservedRange : pb::IMessage<ReservedRange> {
public sealed partial class ReservedRange : pb::IMessage<ReservedRange> {
private static readonly pb::MessageParser<ReservedRange> _parser = new pb::MessageParser<ReservedRange>(() => new ReservedRange());
private pb::UnknownFieldSet _unknownFields;
private int _hasBits0;
@ -1587,10 +1587,11 @@ namespace Google.Protobuf.Reflection {
}
internal sealed partial class ExtensionRangeOptions : pb::IExtendableMessage<ExtensionRangeOptions> {
public sealed partial class ExtensionRangeOptions : pb::IExtendableMessage<ExtensionRangeOptions> {
private static readonly pb::MessageParser<ExtensionRangeOptions> _parser = new pb::MessageParser<ExtensionRangeOptions>(() => new ExtensionRangeOptions());
private pb::UnknownFieldSet _unknownFields;
internal pb::ExtensionSet<ExtensionRangeOptions> _extensions;
private pb::ExtensionSet<ExtensionRangeOptions> _Extensions => _extensions;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ExtensionRangeOptions> Parser { get { return _parser; } }
@ -1732,8 +1733,8 @@ namespace Google.Protobuf.Reflection {
public pbc::RepeatedField<TValue> GetExtension<TValue>(pb::RepeatedExtension<ExtensionRangeOptions, TValue> extension) {
return pb::ExtensionSet.Get(ref _extensions, extension);
}
public pbc::RepeatedField<TValue> GetOrRegisterExtension<TValue>(pb::RepeatedExtension<ExtensionRangeOptions, TValue> extension) {
return pb::ExtensionSet.GetOrRegister(ref _extensions, extension);
public pbc::RepeatedField<TValue> GetOrInitializeExtension<TValue>(pb::RepeatedExtension<ExtensionRangeOptions, TValue> extension) {
return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension);
}
public void SetExtension<TValue>(pb::Extension<ExtensionRangeOptions, TValue> extension, TValue value) {
pb::ExtensionSet.Set(ref _extensions, extension, value);
@ -1753,7 +1754,7 @@ namespace Google.Protobuf.Reflection {
/// <summary>
/// Describes a field within a message.
/// </summary>
internal sealed partial class FieldDescriptorProto : pb::IMessage<FieldDescriptorProto> {
public sealed partial class FieldDescriptorProto : pb::IMessage<FieldDescriptorProto> {
private static readonly pb::MessageParser<FieldDescriptorProto> _parser = new pb::MessageParser<FieldDescriptorProto>(() => new FieldDescriptorProto());
private pb::UnknownFieldSet _unknownFields;
private int _hasBits0;
@ -2298,7 +2299,7 @@ namespace Google.Protobuf.Reflection {
/// <summary>Container for nested types declared in the FieldDescriptorProto message type.</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static partial class Types {
internal enum Type {
public enum Type {
/// <summary>
/// 0 is reserved for errors.
/// Order is weird for historical reasons.
@ -2349,7 +2350,7 @@ namespace Google.Protobuf.Reflection {
[pbr::OriginalName("TYPE_SINT64")] Sint64 = 18,
}
internal enum Label {
public enum Label {
/// <summary>
/// 0 is reserved for errors
/// </summary>
@ -2366,7 +2367,7 @@ namespace Google.Protobuf.Reflection {
/// <summary>
/// Describes a oneof.
/// </summary>
internal sealed partial class OneofDescriptorProto : pb::IMessage<OneofDescriptorProto> {
public sealed partial class OneofDescriptorProto : pb::IMessage<OneofDescriptorProto> {
private static readonly pb::MessageParser<OneofDescriptorProto> _parser = new pb::MessageParser<OneofDescriptorProto>(() => new OneofDescriptorProto());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -2554,7 +2555,7 @@ namespace Google.Protobuf.Reflection {
/// <summary>
/// Describes an enum type.
/// </summary>
internal sealed partial class EnumDescriptorProto : pb::IMessage<EnumDescriptorProto> {
public sealed partial class EnumDescriptorProto : pb::IMessage<EnumDescriptorProto> {
private static readonly pb::MessageParser<EnumDescriptorProto> _parser = new pb::MessageParser<EnumDescriptorProto>(() => new EnumDescriptorProto());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -2818,7 +2819,7 @@ namespace Google.Protobuf.Reflection {
/// is inclusive such that it can appropriately represent the entire int32
/// domain.
/// </summary>
internal sealed partial class EnumReservedRange : pb::IMessage<EnumReservedRange> {
public sealed partial class EnumReservedRange : pb::IMessage<EnumReservedRange> {
private static readonly pb::MessageParser<EnumReservedRange> _parser = new pb::MessageParser<EnumReservedRange>(() => new EnumReservedRange());
private pb::UnknownFieldSet _unknownFields;
private int _hasBits0;
@ -3017,7 +3018,7 @@ namespace Google.Protobuf.Reflection {
/// <summary>
/// Describes a value within an enum.
/// </summary>
internal sealed partial class EnumValueDescriptorProto : pb::IMessage<EnumValueDescriptorProto> {
public sealed partial class EnumValueDescriptorProto : pb::IMessage<EnumValueDescriptorProto> {
private static readonly pb::MessageParser<EnumValueDescriptorProto> _parser = new pb::MessageParser<EnumValueDescriptorProto>(() => new EnumValueDescriptorProto());
private pb::UnknownFieldSet _unknownFields;
private int _hasBits0;
@ -3248,7 +3249,7 @@ namespace Google.Protobuf.Reflection {
/// <summary>
/// Describes a service.
/// </summary>
internal sealed partial class ServiceDescriptorProto : pb::IMessage<ServiceDescriptorProto> {
public sealed partial class ServiceDescriptorProto : pb::IMessage<ServiceDescriptorProto> {
private static readonly pb::MessageParser<ServiceDescriptorProto> _parser = new pb::MessageParser<ServiceDescriptorProto>(() => new ServiceDescriptorProto());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -3456,7 +3457,7 @@ namespace Google.Protobuf.Reflection {
/// <summary>
/// Describes a method of a service.
/// </summary>
internal sealed partial class MethodDescriptorProto : pb::IMessage<MethodDescriptorProto> {
public sealed partial class MethodDescriptorProto : pb::IMessage<MethodDescriptorProto> {
private static readonly pb::MessageParser<MethodDescriptorProto> _parser = new pb::MessageParser<MethodDescriptorProto>(() => new MethodDescriptorProto());
private pb::UnknownFieldSet _unknownFields;
private int _hasBits0;
@ -3815,10 +3816,11 @@ namespace Google.Protobuf.Reflection {
}
internal sealed partial class FileOptions : pb::IExtendableMessage<FileOptions> {
public sealed partial class FileOptions : pb::IExtendableMessage<FileOptions> {
private static readonly pb::MessageParser<FileOptions> _parser = new pb::MessageParser<FileOptions>(() => new FileOptions());
private pb::UnknownFieldSet _unknownFields;
internal pb::ExtensionSet<FileOptions> _extensions;
private pb::ExtensionSet<FileOptions> _Extensions => _extensions;
private int _hasBits0;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<FileOptions> Parser { get { return _parser; } }
@ -4869,8 +4871,8 @@ namespace Google.Protobuf.Reflection {
public pbc::RepeatedField<TValue> GetExtension<TValue>(pb::RepeatedExtension<FileOptions, TValue> extension) {
return pb::ExtensionSet.Get(ref _extensions, extension);
}
public pbc::RepeatedField<TValue> GetOrRegisterExtension<TValue>(pb::RepeatedExtension<FileOptions, TValue> extension) {
return pb::ExtensionSet.GetOrRegister(ref _extensions, extension);
public pbc::RepeatedField<TValue> GetOrInitializeExtension<TValue>(pb::RepeatedExtension<FileOptions, TValue> extension) {
return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension);
}
public void SetExtension<TValue>(pb::Extension<FileOptions, TValue> extension, TValue value) {
pb::ExtensionSet.Set(ref _extensions, extension, value);
@ -4892,7 +4894,7 @@ namespace Google.Protobuf.Reflection {
/// <summary>
/// Generated classes can be optimized for speed or code size.
/// </summary>
internal enum OptimizeMode {
public enum OptimizeMode {
/// <summary>
/// Generate complete code for parsing, serialization,
/// </summary>
@ -4912,10 +4914,11 @@ namespace Google.Protobuf.Reflection {
}
internal sealed partial class MessageOptions : pb::IExtendableMessage<MessageOptions> {
public sealed partial class MessageOptions : pb::IExtendableMessage<MessageOptions> {
private static readonly pb::MessageParser<MessageOptions> _parser = new pb::MessageParser<MessageOptions>(() => new MessageOptions());
private pb::UnknownFieldSet _unknownFields;
internal pb::ExtensionSet<MessageOptions> _extensions;
private pb::ExtensionSet<MessageOptions> _Extensions => _extensions;
private int _hasBits0;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<MessageOptions> Parser { get { return _parser; } }
@ -5277,8 +5280,8 @@ namespace Google.Protobuf.Reflection {
public pbc::RepeatedField<TValue> GetExtension<TValue>(pb::RepeatedExtension<MessageOptions, TValue> extension) {
return pb::ExtensionSet.Get(ref _extensions, extension);
}
public pbc::RepeatedField<TValue> GetOrRegisterExtension<TValue>(pb::RepeatedExtension<MessageOptions, TValue> extension) {
return pb::ExtensionSet.GetOrRegister(ref _extensions, extension);
public pbc::RepeatedField<TValue> GetOrInitializeExtension<TValue>(pb::RepeatedExtension<MessageOptions, TValue> extension) {
return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension);
}
public void SetExtension<TValue>(pb::Extension<MessageOptions, TValue> extension, TValue value) {
pb::ExtensionSet.Set(ref _extensions, extension, value);
@ -5295,10 +5298,11 @@ namespace Google.Protobuf.Reflection {
}
internal sealed partial class FieldOptions : pb::IExtendableMessage<FieldOptions> {
public sealed partial class FieldOptions : pb::IExtendableMessage<FieldOptions> {
private static readonly pb::MessageParser<FieldOptions> _parser = new pb::MessageParser<FieldOptions>(() => new FieldOptions());
private pb::UnknownFieldSet _unknownFields;
internal pb::ExtensionSet<FieldOptions> _extensions;
private pb::ExtensionSet<FieldOptions> _Extensions => _extensions;
private int _hasBits0;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<FieldOptions> Parser { get { return _parser; } }
@ -5752,8 +5756,8 @@ namespace Google.Protobuf.Reflection {
public pbc::RepeatedField<TValue> GetExtension<TValue>(pb::RepeatedExtension<FieldOptions, TValue> extension) {
return pb::ExtensionSet.Get(ref _extensions, extension);
}
public pbc::RepeatedField<TValue> GetOrRegisterExtension<TValue>(pb::RepeatedExtension<FieldOptions, TValue> extension) {
return pb::ExtensionSet.GetOrRegister(ref _extensions, extension);
public pbc::RepeatedField<TValue> GetOrInitializeExtension<TValue>(pb::RepeatedExtension<FieldOptions, TValue> extension) {
return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension);
}
public void SetExtension<TValue>(pb::Extension<FieldOptions, TValue> extension, TValue value) {
pb::ExtensionSet.Set(ref _extensions, extension, value);
@ -5772,7 +5776,7 @@ namespace Google.Protobuf.Reflection {
/// <summary>Container for nested types declared in the FieldOptions message type.</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static partial class Types {
internal enum CType {
public enum CType {
/// <summary>
/// Default mode.
/// </summary>
@ -5781,7 +5785,7 @@ namespace Google.Protobuf.Reflection {
[pbr::OriginalName("STRING_PIECE")] StringPiece = 2,
}
internal enum JSType {
public enum JSType {
/// <summary>
/// Use the default type.
/// </summary>
@ -5801,10 +5805,11 @@ namespace Google.Protobuf.Reflection {
}
internal sealed partial class OneofOptions : pb::IExtendableMessage<OneofOptions> {
public sealed partial class OneofOptions : pb::IExtendableMessage<OneofOptions> {
private static readonly pb::MessageParser<OneofOptions> _parser = new pb::MessageParser<OneofOptions>(() => new OneofOptions());
private pb::UnknownFieldSet _unknownFields;
internal pb::ExtensionSet<OneofOptions> _extensions;
private pb::ExtensionSet<OneofOptions> _Extensions => _extensions;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<OneofOptions> Parser { get { return _parser; } }
@ -5946,8 +5951,8 @@ namespace Google.Protobuf.Reflection {
public pbc::RepeatedField<TValue> GetExtension<TValue>(pb::RepeatedExtension<OneofOptions, TValue> extension) {
return pb::ExtensionSet.Get(ref _extensions, extension);
}
public pbc::RepeatedField<TValue> GetOrRegisterExtension<TValue>(pb::RepeatedExtension<OneofOptions, TValue> extension) {
return pb::ExtensionSet.GetOrRegister(ref _extensions, extension);
public pbc::RepeatedField<TValue> GetOrInitializeExtension<TValue>(pb::RepeatedExtension<OneofOptions, TValue> extension) {
return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension);
}
public void SetExtension<TValue>(pb::Extension<OneofOptions, TValue> extension, TValue value) {
pb::ExtensionSet.Set(ref _extensions, extension, value);
@ -5964,10 +5969,11 @@ namespace Google.Protobuf.Reflection {
}
internal sealed partial class EnumOptions : pb::IExtendableMessage<EnumOptions> {
public sealed partial class EnumOptions : pb::IExtendableMessage<EnumOptions> {
private static readonly pb::MessageParser<EnumOptions> _parser = new pb::MessageParser<EnumOptions>(() => new EnumOptions());
private pb::UnknownFieldSet _unknownFields;
internal pb::ExtensionSet<EnumOptions> _extensions;
private pb::ExtensionSet<EnumOptions> _Extensions => _extensions;
private int _hasBits0;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<EnumOptions> Parser { get { return _parser; } }
@ -6203,8 +6209,8 @@ namespace Google.Protobuf.Reflection {
public pbc::RepeatedField<TValue> GetExtension<TValue>(pb::RepeatedExtension<EnumOptions, TValue> extension) {
return pb::ExtensionSet.Get(ref _extensions, extension);
}
public pbc::RepeatedField<TValue> GetOrRegisterExtension<TValue>(pb::RepeatedExtension<EnumOptions, TValue> extension) {
return pb::ExtensionSet.GetOrRegister(ref _extensions, extension);
public pbc::RepeatedField<TValue> GetOrInitializeExtension<TValue>(pb::RepeatedExtension<EnumOptions, TValue> extension) {
return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension);
}
public void SetExtension<TValue>(pb::Extension<EnumOptions, TValue> extension, TValue value) {
pb::ExtensionSet.Set(ref _extensions, extension, value);
@ -6221,10 +6227,11 @@ namespace Google.Protobuf.Reflection {
}
internal sealed partial class EnumValueOptions : pb::IExtendableMessage<EnumValueOptions> {
public sealed partial class EnumValueOptions : pb::IExtendableMessage<EnumValueOptions> {
private static readonly pb::MessageParser<EnumValueOptions> _parser = new pb::MessageParser<EnumValueOptions>(() => new EnumValueOptions());
private pb::UnknownFieldSet _unknownFields;
internal pb::ExtensionSet<EnumValueOptions> _extensions;
private pb::ExtensionSet<EnumValueOptions> _Extensions => _extensions;
private int _hasBits0;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<EnumValueOptions> Parser { get { return _parser; } }
@ -6415,8 +6422,8 @@ namespace Google.Protobuf.Reflection {
public pbc::RepeatedField<TValue> GetExtension<TValue>(pb::RepeatedExtension<EnumValueOptions, TValue> extension) {
return pb::ExtensionSet.Get(ref _extensions, extension);
}
public pbc::RepeatedField<TValue> GetOrRegisterExtension<TValue>(pb::RepeatedExtension<EnumValueOptions, TValue> extension) {
return pb::ExtensionSet.GetOrRegister(ref _extensions, extension);
public pbc::RepeatedField<TValue> GetOrInitializeExtension<TValue>(pb::RepeatedExtension<EnumValueOptions, TValue> extension) {
return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension);
}
public void SetExtension<TValue>(pb::Extension<EnumValueOptions, TValue> extension, TValue value) {
pb::ExtensionSet.Set(ref _extensions, extension, value);
@ -6433,10 +6440,11 @@ namespace Google.Protobuf.Reflection {
}
internal sealed partial class ServiceOptions : pb::IExtendableMessage<ServiceOptions> {
public sealed partial class ServiceOptions : pb::IExtendableMessage<ServiceOptions> {
private static readonly pb::MessageParser<ServiceOptions> _parser = new pb::MessageParser<ServiceOptions>(() => new ServiceOptions());
private pb::UnknownFieldSet _unknownFields;
internal pb::ExtensionSet<ServiceOptions> _extensions;
private pb::ExtensionSet<ServiceOptions> _Extensions => _extensions;
private int _hasBits0;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<ServiceOptions> Parser { get { return _parser; } }
@ -6627,8 +6635,8 @@ namespace Google.Protobuf.Reflection {
public pbc::RepeatedField<TValue> GetExtension<TValue>(pb::RepeatedExtension<ServiceOptions, TValue> extension) {
return pb::ExtensionSet.Get(ref _extensions, extension);
}
public pbc::RepeatedField<TValue> GetOrRegisterExtension<TValue>(pb::RepeatedExtension<ServiceOptions, TValue> extension) {
return pb::ExtensionSet.GetOrRegister(ref _extensions, extension);
public pbc::RepeatedField<TValue> GetOrInitializeExtension<TValue>(pb::RepeatedExtension<ServiceOptions, TValue> extension) {
return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension);
}
public void SetExtension<TValue>(pb::Extension<ServiceOptions, TValue> extension, TValue value) {
pb::ExtensionSet.Set(ref _extensions, extension, value);
@ -6645,10 +6653,11 @@ namespace Google.Protobuf.Reflection {
}
internal sealed partial class MethodOptions : pb::IExtendableMessage<MethodOptions> {
public sealed partial class MethodOptions : pb::IExtendableMessage<MethodOptions> {
private static readonly pb::MessageParser<MethodOptions> _parser = new pb::MessageParser<MethodOptions>(() => new MethodOptions());
private pb::UnknownFieldSet _unknownFields;
internal pb::ExtensionSet<MethodOptions> _extensions;
private pb::ExtensionSet<MethodOptions> _Extensions => _extensions;
private int _hasBits0;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<MethodOptions> Parser { get { return _parser; } }
@ -6880,8 +6889,8 @@ namespace Google.Protobuf.Reflection {
public pbc::RepeatedField<TValue> GetExtension<TValue>(pb::RepeatedExtension<MethodOptions, TValue> extension) {
return pb::ExtensionSet.Get(ref _extensions, extension);
}
public pbc::RepeatedField<TValue> GetOrRegisterExtension<TValue>(pb::RepeatedExtension<MethodOptions, TValue> extension) {
return pb::ExtensionSet.GetOrRegister(ref _extensions, extension);
public pbc::RepeatedField<TValue> GetOrInitializeExtension<TValue>(pb::RepeatedExtension<MethodOptions, TValue> extension) {
return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension);
}
public void SetExtension<TValue>(pb::Extension<MethodOptions, TValue> extension, TValue value) {
pb::ExtensionSet.Set(ref _extensions, extension, value);
@ -6905,7 +6914,7 @@ namespace Google.Protobuf.Reflection {
/// or neither? HTTP based RPC implementation may choose GET verb for safe
/// methods, and PUT verb for idempotent methods instead of the default POST.
/// </summary>
internal enum IdempotencyLevel {
public enum IdempotencyLevel {
[pbr::OriginalName("IDEMPOTENCY_UNKNOWN")] IdempotencyUnknown = 0,
/// <summary>
/// implies idempotent
@ -6930,7 +6939,7 @@ namespace Google.Protobuf.Reflection {
/// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
/// in them.
/// </summary>
internal sealed partial class UninterpretedOption : pb::IMessage<UninterpretedOption> {
public sealed partial class UninterpretedOption : pb::IMessage<UninterpretedOption> {
private static readonly pb::MessageParser<UninterpretedOption> _parser = new pb::MessageParser<UninterpretedOption>(() => new UninterpretedOption());
private pb::UnknownFieldSet _unknownFields;
private int _hasBits0;
@ -7309,7 +7318,7 @@ namespace Google.Protobuf.Reflection {
/// E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
/// "foo.(bar.baz).qux".
/// </summary>
internal sealed partial class NamePart : pb::IMessage<NamePart> {
public sealed partial class NamePart : pb::IMessage<NamePart> {
private static readonly pb::MessageParser<NamePart> _parser = new pb::MessageParser<NamePart>(() => new NamePart());
private pb::UnknownFieldSet _unknownFields;
private int _hasBits0;
@ -7502,7 +7511,7 @@ namespace Google.Protobuf.Reflection {
/// Encapsulates information about the original source file from which a
/// FileDescriptorProto was generated.
/// </summary>
internal sealed partial class SourceCodeInfo : pb::IMessage<SourceCodeInfo> {
public sealed partial class SourceCodeInfo : pb::IMessage<SourceCodeInfo> {
private static readonly pb::MessageParser<SourceCodeInfo> _parser = new pb::MessageParser<SourceCodeInfo>(() => new SourceCodeInfo());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -7670,7 +7679,7 @@ namespace Google.Protobuf.Reflection {
/// <summary>Container for nested types declared in the SourceCodeInfo message type.</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static partial class Types {
internal sealed partial class Location : pb::IMessage<Location> {
public sealed partial class Location : pb::IMessage<Location> {
private static readonly pb::MessageParser<Location> _parser = new pb::MessageParser<Location>(() => new Location());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -8004,7 +8013,7 @@ namespace Google.Protobuf.Reflection {
/// file. A GeneratedCodeInfo message is associated with only one generated
/// source file, but may contain references to different source .proto files.
/// </summary>
internal sealed partial class GeneratedCodeInfo : pb::IMessage<GeneratedCodeInfo> {
public sealed partial class GeneratedCodeInfo : pb::IMessage<GeneratedCodeInfo> {
private static readonly pb::MessageParser<GeneratedCodeInfo> _parser = new pb::MessageParser<GeneratedCodeInfo>(() => new GeneratedCodeInfo());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -8131,7 +8140,7 @@ namespace Google.Protobuf.Reflection {
/// <summary>Container for nested types declared in the GeneratedCodeInfo message type.</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static partial class Types {
internal sealed partial class Annotation : pb::IMessage<Annotation> {
public sealed partial class Annotation : pb::IMessage<Annotation> {
private static readonly pb::MessageParser<Annotation> _parser = new pb::MessageParser<Annotation>(() => new Annotation());
private pb::UnknownFieldSet _unknownFields;
private int _hasBits0;

View File

@ -128,17 +128,16 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// The (possibly empty) set of custom options for this enum.
/// </summary>
//[Obsolete("CustomOptions are obsolete. Use GetOption")]
[Obsolete("CustomOptions are obsolete. Use GetOption")]
public CustomOptions CustomOptions => new CustomOptions(Proto.Options._extensions?.ValuesByNumber);
/* // uncomment this in the full proto2 support PR
/// <summary>
/// Gets a single value enum option for this descriptor
/// </summary>
public T GetOption<T>(Extension<EnumOptions, T> extension)
{
var value = Proto.Options.GetExtension(extension);
return value is IDeepCloneable<T> clonable ? clonable.Clone() : value;
return value is IDeepCloneable<T> ? (value as IDeepCloneable<T>).Clone() : value;
}
/// <summary>
@ -148,6 +147,5 @@ namespace Google.Protobuf.Reflection
{
return Proto.Options.GetExtension(extension).Clone();
}
*/
}
}

View File

@ -73,17 +73,16 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// The (possibly empty) set of custom options for this enum value.
/// </summary>
//[Obsolete("CustomOptions are obsolete. Use GetOption")]
[Obsolete("CustomOptions are obsolete. Use GetOption")]
public CustomOptions CustomOptions => new CustomOptions(Proto.Options._extensions?.ValuesByNumber);
/* // uncomment this in the full proto2 support PR
/// <summary>
/// Gets a single value enum option for this descriptor
/// </summary>
public T GetOption<T>(Extension<EnumValueOptions, T> extension)
{
var value = Proto.Options.GetExtension(extension);
return value is IDeepCloneable<T> clonable ? clonable.Clone() : value;
return value is IDeepCloneable<T> ? (value as IDeepCloneable<T>).Clone() : value;
}
/// <summary>
@ -93,7 +92,6 @@ namespace Google.Protobuf.Reflection
{
return Proto.Options.GetExtension(extension).Clone();
}
*/
}
}

View File

@ -39,7 +39,7 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// A collection to simplify retrieving the descriptors of extensions in a descriptor for a message
/// </summary>
public class ExtensionCollection
public sealed class ExtensionCollection
{
private IDictionary<MessageDescriptor, IList<FieldDescriptor>> extensionsByTypeInDeclarationOrder;
private IDictionary<MessageDescriptor, IList<FieldDescriptor>> extensionsByTypeInNumberOrder;

View File

@ -66,7 +66,10 @@ namespace Google.Protobuf.Reflection
internal FieldDescriptorProto Proto { get; }
internal Extension Extension { get; }
/// <summary>
/// An extension identifier for this field, or <c>null</c> if this field isn't an extension.
/// </summary>
public Extension Extension { get; }
internal FieldDescriptor(FieldDescriptorProto proto, FileDescriptor file,
MessageDescriptor parent, int index, string propertyName, Extension extension)
@ -201,7 +204,25 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// Returns <c>true</c> if this field is a packed, repeated field; <c>false</c> otherwise.
/// </summary>
public bool IsPacked => File.Proto.Syntax == "proto2" ? Proto.Options?.Packed ?? false : !Proto.Options.HasPacked || Proto.Options.Packed;
public bool IsPacked
{
get
{
if (File.Syntax != Syntax.Proto3)
{
return Proto.Options?.Packed ?? false;
}
else
{
return !Proto.Options.HasPacked || Proto.Options.Packed;
}
}
}
/// <summary>
/// Returns <c>true</c> if this field extends another message type; <c>false</c> otherwise.
/// </summary>
public bool IsExtension => Proto.HasExtendee;
/// <summary>
/// Returns the type of the field.
@ -277,17 +298,16 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// The (possibly empty) set of custom options for this field.
/// </summary>
//[Obsolete("CustomOptions are obsolete. Use GetOption")]
[Obsolete("CustomOptions are obsolete. Use GetOption")]
public CustomOptions CustomOptions => new CustomOptions(Proto.Options._extensions?.ValuesByNumber);
/* // uncomment this in the full proto2 support PR
/// <summary>
/// Gets a single value enum option for this descriptor
/// </summary>
public T GetOption<T>(Extension<FieldOptions, T> extension)
{
var value = Proto.Options.GetExtension(extension);
return value is IDeepCloneable<T> clonable ? clonable.Clone() : value;
return value is IDeepCloneable<T> ? (value as IDeepCloneable<T>).Clone() : value;
}
/// <summary>
@ -297,7 +317,6 @@ namespace Google.Protobuf.Reflection
{
return Proto.Options.GetExtension(extension).Clone();
}
*/
/// <summary>
/// Look up and cross-link all field types etc.
@ -378,6 +397,11 @@ namespace Google.Protobuf.Reflection
private IFieldAccessor CreateAccessor()
{
if (Extension != null)
{
return new ExtensionAccessor(this);
}
// If we're given no property name, that's because we really don't want an accessor.
// This could be because it's a map message, or it could be that we're loading a FileDescriptor dynamically.
// TODO: Support dynamic messages.
@ -386,10 +410,6 @@ namespace Google.Protobuf.Reflection
return null;
}
if (Extension != null)
{
return new ExtensionAccessor(this);
}
var property = ContainingType.ClrType.GetProperty(propertyName);
if (property == null)
{

View File

@ -42,6 +42,25 @@ using static Google.Protobuf.Reflection.SourceCodeInfo.Types;
namespace Google.Protobuf.Reflection
{
/// <summary>
/// The syntax of a .proto file
/// </summary>
public enum Syntax
{
/// <summary>
/// Proto2 syntax
/// </summary>
Proto2,
/// <summary>
/// Proto3 syntax
/// </summary>
Proto3,
/// <summary>
/// An unknown declared syntax
/// </summary>
Unknown
}
/// <summary>
/// Describes a .proto file, including everything defined within.
/// IDescriptor is implemented such that the File property returns this descriptor,
@ -87,6 +106,19 @@ namespace Google.Protobuf.Reflection
Extensions = new ExtensionCollection(this, generatedCodeInfo?.Extensions);
declarations = new Lazy<Dictionary<IDescriptor, DescriptorDeclaration>>(CreateDeclarationMap, LazyThreadSafetyMode.ExecutionAndPublication);
if (!proto.HasSyntax || proto.Syntax == "proto2")
{
Syntax = Syntax.Proto2;
}
else if (proto.Syntax == "proto3")
{
Syntax = Syntax.Proto3;
}
else
{
Syntax = Syntax.Unknown;
}
}
private Dictionary<IDescriptor, DescriptorDeclaration> CreateDeclarationMap()
@ -217,6 +249,11 @@ namespace Google.Protobuf.Reflection
/// </value>
internal FileDescriptorProto Proto { get; }
/// <summary>
/// The syntax of the file
/// </summary>
public Syntax Syntax { get; }
/// <value>
/// The file name.
/// </value>
@ -504,17 +541,16 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// The (possibly empty) set of custom options for this file.
/// </summary>
//[Obsolete("CustomOptions are obsolete. Use GetOption")]
[Obsolete("CustomOptions are obsolete. Use GetOption")]
public CustomOptions CustomOptions => new CustomOptions(Proto.Options._extensions?.ValuesByNumber);
/* // uncomment this in the full proto2 support PR
/// <summary>
/// Gets a single value enum option for this descriptor
/// </summary>
public T GetOption<T>(Extension<FileOptions, T> extension)
{
var value = Proto.Options.GetExtension(extension);
return value is IDeepCloneable<T> clonable ? clonable.Clone() : value;
return value is IDeepCloneable<T> ? (value as IDeepCloneable<T>).Clone() : value;
}
/// <summary>
@ -524,7 +560,6 @@ namespace Google.Protobuf.Reflection
{
return Proto.Options.GetExtension(extension).Clone();
}
*/
/// <summary>
/// Performs initialization for the given generic type argument.

View File

@ -51,11 +51,6 @@ namespace Google.Protobuf.Reflection
/// </summary>
void Clear(IMessage message);
/// <summary>
/// Indicates whether the field in the specified message is set. For proto3 fields, this throws an <see cref="InvalidOperationException"/>
/// </summary>
bool HasValue(IMessage message);
/// <summary>
/// Fetches the field value. For repeated values, this will be an
/// <see cref="IList"/> implementation. For map values, this will be an
@ -63,6 +58,11 @@ namespace Google.Protobuf.Reflection
/// </summary>
object GetValue(IMessage message);
/// <summary>
/// Indicates whether the field in the specified message is set. For proto3 fields, this throws an <see cref="InvalidOperationException"/>
/// </summary>
bool HasValue(IMessage message);
/// <summary>
/// Mutator for single "simple" fields only.
/// </summary>

View File

@ -34,6 +34,7 @@ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
#if NET35
// Needed for ReadOnlyDictionary, which does not exist in .NET 3.5
using Google.Protobuf.Collections;
@ -63,6 +64,7 @@ namespace Google.Protobuf.Reflection
private readonly IList<FieldDescriptor> fieldsInDeclarationOrder;
private readonly IList<FieldDescriptor> fieldsInNumberOrder;
private readonly IDictionary<string, FieldDescriptor> jsonFieldMap;
private Func<IMessage, bool> extensionSetIsInitialized;
internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex, GeneratedClrTypeInfo generatedCodeInfo)
: base(file, file.ComputeFullName(parent, proto.Name), typeIndex)
@ -134,6 +136,21 @@ namespace Google.Protobuf.Reflection
internal DescriptorProto Proto { get; }
internal bool IsExtensionsInitialized(IMessage message)
{
if (Proto.ExtensionRange.Count == 0)
{
return true;
}
if (extensionSetIsInitialized == null)
{
extensionSetIsInitialized = ReflectionUtil.CreateIsInitializedCaller(ClrType);
}
return extensionSetIsInitialized(message);
}
/// <summary>
/// The CLR type used to represent message instances from this descriptor.
/// </summary>
@ -243,17 +260,16 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// The (possibly empty) set of custom options for this message.
/// </summary>
//[Obsolete("CustomOptions are obsolete. Use GetOption")]
[Obsolete("CustomOptions are obsolete. Use GetOption")]
public CustomOptions CustomOptions => new CustomOptions(Proto.Options._extensions?.ValuesByNumber);
/* // uncomment this in the full proto2 support PR
/// <summary>
/// Gets a single value enum option for this descriptor
/// </summary>
public T GetOption<T>(Extension<MessageOptions, T> extension)
{
var value = Proto.Options.GetExtension(extension);
return value is IDeepCloneable<T> clonable ? clonable.Clone() : value;
return value is IDeepCloneable<T> ? (value as IDeepCloneable<T>).Clone() : value;
}
/// <summary>
@ -263,7 +279,6 @@ namespace Google.Protobuf.Reflection
{
return Proto.Options.GetExtension(extension).Clone();
}
*/
/// <summary>
/// Looks up and cross-links all fields and nested types.

View File

@ -73,17 +73,16 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// The (possibly empty) set of custom options for this method.
/// </summary>
//[Obsolete("CustomOptions are obsolete. Use GetOption")]
[Obsolete("CustomOptions are obsolete. Use GetOption")]
public CustomOptions CustomOptions => new CustomOptions(Proto.Options._extensions?.ValuesByNumber);
/* // uncomment this in the full proto2 support PR
/// <summary>
/// Gets a single value enum option for this descriptor
/// </summary>
public T GetOption<T>(Extension<MethodOptions, T> extension)
{
var value = Proto.Options.GetExtension(extension);
return value is IDeepCloneable<T> clonable ? clonable.Clone() : value;
return value is IDeepCloneable<T> ? (value as IDeepCloneable<T>).Clone() : value;
}
/// <summary>
@ -93,7 +92,6 @@ namespace Google.Protobuf.Reflection
{
return Proto.Options.GetExtension(extension).Clone();
}
*/
internal MethodDescriptor(MethodDescriptorProto proto, FileDescriptor file,
ServiceDescriptor parent, int index)

View File

@ -105,17 +105,16 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// The (possibly empty) set of custom options for this oneof.
/// </summary>
//[Obsolete("CustomOptions are obsolete. Use GetOption")]
[Obsolete("CustomOptions are obsolete. Use GetOption")]
public CustomOptions CustomOptions => new CustomOptions(proto.Options._extensions?.ValuesByNumber);
/* // uncomment this in the full proto2 support PR
/// <summary>
/// Gets a single value enum option for this descriptor
/// </summary>
public T GetOption<T>(Extension<OneofOptions, T> extension)
{
var value = proto.Options.GetExtension(extension);
return value is IDeepCloneable<T> clonable ? clonable.Clone() : value;
return value is IDeepCloneable<T> ? (value as IDeepCloneable<T>).Clone() : value;
}
/// <summary>
@ -125,7 +124,6 @@ namespace Google.Protobuf.Reflection
{
return proto.Options.GetExtension(extension).Clone();
}
*/
internal void CrossLink()
{

View File

@ -115,12 +115,15 @@ namespace Google.Protobuf.Reflection
internal static Func<IMessage, bool> CreateFuncIMessageBool(MethodInfo method) =>
GetReflectionHelper(method.DeclaringType, method.ReturnType).CreateFuncIMessageBool(method);
internal static Func<IMessage, bool> CreateIsInitializedCaller(Type msg) =>
((IExtensionSetReflector)Activator.CreateInstance(typeof(ExtensionSetReflector<>).MakeGenericType(msg))).CreateIsInitializedCaller();
/// <summary>
/// Creates a delegate which will execute the given method after casting the first argument to
/// the type that declares the method, and the second argument to the first parameter type of the method.
/// </summary>
internal static IExtensionReflectionHelper CreateExtensionHelper(Extension extension) =>
(IExtensionReflectionHelper)Activator.CreateInstance(typeof(ExtensionReflectionHelper<,>).MakeGenericType(extension.TargetType, extension.GetType().GenericTypeArguments[1]));
(IExtensionReflectionHelper)Activator.CreateInstance(typeof(ExtensionReflectionHelper<,>).MakeGenericType(extension.TargetType, extension.GetType().GenericTypeArguments[1]), extension);
/// <summary>
/// Creates a reflection helper for the given type arguments. Currently these are created on demand
@ -150,6 +153,11 @@ namespace Google.Protobuf.Reflection
void ClearExtension(IMessage message);
}
private interface IExtensionSetReflector
{
Func<IMessage, bool> CreateIsInitializedCaller();
}
private class ReflectionHelper<T1, T2> : IReflectionHelper
{
@ -222,7 +230,7 @@ namespace Google.Protobuf.Reflection
}
else if (extension is RepeatedExtension<T1, T3>)
{
return extensionMessage.GetExtension(extension as RepeatedExtension<T1, T3>);
return extensionMessage.GetOrInitializeExtension(extension as RepeatedExtension<T1, T3>);
}
else
{
@ -300,6 +308,28 @@ namespace Google.Protobuf.Reflection
}
}
private class ExtensionSetReflector<T1> : IExtensionSetReflector where T1 : IExtendableMessage<T1>
{
public Func<IMessage, bool> CreateIsInitializedCaller()
{
var prop = typeof(T1).GetTypeInfo().GetDeclaredProperty("_Extensions");
#if NET35
var getFunc = (Func<T1, ExtensionSet<T1>>)prop.GetGetMethod(true).CreateDelegate(typeof(Func<T1, ExtensionSet<T1>>));
#else
var getFunc = (Func<T1, ExtensionSet<T1>>)prop.GetMethod.CreateDelegate(typeof(Func<T1, ExtensionSet<T1>>));
#endif
var initializedFunc = (Func<ExtensionSet<T1>, bool>)
typeof(ExtensionSet<T1>)
.GetTypeInfo()
.GetDeclaredMethod("IsInitialized")
.CreateDelegate(typeof(Func<ExtensionSet<T1>, bool>));
return (m) => {
var set = getFunc((T1)m);
return set == null || initializedFunc(set);
};
}
}
// Runtime compatibility checking code - see ReflectionHelper<T1, T2>.CreateFuncIMessageInt32 for
// details about why we're doing this.

View File

@ -94,17 +94,16 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// The (possibly empty) set of custom options for this service.
/// </summary>
//[Obsolete("CustomOptions are obsolete. Use GetOption")]
[Obsolete("CustomOptions are obsolete. Use GetOption")]
public CustomOptions CustomOptions => new CustomOptions(Proto.Options._extensions?.ValuesByNumber);
/* // uncomment this in the full proto2 support PR
/// <summary>
/// Gets a single value enum option for this descriptor
/// </summary>
public T GetOption<T>(Extension<ServiceOptions, T> extension)
{
var value = Proto.Options.GetExtension(extension);
return value is IDeepCloneable<T> clonable ? clonable.Clone() : value;
return value is IDeepCloneable<T> ? (value as IDeepCloneable<T>).Clone() : value;
}
/// <summary>
@ -114,7 +113,6 @@ namespace Google.Protobuf.Reflection
{
return Proto.Options.GetExtension(extension).Clone();
}
*/
internal void CrossLink()
{

View File

@ -57,20 +57,7 @@ namespace Google.Protobuf.Reflection
throw new ArgumentException("Not all required properties/methods available");
}
setValueDelegate = ReflectionUtil.CreateActionIMessageObject(property.GetSetMethod());
if (descriptor.File.Proto.Syntax == "proto2")
{
MethodInfo hasMethod = property.DeclaringType.GetRuntimeProperty("Has" + property.Name).GetMethod;
if (hasMethod == null) {
throw new ArgumentException("Not all required properties/methods are available");
}
hasDelegate = ReflectionUtil.CreateFuncIMessageBool(hasMethod);
MethodInfo clearMethod = property.DeclaringType.GetRuntimeMethod("Clear" + property.Name, ReflectionUtil.EmptyTypes);
if (clearMethod == null) {
throw new ArgumentException("Not all required properties/methods are available");
}
clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod);
}
else
if (descriptor.File.Syntax == Syntax.Proto3)
{
hasDelegate = message => {
throw new InvalidOperationException("HasValue is not implemented for proto3 fields");
@ -85,6 +72,19 @@ namespace Google.Protobuf.Reflection
: Activator.CreateInstance(clrType);
clearDelegate = message => SetValue(message, defaultValue);
}
else
{
MethodInfo hasMethod = property.DeclaringType.GetRuntimeProperty("Has" + property.Name).GetMethod;
if (hasMethod == null) {
throw new ArgumentException("Not all required properties/methods are available");
}
hasDelegate = ReflectionUtil.CreateFuncIMessageBool(hasMethod);
MethodInfo clearMethod = property.DeclaringType.GetRuntimeMethod("Clear" + property.Name, ReflectionUtil.EmptyTypes);
if (clearMethod == null) {
throw new ArgumentException("Not all required properties/methods are available");
}
clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod);
}
}
public override void Clear(IMessage message)

View File

@ -306,7 +306,7 @@ std::string FieldGeneratorBase::GetStringDefaultValueInternal(const FieldDescrip
if (descriptor->default_value_string().empty())
return "\"\"";
else
return "global::System.Encoding.UTF8.GetString(global::System.Convert.FromBase64String(\" +" + StringToBase64(descriptor->default_value_string()) + " +\"))";
return "global::System.Text.Encoding.UTF8.GetString(global::System.Convert.FromBase64String(\"" + StringToBase64(descriptor->default_value_string()) + "\"))";
}
std::string FieldGeneratorBase::GetBytesDefaultValueInternal(const FieldDescriptor* descriptor) {

View File

@ -63,12 +63,6 @@ bool Generator::Generate(
std::vector<std::pair<string, string> > options;
ParseGeneratorParameter(parameter, &options);
// We only support proto3 - but we make an exception for descriptor.proto.
if (file->syntax() != FileDescriptor::SYNTAX_PROTO3 && !IsDescriptorProto(file)) {
*error = "C# code generation only supports proto3 syntax";
return false;
}
struct Options cli_options;
for (int i = 0; i < options.size(); i++) {

View File

@ -284,16 +284,35 @@ std::string GetEnumValueName(const std::string& enum_name, const std::string& en
uint GetGroupEndTag(const Descriptor* descriptor) {
const Descriptor* containing_type = descriptor->containing_type();
if (containing_type == NULL) {
return 0;
if (containing_type != NULL) {
const FieldDescriptor* field;
for (int i = 0; i < containing_type->field_count(); i++) {
field = containing_type->field(i);
if (field->type() == FieldDescriptor::Type::TYPE_GROUP && field->message_type() == descriptor) {
return internal::WireFormatLite::MakeTag(field->number(), internal::WireFormatLite::WIRETYPE_END_GROUP);
}
}
for (int i = 0; i < containing_type->extension_count(); i++) {
field = containing_type->extension(i);
if (field->type() == FieldDescriptor::Type::TYPE_GROUP && field->message_type() == descriptor) {
return internal::WireFormatLite::MakeTag(field->number(), internal::WireFormatLite::WIRETYPE_END_GROUP);
}
}
const FieldDescriptor* field = containing_type->FindFieldByName(descriptor->name());
if (field != NULL && field->type() == FieldDescriptor::Type::TYPE_GROUP) {
return internal::WireFormatLite::MakeTag(field->number(), internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
} else {
return 0;
const FileDescriptor* containing_file = descriptor->file();
if (containing_file != NULL) {
const FieldDescriptor* field;
for (int i = 0; i < containing_file->extension_count(); i++) {
field = containing_file->extension(i);
if (field->type() == FieldDescriptor::Type::TYPE_GROUP && field->message_type() == descriptor) {
return internal::WireFormatLite::MakeTag(field->number(), internal::WireFormatLite::WIRETYPE_END_GROUP);
}
}
}
}
return 0;
}
std::string ToCSharpName(const std::string& name, const FileDescriptor* file) {
std::string result = GetFileNamespace(file);

View File

@ -149,6 +149,8 @@ void MessageGenerator::Generate(io::Printer* printer) {
} else {
printer->Print(vars, "private pb::ExtensionSet<$class_name$> _extensions;\n");
}
printer->Print(vars, "private pb::ExtensionSet<$class_name$> _Extensions => _extensions;\n"); // a read-only property for fast retrieval of the set in IsInitialized
}
for (int i = 0; i < has_bit_field_count_; i++) {
@ -270,8 +272,8 @@ void MessageGenerator::Generate(io::Printer* printer) {
"public pbc::RepeatedField<TValue> GetExtension<TValue>(pb::RepeatedExtension<$class_name$, TValue> extension) {\n"
" return pb::ExtensionSet.Get(ref _extensions, extension);\n"
"}\n"
"public pbc::RepeatedField<TValue> GetOrRegisterExtension<TValue>(pb::RepeatedExtension<$class_name$, TValue> extension) {\n"
" return pb::ExtensionSet.GetOrRegister(ref _extensions, extension);\n"
"public pbc::RepeatedField<TValue> GetOrInitializeExtension<TValue>(pb::RepeatedExtension<$class_name$, TValue> extension) {\n"
" return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension);\n"
"}\n"
"public void SetExtension<TValue>(pb::Extension<$class_name$, TValue> extension, TValue value) {\n"
" pb::ExtensionSet.Set(ref _extensions, extension, value);\n"
@ -320,7 +322,7 @@ void MessageGenerator::Generate(io::Printer* printer) {
"#region Extensions\n"
"/// <summary>Container for extensions for other messages declared in the $class_name$ message type.</summary>\n");
WriteGeneratedCodeAttributes(printer);
printer->Print("internal static partial class Extensions {\n");
printer->Print("public static partial class Extensions {\n");
printer->Indent();
for (int i = 0; i < descriptor_->extension_count(); i++) {
std::unique_ptr<FieldGeneratorBase> generator(
@ -625,7 +627,7 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
printer->Indent();
if (end_tag_ != 0) {
printer->Print(
"$end_tag$:\n"
"case $end_tag$:\n"
" return;\n",
"end_tag", StrCat(end_tag_));
}
@ -681,7 +683,7 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
// it's a waste of space to track presence for all values, so we only track them if they're not nullable
int MessageGenerator::GetPresenceIndex(const FieldDescriptor* descriptor) {
if (IsNullable(descriptor) || !IsProto2(descriptor_->file())) {
if (IsNullable(descriptor) || !IsProto2(descriptor->file()) || descriptor->is_extension()) {
return -1;
}

View File

@ -74,7 +74,7 @@ void ReflectionClassGenerator::Generate(io::Printer* printer) {
if (file_->extension_count() > 0) {
printer->Print(
"/// <summary>Holder for extension identifiers generated from the top level of $file_name$</summary>\n"
"internal static partial class $class_name$ {\n",
"$access_level$ static partial class $class_name$ {\n",
"access_level", class_access_level(),
"class_name", extensionClassname_,
"file_name", file_->name());

View File

@ -59,7 +59,7 @@ void SourceGeneratorBase::WriteGeneratedCodeAttributes(io::Printer* printer) {
}
std::string SourceGeneratorBase::class_access_level() {
return (IsDescriptorProto(descriptor_) || this->options()->internal_access) ? "internal" : "public";
return this->options()->internal_access ? "internal" : "public";
}
const Options* SourceGeneratorBase::options() {