aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Jie Luo <anandolee@gmail.com>2015-04-29 11:33:07 -0700
committerGravatar Jie Luo <anandolee@gmail.com>2015-04-29 11:33:07 -0700
commitc5c9c6a7e05a44724bc4bc6192ff995b4398d559 (patch)
treebb4eab9a4c4830b7e6d91f83b1309498a9e41578
parent8bae6c09bc8c8be808f0acc9b2ad4c9811493060 (diff)
field presence Reflection and tests
-rw-r--r--csharp/protos/google/protobuf/field_presence_test.proto24
-rw-r--r--csharp/src/ProtocolBuffers.Test/FieldPResenceTest.cs187
-rw-r--r--csharp/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj2
-rw-r--r--csharp/src/ProtocolBuffers.Test/TestProtos/FieldPresense.cs965
-rw-r--r--csharp/src/ProtocolBuffers/Descriptors/FileDescriptor.cs16
-rw-r--r--csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs13
-rw-r--r--csharp/src/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs2
-rw-r--r--csharp/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs2
-rw-r--r--csharp/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs24
9 files changed, 1225 insertions, 10 deletions
diff --git a/csharp/protos/google/protobuf/field_presence_test.proto b/csharp/protos/google/protobuf/field_presence_test.proto
new file mode 100644
index 00000000..43b4f04b
--- /dev/null
+++ b/csharp/protos/google/protobuf/field_presence_test.proto
@@ -0,0 +1,24 @@
+syntax = "proto3";
+
+package field_presence_test;
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "FieldPresenceTestProto";
+option java_generate_equals_and_hash = true;
+
+message TestAllTypes {
+ enum NestedEnum {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ }
+ message NestedMessage {
+ optional int32 value = 1;
+ }
+
+ optional int32 optional_int32 = 1;
+ optional string optional_string = 2;
+ optional bytes optional_bytes = 3;
+ optional NestedEnum optional_nested_enum = 4;
+ optional NestedMessage optional_nested_message = 5;
+}
diff --git a/csharp/src/ProtocolBuffers.Test/FieldPResenceTest.cs b/csharp/src/ProtocolBuffers.Test/FieldPResenceTest.cs
new file mode 100644
index 00000000..7e5abbf2
--- /dev/null
+++ b/csharp/src/ProtocolBuffers.Test/FieldPResenceTest.cs
@@ -0,0 +1,187 @@
+#region Copyright notice and license
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc. All rights reserved.
+// Author: jieluo@google.com (Jie Luo)
+//
+// 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
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#endregion
+
+using System;
+using System.Reflection;
+using System.Collections.Generic;
+using Google.ProtocolBuffers.Descriptors;
+using Google.ProtocolBuffers.TestProtos;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace Google.ProtocolBuffers
+{
+ [TestClass]
+ class FieldPresenceTest
+ {
+ private void CheckHasMethodRemoved(Type proto2Type, Type proto3Type, string name)
+ {
+ Assert.NotNull(proto2Type.GetProperty(name));
+ Assert.NotNull(proto2Type.GetProperty("Has" + name));
+ Assert.NotNull(proto3Type.GetProperty(name));
+ Assert.Null(proto3Type.GetProperty("Has" + name));
+ }
+
+ [TestMethod]
+ public void TestHasMethod()
+ {
+ // Optional non-message fields don't have HasFoo method generated
+ Type proto2Type = typeof(TestAllTypes);
+ Type proto3Type = typeof(field_presence_test.TestAllTypes);
+ CheckHasMethodRemoved(proto2Type, proto3Type, "OptionalInt32");
+ CheckHasMethodRemoved(proto2Type, proto3Type, "OptionalString");
+ CheckHasMethodRemoved(proto2Type, proto3Type, "OptionalBytes");
+ CheckHasMethodRemoved(proto2Type, proto3Type, "OptionalNestedEnum");
+
+ proto2Type = typeof(TestAllTypes.Builder);
+ proto3Type = typeof(field_presence_test.TestAllTypes.Builder);
+ CheckHasMethodRemoved(proto2Type, proto3Type, "OptionalInt32");
+ CheckHasMethodRemoved(proto2Type, proto3Type, "OptionalString");
+ CheckHasMethodRemoved(proto2Type, proto3Type, "OptionalBytes");
+ CheckHasMethodRemoved(proto2Type, proto3Type, "OptionalNestedEnum");
+
+ // message fields still have the HasFoo method generated
+ Assert.False(field_presence_test.TestAllTypes.CreateBuilder().Build().HasOptionalNestedMessage);
+ Assert.False(field_presence_test.TestAllTypes.CreateBuilder().HasOptionalNestedMessage);
+ }
+
+ [TestMethod]
+ public void TestFieldPresence()
+ {
+ // Optional non-message fields set to their default value are treated the same
+ // way as not set.
+
+ // Serialization will ignore such fields.
+ field_presence_test.TestAllTypes.Builder builder = field_presence_test.TestAllTypes.CreateBuilder();
+ builder.SetOptionalInt32(0);
+ builder.SetOptionalString("");
+ builder.SetOptionalBytes(ByteString.Empty);
+ builder.SetOptionalNestedEnum(field_presence_test.TestAllTypes.Types.NestedEnum.FOO);
+ field_presence_test.TestAllTypes message = builder.Build();
+ Assert.AreEqual(0, message.SerializedSize);
+
+ // Test merge
+ field_presence_test.TestAllTypes.Builder a = field_presence_test.TestAllTypes.CreateBuilder();
+ a.SetOptionalInt32(1);
+ a.SetOptionalString("x");
+ a.SetOptionalBytes(ByteString.CopyFromUtf8("y"));
+ a.SetOptionalNestedEnum(field_presence_test.TestAllTypes.Types.NestedEnum.BAR);
+ a.MergeFrom(message);
+ field_presence_test.TestAllTypes messageA = a.Build();
+ Assert.AreEqual(1, messageA.OptionalInt32);
+ Assert.AreEqual("x", messageA.OptionalString);
+ Assert.AreEqual(ByteString.CopyFromUtf8("y"), messageA.OptionalBytes);
+ Assert.AreEqual(field_presence_test.TestAllTypes.Types.NestedEnum.BAR, messageA.OptionalNestedEnum);
+
+ // equals/hashCode should produce the same results
+ field_presence_test.TestAllTypes empty = field_presence_test.TestAllTypes.CreateBuilder().Build();
+ Assert.True(empty.Equals(message));
+ Assert.True(message.Equals(empty));
+ Assert.AreEqual(empty.GetHashCode(), message.GetHashCode());
+ }
+
+ [TestMethod]
+ public void TestFieldPresenceReflection()
+ {
+ MessageDescriptor descriptor = field_presence_test.TestAllTypes.Descriptor;
+ FieldDescriptor optionalInt32Field = descriptor.FindFieldByName("optional_int32");
+ FieldDescriptor optionalStringField = descriptor.FindFieldByName("optional_string");
+ FieldDescriptor optionalBytesField = descriptor.FindFieldByName("optional_bytes");
+ FieldDescriptor optionalNestedEnumField = descriptor.FindFieldByName("optional_nested_enum");
+
+ field_presence_test.TestAllTypes message = field_presence_test.TestAllTypes.CreateBuilder().Build();
+ Assert.False(message.HasField(optionalInt32Field));
+ Assert.False(message.HasField(optionalStringField));
+ Assert.False(message.HasField(optionalBytesField));
+ Assert.False(message.HasField(optionalNestedEnumField));
+
+ // Set to default value is seen as not present
+ message = field_presence_test.TestAllTypes.CreateBuilder()
+ .SetOptionalInt32(0)
+ .SetOptionalString("")
+ .SetOptionalBytes(ByteString.Empty)
+ .SetOptionalNestedEnum(field_presence_test.TestAllTypes.Types.NestedEnum.FOO)
+ .Build();
+ Assert.False(message.HasField(optionalInt32Field));
+ Assert.False(message.HasField(optionalStringField));
+ Assert.False(message.HasField(optionalBytesField));
+ Assert.False(message.HasField(optionalNestedEnumField));
+ Assert.AreEqual(0, message.AllFields.Count);
+
+ // Set t0 non-defalut value is seen as present
+ message = field_presence_test.TestAllTypes.CreateBuilder()
+ .SetOptionalInt32(1)
+ .SetOptionalString("x")
+ .SetOptionalBytes(ByteString.CopyFromUtf8("y"))
+ .SetOptionalNestedEnum(field_presence_test.TestAllTypes.Types.NestedEnum.BAR)
+ .Build();
+ Assert.True(message.HasField(optionalInt32Field));
+ Assert.True(message.HasField(optionalStringField));
+ Assert.True(message.HasField(optionalBytesField));
+ Assert.True(message.HasField(optionalNestedEnumField));
+ Assert.AreEqual(4, message.AllFields.Count);
+ }
+
+ [TestMethod]
+ public void TestMessageField()
+ {
+ field_presence_test.TestAllTypes.Builder builder = field_presence_test.TestAllTypes.CreateBuilder();
+ Assert.False(builder.HasOptionalNestedMessage);
+ Assert.False(builder.Build().HasOptionalNestedMessage);
+
+ // Unlike non-message fields, if we set default value to message field, the field
+ // shoule be seem as present.
+ builder.SetOptionalNestedMessage(field_presence_test.TestAllTypes.Types.NestedMessage.DefaultInstance);
+ Assert.True(builder.HasOptionalNestedMessage);
+ Assert.True(builder.Build().HasOptionalNestedMessage);
+
+ }
+
+ [TestMethod]
+ public void TestSeralizeAndParese()
+ {
+ field_presence_test.TestAllTypes.Builder builder = field_presence_test.TestAllTypes.CreateBuilder();
+ builder.SetOptionalInt32(1234);
+ builder.SetOptionalString("hello");
+ builder.SetOptionalNestedMessage(field_presence_test.TestAllTypes.Types.NestedMessage.DefaultInstance);
+ ByteString data = builder.Build().ToByteString();
+
+ field_presence_test.TestAllTypes message = field_presence_test.TestAllTypes.ParseFrom(data);
+ Assert.AreEqual(1234, message.OptionalInt32);
+ Assert.AreEqual("hello", message.OptionalString);
+ Assert.AreEqual(ByteString.Empty, message.OptionalBytes);
+ Assert.AreEqual(field_presence_test.TestAllTypes.Types.NestedEnum.FOO, message.OptionalNestedEnum);
+ Assert.True(message.HasOptionalNestedMessage);
+ Assert.AreEqual(0, message.OptionalNestedMessage.Value);
+ }
+ }
+}
diff --git a/csharp/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj b/csharp/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
index b11b1ad8..8a9a8002 100644
--- a/csharp/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
+++ b/csharp/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
@@ -71,6 +71,7 @@
</Compile>
<Compile Include="AbstractMessageTest.cs" />
<Compile Include="ByteStringTest.cs" />
+ <Compile Include="FieldPresenceTest.cs" />
<Compile Include="CodedInputStreamTest.cs" />
<Compile Include="CodedOutputStreamTest.cs" />
<Compile Include="Collections\PopsicleListTest.cs" />
@@ -82,6 +83,7 @@
<Compile Include="Compatibility\TextCompatibilityTests.cs" />
<Compile Include="Compatibility\XmlCompatibilityTests.cs" />
<Compile Include="SerializableAttribute.cs" />
+ <Compile Include="TestProtos\FieldPresense.cs" />
<Compile Include="TestProtos\GoogleSize.cs" />
<Compile Include="TestProtos\GoogleSpeed.cs" />
<Compile Include="TestProtos\Unittest.cs" />
diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/FieldPresense.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/FieldPresense.cs
new file mode 100644
index 00000000..64f447f1
--- /dev/null
+++ b/csharp/src/ProtocolBuffers.Test/TestProtos/FieldPresense.cs
@@ -0,0 +1,965 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: protos/google/protobuf/field_presence_test.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.ProtocolBuffers;
+using pbc = global::Google.ProtocolBuffers.Collections;
+using pbd = global::Google.ProtocolBuffers.Descriptors;
+using scg = global::System.Collections.Generic;
+namespace field_presence_test
+{
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public static partial class FieldPresenceTest
+ {
+
+ #region Extension registration
+ public static void RegisterAllExtensions(pb::ExtensionRegistry registry)
+ {
+ }
+ #endregion
+ #region Static variables
+ internal static pbd::MessageDescriptor internal__static_field_presence_test_TestAllTypes__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable<global::field_presence_test.TestAllTypes, global::field_presence_test.TestAllTypes.Builder> internal__static_field_presence_test_TestAllTypes__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_field_presence_test_TestAllTypes_NestedMessage__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable<global::field_presence_test.TestAllTypes.Types.NestedMessage, global::field_presence_test.TestAllTypes.Types.NestedMessage.Builder> internal__static_field_presence_test_TestAllTypes_NestedMessage__FieldAccessorTable;
+ #endregion
+ #region Descriptor
+ public static pbd::FileDescriptor Descriptor
+ {
+ get { return descriptor; }
+ }
+ private static pbd::FileDescriptor descriptor;
+
+ static FieldPresenceTest()
+ {
+ byte[] descriptorData = global::System.Convert.FromBase64String(
+ string.Concat(
+ "CjBwcm90b3MvZ29vZ2xlL3Byb3RvYnVmL2ZpZWxkX3ByZXNlbmNlX3Rlc3Qu",
+ "cHJvdG8SE2ZpZWxkX3ByZXNlbmNlX3Rlc3QivgIKDFRlc3RBbGxUeXBlcxIW",
+ "Cg5vcHRpb25hbF9pbnQzMhgBIAEoBRIXCg9vcHRpb25hbF9zdHJpbmcYAiAB",
+ "KAkSFgoOb3B0aW9uYWxfYnl0ZXMYAyABKAwSSgoUb3B0aW9uYWxfbmVzdGVk",
+ "X2VudW0YBCABKA4yLC5maWVsZF9wcmVzZW5jZV90ZXN0LlRlc3RBbGxUeXBl",
+ "cy5OZXN0ZWRFbnVtElAKF29wdGlvbmFsX25lc3RlZF9tZXNzYWdlGAUgASgL",
+ "Mi8uZmllbGRfcHJlc2VuY2VfdGVzdC5UZXN0QWxsVHlwZXMuTmVzdGVkTWVz",
+ "c2FnZRoeCg1OZXN0ZWRNZXNzYWdlEg0KBXZhbHVlGAEgASgFIicKCk5lc3Rl",
+ "ZEVudW0SBwoDRk9PEAASBwoDQkFSEAESBwoDQkFaEAJCMAoTY29tLmdvb2ds",
+ "ZS5wcm90b2J1ZkIWRmllbGRQcmVzZW5jZVRlc3RQcm90b6ABAWIGcHJvdG8z"));
+ pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root)
+ {
+ descriptor = root;
+ internal__static_field_presence_test_TestAllTypes__Descriptor = Descriptor.MessageTypes[0];
+ internal__static_field_presence_test_TestAllTypes__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable<global::field_presence_test.TestAllTypes, global::field_presence_test.TestAllTypes.Builder>(internal__static_field_presence_test_TestAllTypes__Descriptor,
+ new string[] { "OptionalInt32", "OptionalString", "OptionalBytes", "OptionalNestedEnum", "OptionalNestedMessage", });
+ internal__static_field_presence_test_TestAllTypes_NestedMessage__Descriptor = internal__static_field_presence_test_TestAllTypes__Descriptor.NestedTypes[0];
+ internal__static_field_presence_test_TestAllTypes_NestedMessage__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable<global::field_presence_test.TestAllTypes.Types.NestedMessage, global::field_presence_test.TestAllTypes.Types.NestedMessage.Builder>(internal__static_field_presence_test_TestAllTypes_NestedMessage__Descriptor,
+ new string[] { "Value", });
+ pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();
+ RegisterAllExtensions(registry);
+ return registry;
+ };
+ pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+ new pbd::FileDescriptor[] {
+ }, assigner);
+ }
+ #endregion
+
+ }
+ #region Messages
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class TestAllTypes : pb::GeneratedMessage<TestAllTypes, TestAllTypes.Builder>
+ {
+ private TestAllTypes() { }
+ private static readonly TestAllTypes defaultInstance = new TestAllTypes().MakeReadOnly();
+ private static readonly string[] _testAllTypesFieldNames = new string[] { "optional_bytes", "optional_int32", "optional_nested_enum", "optional_nested_message", "optional_string" };
+ private static readonly uint[] _testAllTypesFieldTags = new uint[] { 26, 8, 32, 42, 18 };
+ public static TestAllTypes DefaultInstance
+ {
+ get { return defaultInstance; }
+ }
+
+ public override TestAllTypes DefaultInstanceForType
+ {
+ get { return DefaultInstance; }
+ }
+
+ protected override TestAllTypes ThisMessage
+ {
+ get { return this; }
+ }
+
+ public static pbd::MessageDescriptor Descriptor
+ {
+ get { return global::field_presence_test.FieldPresenceTest.internal__static_field_presence_test_TestAllTypes__Descriptor; }
+ }
+
+ protected override pb::FieldAccess.FieldAccessorTable<TestAllTypes, TestAllTypes.Builder> InternalFieldAccessors
+ {
+ get { return global::field_presence_test.FieldPresenceTest.internal__static_field_presence_test_TestAllTypes__FieldAccessorTable; }
+ }
+
+ #region Nested types
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public static partial class Types
+ {
+ public enum NestedEnum
+ {
+ FOO = 0,
+ BAR = 1,
+ BAZ = 2,
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class NestedMessage : pb::GeneratedMessage<NestedMessage, NestedMessage.Builder>
+ {
+ private NestedMessage() { }
+ private static readonly NestedMessage defaultInstance = new NestedMessage().MakeReadOnly();
+ private static readonly string[] _nestedMessageFieldNames = new string[] { "value" };
+ private static readonly uint[] _nestedMessageFieldTags = new uint[] { 8 };
+ public static NestedMessage DefaultInstance
+ {
+ get { return defaultInstance; }
+ }
+
+ public override NestedMessage DefaultInstanceForType
+ {
+ get { return DefaultInstance; }
+ }
+
+ protected override NestedMessage ThisMessage
+ {
+ get { return this; }
+ }
+
+ public static pbd::MessageDescriptor Descriptor
+ {
+ get { return global::field_presence_test.FieldPresenceTest.internal__static_field_presence_test_TestAllTypes_NestedMessage__Descriptor; }
+ }
+
+ protected override pb::FieldAccess.FieldAccessorTable<NestedMessage, NestedMessage.Builder> InternalFieldAccessors
+ {
+ get { return global::field_presence_test.FieldPresenceTest.internal__static_field_presence_test_TestAllTypes_NestedMessage__FieldAccessorTable; }
+ }
+
+ public const int ValueFieldNumber = 1;
+ private int value_;
+ public int Value
+ {
+ get { return value_; }
+ }
+
+ public override void WriteTo(pb::ICodedOutputStream output)
+ {
+ CalcSerializedSize();
+ string[] field_names = _nestedMessageFieldNames;
+ if (Value != 0)
+ {
+ output.WriteInt32(1, field_names[0], Value);
+ }
+ UnknownFields.WriteTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public override int SerializedSize
+ {
+ get
+ {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+ return CalcSerializedSize();
+ }
+ }
+
+ private int CalcSerializedSize()
+ {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (Value != 0)
+ {
+ size += pb::CodedOutputStream.ComputeInt32Size(1, Value);
+ }
+ size += UnknownFields.SerializedSize;
+ memoizedSerializedSize = size;
+ return size;
+ }
+ public static NestedMessage ParseFrom(pb::ByteString data)
+ {
+ return ((Builder)CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static NestedMessage ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry)
+ {
+ return ((Builder)CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static NestedMessage ParseFrom(byte[] data)
+ {
+ return ((Builder)CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static NestedMessage ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry)
+ {
+ return ((Builder)CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static NestedMessage ParseFrom(global::System.IO.Stream input)
+ {
+ return ((Builder)CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static NestedMessage ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry)
+ {
+ return ((Builder)CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ public static NestedMessage ParseDelimitedFrom(global::System.IO.Stream input)
+ {
+ return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
+ }
+ public static NestedMessage ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry)
+ {
+ return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
+ }
+ public static NestedMessage ParseFrom(pb::ICodedInputStream input)
+ {
+ return ((Builder)CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static NestedMessage ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry)
+ {
+ return ((Builder)CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ private NestedMessage MakeReadOnly()
+ {
+ return this;
+ }
+
+ public static Builder CreateBuilder() { return new Builder(); }
+ public override Builder ToBuilder() { return CreateBuilder(this); }
+ public override Builder CreateBuilderForType() { return new Builder(); }
+ public static Builder CreateBuilder(NestedMessage prototype)
+ {
+ return new Builder(prototype);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class Builder : pb::GeneratedBuilder<NestedMessage, Builder>
+ {
+ protected override Builder ThisBuilder
+ {
+ get { return this; }
+ }
+ public Builder()
+ {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ }
+ internal Builder(NestedMessage cloneFrom)
+ {
+ result = cloneFrom;
+ resultIsReadOnly = true;
+ }
+
+ private bool resultIsReadOnly;
+ private NestedMessage result;
+
+ private NestedMessage PrepareBuilder()
+ {
+ if (resultIsReadOnly)
+ {
+ NestedMessage original = result;
+ result = new NestedMessage();
+ resultIsReadOnly = false;
+ MergeFrom(original);
+ }
+ return result;
+ }
+
+ public override bool IsInitialized
+ {
+ get { return result.IsInitialized; }
+ }
+
+ protected override NestedMessage MessageBeingBuilt
+ {
+ get { return PrepareBuilder(); }
+ }
+
+ public override Builder Clear()
+ {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ return this;
+ }
+
+ public override Builder Clone()
+ {
+ if (resultIsReadOnly)
+ {
+ return new Builder(result);
+ }
+ else
+ {
+ return new Builder().MergeFrom(result);
+ }
+ }
+
+ public override pbd::MessageDescriptor DescriptorForType
+ {
+ get { return global::field_presence_test.TestAllTypes.Types.NestedMessage.Descriptor; }
+ }
+
+ public override NestedMessage DefaultInstanceForType
+ {
+ get { return global::field_presence_test.TestAllTypes.Types.NestedMessage.DefaultInstance; }
+ }
+
+ public override NestedMessage BuildPartial()
+ {
+ if (resultIsReadOnly)
+ {
+ return result;
+ }
+ resultIsReadOnly = true;
+ return result.MakeReadOnly();
+ }
+
+ public override Builder MergeFrom(pb::IMessage other)
+ {
+ if (other is NestedMessage)
+ {
+ return MergeFrom((NestedMessage)other);
+ }
+ else
+ {
+ base.MergeFrom(other);
+ return this;
+ }
+ }
+
+ public override Builder MergeFrom(NestedMessage other)
+ {
+ if (other == global::field_presence_test.TestAllTypes.Types.NestedMessage.DefaultInstance) return this;
+ PrepareBuilder();
+ if (other.Value != 0)
+ {
+ Value = other.Value;
+ }
+ this.MergeUnknownFields(other.UnknownFields);
+ return this;
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input)
+ {
+ return MergeFrom(input, pb::ExtensionRegistry.Empty);
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry)
+ {
+ PrepareBuilder();
+ pb::UnknownFieldSet.Builder unknownFields = null;
+ uint tag;
+ string field_name;
+ while (input.ReadTag(out tag, out field_name))
+ {
+ if (tag == 0 && field_name != null)
+ {
+ int field_ordinal = global::System.Array.BinarySearch(_nestedMessageFieldNames, field_name, global::System.StringComparer.Ordinal);
+ if (field_ordinal >= 0)
+ tag = _nestedMessageFieldTags[field_ordinal];
+ else
+ {
+ if (unknownFields == null)
+ {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ continue;
+ }
+ }
+ switch (tag)
+ {
+ case 0:
+ {
+ throw pb::InvalidProtocolBufferException.InvalidTag();
+ }
+ default:
+ {
+ if (pb::WireFormat.IsEndGroupTag(tag))
+ {
+ if (unknownFields != null)
+ {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+ if (unknownFields == null)
+ {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ break;
+ }
+ case 8:
+ {
+ input.ReadInt32(ref result.value_);
+ break;
+ }
+ }
+ }
+
+ if (unknownFields != null)
+ {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+
+
+ public int Value
+ {
+ get { return result.Value; }
+ set { SetValue(value); }
+ }
+ public Builder SetValue(int value)
+ {
+ PrepareBuilder();
+ result.value_ = value;
+ return this;
+ }
+ public Builder ClearValue()
+ {
+ PrepareBuilder();
+ result.value_ = 0;
+ return this;
+ }
+ }
+ static NestedMessage()
+ {
+ object.ReferenceEquals(global::field_presence_test.FieldPresenceTest.Descriptor, null);
+ }
+ }
+
+ }
+ #endregion
+
+ public const int OptionalInt32FieldNumber = 1;
+ private int optionalInt32_;
+ public int OptionalInt32
+ {
+ get { return optionalInt32_; }
+ }
+
+ public const int OptionalStringFieldNumber = 2;
+ private string optionalString_ = "";
+ public string OptionalString
+ {
+ get { return optionalString_; }
+ }
+
+ public const int OptionalBytesFieldNumber = 3;
+ private pb::ByteString optionalBytes_ = pb::ByteString.Empty;
+ public pb::ByteString OptionalBytes
+ {
+ get { return optionalBytes_; }
+ }
+
+ public const int OptionalNestedEnumFieldNumber = 4;
+ private global::field_presence_test.TestAllTypes.Types.NestedEnum optionalNestedEnum_ = global::field_presence_test.TestAllTypes.Types.NestedEnum.FOO;
+ public global::field_presence_test.TestAllTypes.Types.NestedEnum OptionalNestedEnum
+ {
+ get { return optionalNestedEnum_; }
+ }
+
+ public const int OptionalNestedMessageFieldNumber = 5;
+ private bool hasOptionalNestedMessage;
+ private global::field_presence_test.TestAllTypes.Types.NestedMessage optionalNestedMessage_;
+ public bool HasOptionalNestedMessage
+ {
+ get { return hasOptionalNestedMessage; }
+ }
+ public global::field_presence_test.TestAllTypes.Types.NestedMessage OptionalNestedMessage
+ {
+ get { return optionalNestedMessage_ ?? global::field_presence_test.TestAllTypes.Types.NestedMessage.DefaultInstance; }
+ }
+
+ public override void WriteTo(pb::ICodedOutputStream output)
+ {
+ CalcSerializedSize();
+ string[] field_names = _testAllTypesFieldNames;
+ if (OptionalInt32 != 0)
+ {
+ output.WriteInt32(1, field_names[1], OptionalInt32);
+ }
+ if (OptionalString != "")
+ {
+ output.WriteString(2, field_names[4], OptionalString);
+ }
+ if (OptionalBytes != pb::ByteString.Empty)
+ {
+ output.WriteBytes(3, field_names[0], OptionalBytes);
+ }
+ if (OptionalNestedEnum != global::field_presence_test.TestAllTypes.Types.NestedEnum.FOO)
+ {
+ output.WriteEnum(4, field_names[2], (int)OptionalNestedEnum, OptionalNestedEnum);
+ }
+ if (hasOptionalNestedMessage)
+ {
+ output.WriteMessage(5, field_names[3], OptionalNestedMessage);
+ }
+ UnknownFields.WriteTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public override int SerializedSize
+ {
+ get
+ {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+ return CalcSerializedSize();
+ }
+ }
+
+ private int CalcSerializedSize()
+ {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (OptionalInt32 != 0)
+ {
+ size += pb::CodedOutputStream.ComputeInt32Size(1, OptionalInt32);
+ }
+ if (OptionalString != "")
+ {
+ size += pb::CodedOutputStream.ComputeStringSize(2, OptionalString);
+ }
+ if (OptionalBytes != pb::ByteString.Empty)
+ {
+ size += pb::CodedOutputStream.ComputeBytesSize(3, OptionalBytes);
+ }
+ if (OptionalNestedEnum != global::field_presence_test.TestAllTypes.Types.NestedEnum.FOO)
+ {
+ size += pb::CodedOutputStream.ComputeEnumSize(4, (int)OptionalNestedEnum);
+ }
+ if (hasOptionalNestedMessage)
+ {
+ size += pb::CodedOutputStream.ComputeMessageSize(5, OptionalNestedMessage);
+ }
+ size += UnknownFields.SerializedSize;
+ memoizedSerializedSize = size;
+ return size;
+ }
+ public static TestAllTypes ParseFrom(pb::ByteString data)
+ {
+ return ((Builder)CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static TestAllTypes ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry)
+ {
+ return ((Builder)CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static TestAllTypes ParseFrom(byte[] data)
+ {
+ return ((Builder)CreateBuilder().MergeFrom(data)).BuildParsed();
+ }
+ public static TestAllTypes ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry)
+ {
+ return ((Builder)CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+ }
+ public static TestAllTypes ParseFrom(global::System.IO.Stream input)
+ {
+ return ((Builder)CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static TestAllTypes ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry)
+ {
+ return ((Builder)CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ public static TestAllTypes ParseDelimitedFrom(global::System.IO.Stream input)
+ {
+ return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
+ }
+ public static TestAllTypes ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry)
+ {
+ return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
+ }
+ public static TestAllTypes ParseFrom(pb::ICodedInputStream input)
+ {
+ return ((Builder)CreateBuilder().MergeFrom(input)).BuildParsed();
+ }
+ public static TestAllTypes ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry)
+ {
+ return ((Builder)CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+ }
+ private TestAllTypes MakeReadOnly()
+ {
+ return this;
+ }
+
+ public static Builder CreateBuilder() { return new Builder(); }
+ public override Builder ToBuilder() { return CreateBuilder(this); }
+ public override Builder CreateBuilderForType() { return new Builder(); }
+ public static Builder CreateBuilder(TestAllTypes prototype)
+ {
+ return new Builder(prototype);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class Builder : pb::GeneratedBuilder<TestAllTypes, Builder>
+ {
+ protected override Builder ThisBuilder
+ {
+ get { return this; }
+ }
+ public Builder()
+ {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ }
+ internal Builder(TestAllTypes cloneFrom)
+ {
+ result = cloneFrom;
+ resultIsReadOnly = true;
+ }
+
+ private bool resultIsReadOnly;
+ private TestAllTypes result;
+
+ private TestAllTypes PrepareBuilder()
+ {
+ if (resultIsReadOnly)
+ {
+ TestAllTypes original = result;
+ result = new TestAllTypes();
+ resultIsReadOnly = false;
+ MergeFrom(original);
+ }
+ return result;
+ }
+
+ public override bool IsInitialized
+ {
+ get { return result.IsInitialized; }
+ }
+
+ protected override TestAllTypes MessageBeingBuilt
+ {
+ get { return PrepareBuilder(); }
+ }
+
+ public override Builder Clear()
+ {
+ result = DefaultInstance;
+ resultIsReadOnly = true;
+ return this;
+ }
+
+ public override Builder Clone()
+ {
+ if (resultIsReadOnly)
+ {
+ return new Builder(result);
+ }
+ else
+ {
+ return new Builder().MergeFrom(result);
+ }
+ }
+
+ public override pbd::MessageDescriptor DescriptorForType
+ {
+ get { return global::field_presence_test.TestAllTypes.Descriptor; }
+ }
+
+ public override TestAllTypes DefaultInstanceForType
+ {
+ get { return global::field_presence_test.TestAllTypes.DefaultInstance; }
+ }
+
+ public override TestAllTypes BuildPartial()
+ {
+ if (resultIsReadOnly)
+ {
+ return result;
+ }
+ resultIsReadOnly = true;
+ return result.MakeReadOnly();
+ }
+
+ public override Builder MergeFrom(pb::IMessage other)
+ {
+ if (other is TestAllTypes)
+ {
+ return MergeFrom((TestAllTypes)other);
+ }
+ else
+ {
+ base.MergeFrom(other);
+ return this;
+ }
+ }
+
+ public override Builder MergeFrom(TestAllTypes other)
+ {
+ if (other == global::field_presence_test.TestAllTypes.DefaultInstance) return this;
+ PrepareBuilder();
+ if (other.OptionalInt32 != 0)
+ {
+ OptionalInt32 = other.OptionalInt32;
+ }
+ if (other.OptionalString != "")
+ {
+ OptionalString = other.OptionalString;
+ }
+ if (other.OptionalBytes != pb::ByteString.Empty)
+ {
+ OptionalBytes = other.OptionalBytes;
+ }
+ if (other.OptionalNestedEnum != global::field_presence_test.TestAllTypes.Types.NestedEnum.FOO)
+ {
+ OptionalNestedEnum = other.OptionalNestedEnum;
+ }
+ if (other.HasOptionalNestedMessage)
+ {
+ MergeOptionalNestedMessage(other.OptionalNestedMessage);
+ }
+ this.MergeUnknownFields(other.UnknownFields);
+ return this;
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input)
+ {
+ return MergeFrom(input, pb::ExtensionRegistry.Empty);
+ }
+
+ public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry)
+ {
+ PrepareBuilder();
+ pb::UnknownFieldSet.Builder unknownFields = null;
+ uint tag;
+ string field_name;
+ while (input.ReadTag(out tag, out field_name))
+ {
+ if (tag == 0 && field_name != null)
+ {
+ int field_ordinal = global::System.Array.BinarySearch(_testAllTypesFieldNames, field_name, global::System.StringComparer.Ordinal);
+ if (field_ordinal >= 0)
+ tag = _testAllTypesFieldTags[field_ordinal];
+ else
+ {
+ if (unknownFields == null)
+ {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ continue;
+ }
+ }
+ switch (tag)
+ {
+ case 0:
+ {
+ throw pb::InvalidProtocolBufferException.InvalidTag();
+ }
+ default:
+ {
+ if (pb::WireFormat.IsEndGroupTag(tag))
+ {
+ if (unknownFields != null)
+ {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+ if (unknownFields == null)
+ {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+ break;
+ }
+ case 8:
+ {
+ input.ReadInt32(ref result.optionalInt32_);
+ break;
+ }
+ case 18:
+ {
+ input.ReadString(ref result.optionalString_);
+ break;
+ }
+ case 26:
+ {
+ input.ReadBytes(ref result.optionalBytes_);
+ break;
+ }
+ case 32:
+ {
+ object unknown;
+ if (input.ReadEnum(ref result.optionalNestedEnum_, out unknown))
+ {
+ }
+ else if (unknown is int)
+ {
+ if (unknownFields == null)
+ {
+ unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+ }
+ unknownFields.MergeVarintField(4, (ulong)(int)unknown);
+ }
+ break;
+ }
+ case 42:
+ {
+ global::field_presence_test.TestAllTypes.Types.NestedMessage.Builder subBuilder = global::field_presence_test.TestAllTypes.Types.NestedMessage.CreateBuilder();
+ if (result.hasOptionalNestedMessage)
+ {
+ subBuilder.MergeFrom(OptionalNestedMessage);
+ }
+ input.ReadMessage(subBuilder, extensionRegistry);
+ OptionalNestedMessage = subBuilder.BuildPartial();
+ break;
+ }
+ }
+ }
+
+ if (unknownFields != null)
+ {
+ this.UnknownFields = unknownFields.Build();
+ }
+ return this;
+ }
+
+
+ public int OptionalInt32
+ {
+ get { return result.OptionalInt32; }
+ set { SetOptionalInt32(value); }
+ }
+ public Builder SetOptionalInt32(int value)
+ {
+ PrepareBuilder();
+ result.optionalInt32_ = value;
+ return this;
+ }
+ public Builder ClearOptionalInt32()
+ {
+ PrepareBuilder();
+ result.optionalInt32_ = 0;
+ return this;
+ }
+
+ public string OptionalString
+ {
+ get { return result.OptionalString; }
+ set { SetOptionalString(value); }
+ }
+ public Builder SetOptionalString(string value)
+ {
+ pb::ThrowHelper.ThrowIfNull(value, "value");
+ PrepareBuilder();
+ result.optionalString_ = value;
+ return this;
+ }
+ public Builder ClearOptionalString()
+ {
+ PrepareBuilder();
+ result.optionalString_ = "";
+ return this;
+ }
+
+ public pb::ByteString OptionalBytes
+ {
+ get { return result.OptionalBytes; }
+ set { SetOptionalBytes(value); }
+ }
+ public Builder SetOptionalBytes(pb::ByteString value)
+ {
+ pb::ThrowHelper.ThrowIfNull(value, "value");
+ PrepareBuilder();
+ result.optionalBytes_ = value;
+ return this;
+ }
+ public Builder ClearOptionalBytes()
+ {
+ PrepareBuilder();
+ result.optionalBytes_ = pb::ByteString.Empty;
+ return this;
+ }
+
+ public global::field_presence_test.TestAllTypes.Types.NestedEnum OptionalNestedEnum
+ {
+ get { return result.OptionalNestedEnum; }
+ set { SetOptionalNestedEnum(value); }
+ }
+ public Builder SetOptionalNestedEnum(global::field_presence_test.TestAllTypes.Types.NestedEnum value)
+ {
+ PrepareBuilder();
+ result.optionalNestedEnum_ = value;
+ return this;
+ }
+ public Builder ClearOptionalNestedEnum()
+ {
+ PrepareBuilder();
+ result.optionalNestedEnum_ = global::field_presence_test.TestAllTypes.Types.NestedEnum.FOO;
+ return this;
+ }
+
+ public bool HasOptionalNestedMessage
+ {
+ get { return result.hasOptionalNestedMessage; }
+ }
+ public global::field_presence_test.TestAllTypes.Types.NestedMessage OptionalNestedMessage
+ {
+ get { return result.OptionalNestedMessage; }
+ set { SetOptionalNestedMessage(value); }
+ }
+ public Builder SetOptionalNestedMessage(global::field_presence_test.TestAllTypes.Types.NestedMessage value)
+ {
+ pb::ThrowHelper.ThrowIfNull(value, "value");
+ PrepareBuilder();
+ result.hasOptionalNestedMessage = true;
+ result.optionalNestedMessage_ = value;
+ return this;
+ }
+ public Builder SetOptionalNestedMessage(global::field_presence_test.TestAllTypes.Types.NestedMessage.Builder builderForValue)
+ {
+ pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+ PrepareBuilder();
+ result.hasOptionalNestedMessage = true;
+ result.optionalNestedMessage_ = builderForValue.Build();
+ return this;
+ }
+ public Builder MergeOptionalNestedMessage(global::field_presence_test.TestAllTypes.Types.NestedMessage value)
+ {
+ pb::ThrowHelper.ThrowIfNull(value, "value");
+ PrepareBuilder();
+ if (result.hasOptionalNestedMessage &&
+ result.optionalNestedMessage_ != global::field_presence_test.TestAllTypes.Types.NestedMessage.DefaultInstance)
+ {
+ result.optionalNestedMessage_ = global::field_presence_test.TestAllTypes.Types.NestedMessage.CreateBuilder(result.optionalNestedMessage_).MergeFrom(value).BuildPartial();
+ }
+ else
+ {
+ result.optionalNestedMessage_ = value;
+ }
+ result.hasOptionalNestedMessage = true;
+ return this;
+ }
+ public Builder ClearOptionalNestedMessage()
+ {
+ PrepareBuilder();
+ result.hasOptionalNestedMessage = false;
+ result.optionalNestedMessage_ = null;
+ return this;
+ }
+ }
+ static TestAllTypes()
+ {
+ object.ReferenceEquals(global::field_presence_test.FieldPresenceTest.Descriptor, null);
+ }
+ }
+
+ #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/csharp/src/ProtocolBuffers/Descriptors/FileDescriptor.cs b/csharp/src/ProtocolBuffers/Descriptors/FileDescriptor.cs
index 354e99a3..8a3e26fa 100644
--- a/csharp/src/ProtocolBuffers/Descriptors/FileDescriptor.cs
+++ b/csharp/src/ProtocolBuffers/Descriptors/FileDescriptor.cs
@@ -54,6 +54,22 @@ namespace Google.ProtocolBuffers.Descriptors
private readonly IList<FileDescriptor> publicDependencies;
private readonly DescriptorPool pool;
+ public enum Syntax
+ {
+ UNKNOWN,
+ PROTO2,
+ PROTO3
+ }
+
+ public Syntax GetSyntax()
+ {
+ if (proto.Syntax == "proto3")
+ {
+ return Syntax.PROTO3;
+ }
+ return Syntax.PROTO2;
+ }
+
private FileDescriptor(FileDescriptorProto proto, FileDescriptor[] dependencies, DescriptorPool pool, bool allowUnknownDependencies)
{
this.pool = pool;
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs b/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs
index 6ba039c1..60b032e2 100644
--- a/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs
+++ b/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs
@@ -68,16 +68,21 @@ namespace Google.ProtocolBuffers.FieldAccess
{
this.descriptor = descriptor;
accessors = new IFieldAccessor<TMessage, TBuilder>[descriptor.Fields.Count];
+ bool supportFieldPresence = false;
+ if (descriptor.File.GetSyntax() == FileDescriptor.Syntax.PROTO2)
+ {
+ supportFieldPresence = true;
+ }
for (int i = 0; i < accessors.Length; i++)
{
- accessors[i] = CreateAccessor(descriptor.Fields[i], propertyNames[i]);
+ accessors[i] = CreateAccessor(descriptor.Fields[i], propertyNames[i], supportFieldPresence);
}
}
/// <summary>
/// Creates an accessor for a single field
/// </summary>
- private static IFieldAccessor<TMessage, TBuilder> CreateAccessor(FieldDescriptor field, string name)
+ private static IFieldAccessor<TMessage, TBuilder> CreateAccessor(FieldDescriptor field, string name, bool supportFieldPresence)
{
if (field.IsRepeated)
{
@@ -98,9 +103,9 @@ namespace Google.ProtocolBuffers.FieldAccess
case MappedType.Message:
return new SingleMessageAccessor<TMessage, TBuilder>(name);
case MappedType.Enum:
- return new SingleEnumAccessor<TMessage, TBuilder>(field, name);
+ return new SingleEnumAccessor<TMessage, TBuilder>(field, name, supportFieldPresence);
default:
- return new SinglePrimitiveAccessor<TMessage, TBuilder>(name);
+ return new SinglePrimitiveAccessor<TMessage, TBuilder>(field, name, supportFieldPresence);
}
}
}
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs b/csharp/src/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs
index 6327cc55..e63f717c 100644
--- a/csharp/src/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs
+++ b/csharp/src/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs
@@ -42,7 +42,7 @@ namespace Google.ProtocolBuffers.FieldAccess
{
private readonly EnumDescriptor enumDescriptor;
- internal SingleEnumAccessor(FieldDescriptor field, string name) : base(name)
+ internal SingleEnumAccessor(FieldDescriptor field, string name, bool supportFieldPresence) : base(field, name, supportFieldPresence)
{
enumDescriptor = field.EnumType;
}
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs b/csharp/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs
index 6bf48a0c..0ec2b0b7 100644
--- a/csharp/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs
+++ b/csharp/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs
@@ -48,7 +48,7 @@ namespace Google.ProtocolBuffers.FieldAccess
/// </summary>
private readonly Func<IBuilder> createBuilderDelegate;
- internal SingleMessageAccessor(string name) : base(name)
+ internal SingleMessageAccessor(string name) : base(null, name, true)
{
MethodInfo createBuilderMethod = ClrType.GetMethod("CreateBuilder", ReflectionUtil.EmptyTypes);
if (createBuilderMethod == null)
diff --git a/csharp/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs b/csharp/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs
index e5a07540..b964066d 100644
--- a/csharp/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs
+++ b/csharp/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs
@@ -31,6 +31,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Reflection;
+using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.FieldAccess
{
@@ -42,6 +43,7 @@ namespace Google.ProtocolBuffers.FieldAccess
where TBuilder : IBuilder<TMessage, TBuilder>
{
private readonly Type clrType;
+ private readonly FieldDescriptor field;
private readonly Func<TMessage, object> getValueDelegate;
private readonly Action<TBuilder, object> setValueDelegate;
private readonly Func<TMessage, bool> hasDelegate;
@@ -56,18 +58,28 @@ namespace Google.ProtocolBuffers.FieldAccess
get { return clrType; }
}
- internal SinglePrimitiveAccessor(string name)
+ internal SinglePrimitiveAccessor(FieldDescriptor fieldDesriptor, string name, bool supportFieldPresence)
{
+ field = fieldDesriptor;
PropertyInfo messageProperty = typeof(TMessage).GetProperty(name, null, ReflectionUtil.EmptyTypes);
PropertyInfo builderProperty = typeof(TBuilder).GetProperty(name, null, ReflectionUtil.EmptyTypes);
- PropertyInfo hasProperty = typeof(TMessage).GetProperty("Has" + name);
MethodInfo clearMethod = typeof(TBuilder).GetMethod("Clear" + name);
- if (messageProperty == null || builderProperty == null || hasProperty == null || clearMethod == null)
+ if (messageProperty == null || builderProperty == null || clearMethod == null)
{
throw new ArgumentException("Not all required properties/methods available");
}
+
+ if (supportFieldPresence)
+ {
+ PropertyInfo hasProperty = typeof(TMessage).GetProperty("Has" + name);
+ if (hasProperty == null)
+ {
+ throw new ArgumentException("Has properties not available");
+ }
+ hasDelegate = ReflectionUtil.CreateDelegateFunc<TMessage, bool>(hasProperty.GetGetMethod());
+ }
+
clrType = messageProperty.PropertyType;
- hasDelegate = ReflectionUtil.CreateDelegateFunc<TMessage, bool>(hasProperty.GetGetMethod());
clearDelegate = ReflectionUtil.CreateDelegateFunc<TBuilder, IBuilder>(clearMethod);
getValueDelegate = ReflectionUtil.CreateUpcastDelegate<TMessage>(messageProperty.GetGetMethod());
setValueDelegate = ReflectionUtil.CreateDowncastDelegate<TBuilder>(builderProperty.GetSetMethod());
@@ -75,6 +87,10 @@ namespace Google.ProtocolBuffers.FieldAccess
public bool Has(TMessage message)
{
+ if (hasDelegate == null)
+ {
+ return !GetValue(message).Equals(field.DefaultValue);
+ }
return hasDelegate(message);
}