From bef2caf5e49dbcf6b926d01cfb0948dedee49c93 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Thu, 14 Aug 2008 20:35:23 +0100 Subject: [PATCH] Added DynamicMessage and ExtendableBuilder, along with the first supporting tests. --- .../AbstractMessageTest.cs | 342 ++++++++ .../CodedInputStreamTest.cs | 66 +- .../CodedOutputStreamTest.cs | 24 +- .../ProtocolBuffers.Test.csproj | 2 + .../ProtocolBuffers.Test/ReflectionTester.cs | 782 ++++++++++++++++++ .../UnitTestEmbedOptimizeForProtoFile.cs | 5 +- .../TestProtos/UnitTestImportProtoFile.cs | 5 +- .../TestProtos/UnitTestMessageSetProtoFile.cs | 27 +- .../UnitTestOptimizeForProtoFile.cs | 3 +- .../TestProtos/UnitTestProtoFile.cs | 175 +++- csharp/ProtocolBuffers.Test/TestUtil.cs | 382 ++++++++- csharp/ProtocolBuffers/AbstractBuilder.cs | 13 +- csharp/ProtocolBuffers/AbstractMessage.cs | 7 +- .../Collections/Dictionaries.cs | 79 ++ .../DescriptorProtos/DescriptorProtoFile.cs | 61 +- .../Descriptors/EnumDescriptor.cs | 6 +- csharp/ProtocolBuffers/DynamicMessage.cs | 376 ++++++++- csharp/ProtocolBuffers/ExtendableBuilder.cs | 147 ++++ csharp/ProtocolBuffers/ExtendableMessage.cs | 19 +- .../FieldAccess/RepeatedPrimitiveAccessor.cs | 2 +- csharp/ProtocolBuffers/GeneratedBuilder.cs | 16 +- .../ProtocolBuffers/GeneratedExtensionBase.cs | 37 +- csharp/ProtocolBuffers/GeneratedMessage.cs | 7 +- .../GeneratedRepeatException.cs | 4 +- .../GeneratedSingleExtension.cs | 2 +- csharp/ProtocolBuffers/IBuilder.cs | 12 + csharp/ProtocolBuffers/ProtocolBuffers.csproj | 1 + csharp/ProtocolBuffers/TextGenerator.cs | 3 + 28 files changed, 2494 insertions(+), 111 deletions(-) create mode 100644 csharp/ProtocolBuffers.Test/AbstractMessageTest.cs create mode 100644 csharp/ProtocolBuffers.Test/ReflectionTester.cs create mode 100644 csharp/ProtocolBuffers/ExtendableBuilder.cs diff --git a/csharp/ProtocolBuffers.Test/AbstractMessageTest.cs b/csharp/ProtocolBuffers.Test/AbstractMessageTest.cs new file mode 100644 index 0000000000..2c16b5b438 --- /dev/null +++ b/csharp/ProtocolBuffers.Test/AbstractMessageTest.cs @@ -0,0 +1,342 @@ +using System; +using System.Collections.Generic; +using Google.ProtocolBuffers.Descriptors; +using NUnit.Framework; +using Google.ProtocolBuffers.TestProtos; + +namespace Google.ProtocolBuffers { + [TestFixture] + public class AbstractMessageTest { + + [Test] + public void Clear() { + AbstractMessageWrapper message = (AbstractMessageWrapper) + new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder(TestUtil.GetAllSet())).Clear().Build(); + TestUtil.AssertClear((TestAllTypes) message.WrappedMessage); + } + + [Test] + public void Copy() { + AbstractMessageWrapper message = (AbstractMessageWrapper) + new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder()).MergeFrom(TestUtil.GetAllSet()).Build(); + TestUtil.AssertAllFieldsSet((TestAllTypes) message.WrappedMessage); + } + + [Test] + public void SerializedSize() { + TestAllTypes message = TestUtil.GetAllSet(); + IMessage abstractMessage = new AbstractMessageWrapper(TestUtil.GetAllSet()); + + Assert.AreEqual(message.SerializedSize, abstractMessage.SerializedSize); + } + + [Test] + public void Serialization() { + IMessage abstractMessage = new AbstractMessageWrapper(TestUtil.GetAllSet()); + TestUtil.AssertAllFieldsSet(TestAllTypes.ParseFrom(abstractMessage.ToByteString())); + Assert.AreEqual(TestUtil.GetAllSet().ToByteString(), abstractMessage.ToByteString()); + } + + [Test] + public void Parsing() { + IBuilder builder = new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder()); + AbstractMessageWrapper message = (AbstractMessageWrapper) builder.MergeFrom(TestUtil.GetAllSet().ToByteString()).Build(); + TestUtil.AssertAllFieldsSet((TestAllTypes) message.WrappedMessage); + } + + [Test] + public void OptimizedForSize() { + // We're mostly only Checking that this class was compiled successfully. + TestOptimizedForSize message = TestOptimizedForSize.CreateBuilder().SetI(1).Build(); + message = TestOptimizedForSize.ParseFrom(message.ToByteString()); + Assert.AreEqual(2, message.SerializedSize); + } + + // ----------------------------------------------------------------- + // Tests for isInitialized(). + + private static readonly TestRequired TestRequiredUninitialized = TestRequired.DefaultInstance; + private static readonly TestRequired TestRequiredInitialized = TestRequired.CreateBuilder().SetA(1).SetB(2).SetC(3).Build(); + + [Test] + public void IsInitialized() { + TestRequired.Builder builder = TestRequired.CreateBuilder(); + AbstractMessageWrapper.Builder abstractBuilder = new AbstractMessageWrapper.Builder(builder); + + Assert.IsFalse(abstractBuilder.Initialized); + builder.A = 1; + Assert.IsFalse(abstractBuilder.Initialized); + builder.B = 1; + Assert.IsFalse(abstractBuilder.Initialized); + builder.C = 1; + Assert.IsTrue(abstractBuilder.Initialized); + } + + [Test] + public void ForeignIsInitialized() { + TestRequiredForeign.Builder builder = TestRequiredForeign.CreateBuilder(); + AbstractMessageWrapper.Builder abstractBuilder = new AbstractMessageWrapper.Builder(builder); + + Assert.IsTrue(abstractBuilder.Initialized); + + builder.SetOptionalMessage(TestRequiredUninitialized); + Assert.IsFalse(abstractBuilder.Initialized); + + builder.SetOptionalMessage(TestRequiredInitialized); + Assert.IsTrue(abstractBuilder.Initialized); + + builder.AddRepeatedMessage(TestRequiredUninitialized); + Assert.IsFalse(abstractBuilder.Initialized); + + builder.SetRepeatedMessage(0, TestRequiredInitialized); + Assert.IsTrue(abstractBuilder.Initialized); + } + + // ----------------------------------------------------------------- + // Tests for mergeFrom + + static readonly TestAllTypes MergeSource = TestAllTypes.CreateBuilder() + .SetOptionalInt32(1) + .SetOptionalString("foo") + .SetOptionalForeignMessage(ForeignMessage.DefaultInstance) + .AddRepeatedString("bar") + .Build(); + + static readonly TestAllTypes MergeDest = TestAllTypes.CreateBuilder() + .SetOptionalInt64(2) + .SetOptionalString("baz") + .SetOptionalForeignMessage(ForeignMessage.CreateBuilder().SetC(3).Build()) + .AddRepeatedString("qux") + .Build(); + + const string MergeResultText = "optional_int32: 1\n" + + "optional_int64: 2\n" + + "optional_string: \"foo\"\n" + + "optional_foreign_message {\n" + + " c: 3\n" + + "}\n" + + "repeated_string: \"qux\"\n" + + "repeated_string: \"bar\"\n"; + + [Test] + public void MergeFrom() { + AbstractMessageWrapper result = (AbstractMessageWrapper) + new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder(MergeDest)) + .MergeFrom(MergeSource) + .Build(); + + Assert.AreEqual(MergeResultText, result.ToString()); + } + + // ----------------------------------------------------------------- + // Tests for equals and hashCode + + [Test] + public void EqualsAndHashCode() { + TestAllTypes a = TestUtil.GetAllSet(); + TestAllTypes b = TestAllTypes.CreateBuilder().Build(); + TestAllTypes c = TestAllTypes.CreateBuilder(b).AddRepeatedString("x").Build(); + TestAllTypes d = TestAllTypes.CreateBuilder(c).AddRepeatedString("y").Build(); + TestAllExtensions e = TestUtil.GetAllExtensionsSet(); + TestAllExtensions f = TestAllExtensions.CreateBuilder(e) + .AddExtension(UnitTestProtoFile.RepeatedInt32Extension, 999).Build(); + + CheckEqualsIsConsistent(a); + CheckEqualsIsConsistent(b); + CheckEqualsIsConsistent(c); + CheckEqualsIsConsistent(d); + CheckEqualsIsConsistent(e); + CheckEqualsIsConsistent(f); + + CheckNotEqual(a, b); + CheckNotEqual(a, c); + CheckNotEqual(a, d); + CheckNotEqual(a, e); + CheckNotEqual(a, f); + + CheckNotEqual(b, c); + CheckNotEqual(b, d); + CheckNotEqual(b, e); + CheckNotEqual(b, f); + + CheckNotEqual(c, d); + CheckNotEqual(c, e); + CheckNotEqual(c, f); + + CheckNotEqual(d, e); + CheckNotEqual(d, f); + + CheckNotEqual(e, f); + } + + /// + /// Asserts that the given protos are equal and have the same hash code. + /// + private static void CheckEqualsIsConsistent(IMessage message) { + // Object should be equal to itself. + Assert.AreEqual(message, message); + + // Object should be equal to a dynamic copy of itself. + DynamicMessage dynamic = (DynamicMessage) ((IBuilder) DynamicMessage.CreateBuilder(message)).Build(); + Assert.AreEqual(message, dynamic); + Assert.AreEqual(dynamic, message); + Assert.AreEqual(dynamic.GetHashCode(), message.GetHashCode()); + } + + /// + /// Asserts that the given protos are not equal and have different hash codes. + /// + /// + /// It's valid for non-equal objects to have the same hash code, so + /// this test is stricter than it needs to be. However, this should happen + /// relatively rarely. (If this test fails, it's probably still due to a bug.) + /// + private static void CheckNotEqual(IMessage m1, IMessage m2) { + String equalsError = string.Format("{0} should not be equal to {1}", m1, m2); + Assert.IsFalse(m1.Equals(m2), equalsError); + Assert.IsFalse(m2.Equals(m1), equalsError); + + Assert.IsFalse(m1.GetHashCode() == m2.GetHashCode(), + string.Format("{0} should have a different hash code from {1}", m1, m2)); + } + + /// + /// Extends AbstractMessage and wraps some other message object. The methods + /// of the Message interface which aren't explicitly implemented by + /// AbstractMessage are forwarded to the wrapped object. This allows us to + /// test that AbstractMessage's implementations work even if the wrapped + /// object does not use them. + /// + private class AbstractMessageWrapper : AbstractMessage { + private readonly IMessage wrappedMessage; + + public IMessage WrappedMessage { + get { return wrappedMessage; } + } + + public AbstractMessageWrapper(IMessage wrappedMessage) { + this.wrappedMessage = wrappedMessage; + } + + public override MessageDescriptor DescriptorForType { + get { return wrappedMessage.DescriptorForType; } + } + + protected override IMessage DefaultInstanceForTypeImpl { + get { return new AbstractMessageWrapper(wrappedMessage.DefaultInstanceForType); } + } + + public override IDictionary AllFields { + get { return wrappedMessage.AllFields; } + } + + public override bool HasField(FieldDescriptor field) { + return wrappedMessage.HasField(field); + } + + public override object this[FieldDescriptor field] { + get { return wrappedMessage[field]; } + } + + public override object this[FieldDescriptor field, int index] { + get { return wrappedMessage[field, index]; } + } + + public override int GetRepeatedFieldCount(FieldDescriptor field) { + return wrappedMessage.GetRepeatedFieldCount(field); + } + + public override UnknownFieldSet UnknownFields { + get { return wrappedMessage.UnknownFields; } + } + + protected override IBuilder CreateBuilderForTypeImpl() { + return new Builder(wrappedMessage.CreateBuilderForType()); + } + + internal class Builder : AbstractBuilder { + private readonly IBuilder wrappedBuilder; + + internal Builder(IBuilder wrappedBuilder) { + this.wrappedBuilder = wrappedBuilder; + } + + public override bool Initialized { + get { return wrappedBuilder.Initialized; } + } + + public override IDictionary AllFields { + get { return wrappedBuilder.AllFields; } + } + + public override object this[FieldDescriptor field] { + get { return wrappedBuilder[field]; } + set { wrappedBuilder[field] = value; } + } + + public override MessageDescriptor DescriptorForType { + get { return wrappedBuilder.DescriptorForType; } + } + + public override int GetRepeatedFieldCount(FieldDescriptor field) { + return wrappedBuilder.GetRepeatedFieldCount(field); + } + + public override object this[FieldDescriptor field, int index] { + get { return wrappedBuilder[field, index]; } + set { wrappedBuilder[field, index] = value; } + } + + public override bool HasField(FieldDescriptor field) { + return wrappedBuilder.HasField(field); + } + + public override UnknownFieldSet UnknownFields { + get { return wrappedBuilder.UnknownFields; } + set { wrappedBuilder.UnknownFields = value; } + } + + protected override IMessage BuildImpl() { + return new AbstractMessageWrapper(wrappedBuilder.Build()); + } + + protected override IMessage BuildPartialImpl() { + return new AbstractMessageWrapper(wrappedBuilder.BuildPartial()); + } + + protected override IBuilder CloneImpl() { + return new Builder(wrappedBuilder.Clone()); + } + + protected override IMessage DefaultInstanceForTypeImpl { + get { return wrappedBuilder.DefaultInstanceForType; } + } + + protected override IBuilder ClearFieldImpl(FieldDescriptor field) { + wrappedBuilder.ClearField(field); + return this; + } + + protected override IBuilder AddRepeatedFieldImpl(FieldDescriptor field, object value) { + wrappedBuilder.AddRepeatedField(field, value); + return this; + } + + public override IBuilder CreateBuilderForField(FieldDescriptor field) { + wrappedBuilder.CreateBuilderForField(field); + return this; + } + + public override IBuilder MergeFrom(IMessage other) { + wrappedBuilder.MergeFrom(other); + return this; + } + + protected override IBuilder MergeFromImpl(CodedInputStream input, ExtensionRegistry extensionRegistry) { + wrappedBuilder.MergeFrom(input, extensionRegistry); + return this; + } + } + } + } +} diff --git a/csharp/ProtocolBuffers.Test/CodedInputStreamTest.cs b/csharp/ProtocolBuffers.Test/CodedInputStreamTest.cs index 3be8041cd3..9dc34ca7e3 100644 --- a/csharp/ProtocolBuffers.Test/CodedInputStreamTest.cs +++ b/csharp/ProtocolBuffers.Test/CodedInputStreamTest.cs @@ -274,65 +274,65 @@ namespace Google.ProtocolBuffers { // success. } } - - /* TODO(jonskeet): Reinstate this when protoc is ready - private TestRecursiveMessage makeRecursiveMessage(int depth) { + private static TestRecursiveMessage MakeRecursiveMessage(int depth) { if (depth == 0) { - return TestRecursiveMessage.newBuilder().setI(5).build(); + return TestRecursiveMessage.CreateBuilder().SetI(5).Build(); } else { - return TestRecursiveMessage.newBuilder() - .setA(makeRecursiveMessage(depth - 1)).build(); + return TestRecursiveMessage.CreateBuilder() + .SetA(MakeRecursiveMessage(depth - 1)).Build(); } } - private void assertMessageDepth(TestRecursiveMessage message, int depth) { + private static void AssertMessageDepth(TestRecursiveMessage message, int depth) { if (depth == 0) { - assertFalse(message.hasA()); - assertEquals(5, message.getI()); + Assert.IsFalse(message.HasA); + Assert.AreEqual(5, message.I); } else { - assertTrue(message.hasA()); - assertMessageDepth(message.getA(), depth - 1); + Assert.IsTrue(message.HasA); + AssertMessageDepth(message.A, depth - 1); } } - public void testMaliciousRecursion() { - ByteString data64 = makeRecursiveMessage(64).toByteString(); - ByteString data65 = makeRecursiveMessage(65).toByteString(); + [Test] + public void MaliciousRecursion() { + ByteString data64 = MakeRecursiveMessage(64).ToByteString(); + ByteString data65 = MakeRecursiveMessage(65).ToByteString(); - assertMessageDepth(TestRecursiveMessage.parseFrom(data64), 64); + AssertMessageDepth(TestRecursiveMessage.ParseFrom(data64), 64); try { - TestRecursiveMessage.parseFrom(data65); - fail("Should have thrown an exception!"); - } catch (InvalidProtocolBufferException e) { + TestRecursiveMessage.ParseFrom(data65); + Assert.Fail("Should have thrown an exception!"); + } catch (InvalidProtocolBufferException) { // success. } - CodedInputStream input = data64.newCodedInput(); - input.setRecursionLimit(8); + CodedInputStream input = data64.CreateCodedInput(); + input.SetRecursionLimit(8); try { - TestRecursiveMessage.parseFrom(input); - fail("Should have thrown an exception!"); - } catch (InvalidProtocolBufferException e) { + TestRecursiveMessage.ParseFrom(input); + Assert.Fail("Should have thrown an exception!"); + } catch (InvalidProtocolBufferException) { // success. } } - */ - /* TODO(jonskeet): Reinstate this when protoc is ready - public void testSizeLimit() throws Exception { - CodedInputStream input = CodedInputStream.newInstance( - TestUtil.getAllSet().toByteString().newInput()); - input.setSizeLimit(16); + [Test] + public void SizeLimit() { + // Have to use a Stream rather than ByteString.CreateCodedInput as SizeLimit doesn't + // apply to the latter case. + MemoryStream ms = new MemoryStream(TestUtil.GetAllSet().ToByteString().ToByteArray()); + CodedInputStream input = CodedInputStream.CreateInstance(ms); + input.SetSizeLimit(16); try { - TestAllTypes.parseFrom(input); - fail("Should have thrown an exception!"); - } catch (InvalidProtocolBufferException e) { + TestAllTypes.ParseFrom(input); + Assert.Fail("Should have thrown an exception!"); + } catch (InvalidProtocolBufferException) { // success. } - }*/ + } /// /// Tests that if we read an string that contains invalid UTF-8, no exception diff --git a/csharp/ProtocolBuffers.Test/CodedOutputStreamTest.cs b/csharp/ProtocolBuffers.Test/CodedOutputStreamTest.cs index f2f00dfeb9..60f7db87d9 100644 --- a/csharp/ProtocolBuffers.Test/CodedOutputStreamTest.cs +++ b/csharp/ProtocolBuffers.Test/CodedOutputStreamTest.cs @@ -14,6 +14,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +using Google.ProtocolBuffers.TestProtos; using NUnit.Framework; namespace Google.ProtocolBuffers { @@ -33,6 +34,10 @@ namespace Google.ProtocolBuffers { return bytes; } + private static void AssertEqualBytes(byte[] a, byte[] b) { + Assert.AreEqual(ByteString.CopyFrom(a), ByteString.CopyFrom(b)); + } + /// /// Writes the given value using WriteRawVarint32() and WriteRawVarint64() and /// checks that the result matches the given bytes @@ -174,24 +179,23 @@ namespace Google.ProtocolBuffers { 0x9abcdef012345678UL); } - /* TODO(jonskeet): Put this back when we've got the rest working! [Test] - public void testWriteWholeMessage() throws Exception { - TestAllTypes message = TestUtil.getAllSet(); + public void WriteWholeMessage() { + TestAllTypes message = TestUtil.GetAllSet(); - byte[] rawBytes = message.toByteArray(); - assertEqualBytes(TestUtil.getGoldenMessage().toByteArray(), rawBytes); + byte[] rawBytes = message.ToByteArray(); + AssertEqualBytes(TestUtil.GoldenMessage.ToByteArray(), rawBytes); // Try different block sizes. for (int blockSize = 1; blockSize < 256; blockSize *= 2) { MemoryStream rawOutput = new MemoryStream(); CodedOutputStream output = - CodedOutputStream.newInstance(rawOutput, blockSize); - message.writeTo(output); - output.flush(); - assertEqualBytes(rawBytes, rawOutput.toByteArray()); + CodedOutputStream.CreateInstance(rawOutput, blockSize); + message.WriteTo(output); + output.Flush(); + AssertEqualBytes(rawBytes, rawOutput.ToArray()); } - } */ + } [Test] diff --git a/csharp/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj b/csharp/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj index bbb93a1fde..87c5bedb3a 100644 --- a/csharp/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj +++ b/csharp/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj @@ -44,10 +44,12 @@ + + diff --git a/csharp/ProtocolBuffers.Test/ReflectionTester.cs b/csharp/ProtocolBuffers.Test/ReflectionTester.cs new file mode 100644 index 0000000000..c776772412 --- /dev/null +++ b/csharp/ProtocolBuffers.Test/ReflectionTester.cs @@ -0,0 +1,782 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Google.ProtocolBuffers.Descriptors; +using NUnit.Framework; + +namespace Google.ProtocolBuffers { + /// + /// Performs the same things that the methods of TestUtil do, but + /// via the reflection interface. This is its own class because it needs + /// to know what descriptor to use. + /// + internal class ReflectionTester { + private readonly MessageDescriptor baseDescriptor; + private readonly ExtensionRegistry extensionRegistry; + + private readonly FileDescriptor file; + private readonly FileDescriptor importFile; + + private readonly MessageDescriptor optionalGroup; + private readonly MessageDescriptor repeatedGroup; + private readonly MessageDescriptor nestedMessage; + private readonly MessageDescriptor foreignMessage; + private readonly MessageDescriptor importMessage; + + private readonly FieldDescriptor groupA; + private readonly FieldDescriptor repeatedGroupA; + private readonly FieldDescriptor nestedB; + private readonly FieldDescriptor foreignC; + private readonly FieldDescriptor importD; + + private readonly EnumDescriptor nestedEnum; + private readonly EnumDescriptor foreignEnum; + private readonly EnumDescriptor importEnum; + + private readonly EnumValueDescriptor nestedFoo; + private readonly EnumValueDescriptor nestedBar; + private readonly EnumValueDescriptor nestedBaz; + private readonly EnumValueDescriptor foreignFoo; + private readonly EnumValueDescriptor foreignBar; + private readonly EnumValueDescriptor foreignBaz; + private readonly EnumValueDescriptor importFoo; + private readonly EnumValueDescriptor importBar; + private readonly EnumValueDescriptor importBaz; + + /// + /// Constructs an instance that will expect messages using the given + /// descriptor. Normally should be + /// a descriptor for TestAllTypes. However, if extensionRegistry is non-null, + /// then baseDescriptor should be for TestAllExtensions instead, and instead of + /// reading and writing normal fields, the tester will read and write extensions. + /// All of the TestAllExtensions extensions must be registered in the registry. + /// TODO(jonskeet): Enforce all of these with two factory methods. + /// + public ReflectionTester(MessageDescriptor baseDescriptor, + ExtensionRegistry extensionRegistry) { + this.baseDescriptor = baseDescriptor; + this.extensionRegistry = extensionRegistry; + + this.file = baseDescriptor.File; + Assert.AreEqual(1, file.Dependencies.Count); + this.importFile = file.Dependencies[0]; + + MessageDescriptor testAllTypes; + if (extensionRegistry == null) { + testAllTypes = baseDescriptor; + } else { + testAllTypes = file.FindTypeByName("TestAllTypes"); + Assert.IsNotNull(testAllTypes); + } + + if (extensionRegistry == null) { + this.optionalGroup = + baseDescriptor.FindDescriptor("OptionalGroup"); + this.repeatedGroup = + baseDescriptor.FindDescriptor("RepeatedGroup"); + } else { + this.optionalGroup = + file.FindTypeByName("OptionalGroup_extension"); + this.repeatedGroup = + file.FindTypeByName("RepeatedGroup_extension"); + } + this.nestedMessage = testAllTypes.FindDescriptor("NestedMessage"); + this.foreignMessage = file.FindTypeByName("ForeignMessage"); + this.importMessage = importFile.FindTypeByName("ImportMessage"); + + this.nestedEnum = testAllTypes.FindDescriptor("NestedEnum"); + this.foreignEnum = file.FindTypeByName("ForeignEnum"); + this.importEnum = importFile.FindTypeByName("ImportEnum"); + + Assert.IsNotNull(optionalGroup ); + Assert.IsNotNull(repeatedGroup ); + Assert.IsNotNull(nestedMessage ); + Assert.IsNotNull(foreignMessage); + Assert.IsNotNull(importMessage ); + Assert.IsNotNull(nestedEnum ); + Assert.IsNotNull(foreignEnum ); + Assert.IsNotNull(importEnum ); + + this.nestedB = nestedMessage.FindDescriptor("bb"); + this.foreignC = foreignMessage.FindDescriptor("c"); + this.importD = importMessage .FindDescriptor("d"); + this.nestedFoo = nestedEnum.FindValueByName("FOO"); + this.nestedBar = nestedEnum.FindValueByName("BAR"); + this.nestedBaz = nestedEnum.FindValueByName("BAZ"); + this.foreignFoo = foreignEnum.FindValueByName("FOREIGN_FOO"); + this.foreignBar = foreignEnum.FindValueByName("FOREIGN_BAR"); + this.foreignBaz = foreignEnum.FindValueByName("FOREIGN_BAZ"); + this.importFoo = importEnum.FindValueByName("IMPORT_FOO"); + this.importBar = importEnum.FindValueByName("IMPORT_BAR"); + this.importBaz = importEnum.FindValueByName("IMPORT_BAZ"); + + this.groupA = optionalGroup.FindDescriptor("a"); + this.repeatedGroupA = repeatedGroup.FindDescriptor("a"); + + Assert.IsNotNull(groupA ); + Assert.IsNotNull(repeatedGroupA); + Assert.IsNotNull(nestedB ); + Assert.IsNotNull(foreignC ); + Assert.IsNotNull(importD ); + Assert.IsNotNull(nestedFoo ); + Assert.IsNotNull(nestedBar ); + Assert.IsNotNull(nestedBaz ); + Assert.IsNotNull(foreignFoo ); + Assert.IsNotNull(foreignBar ); + Assert.IsNotNull(foreignBaz ); + Assert.IsNotNull(importFoo ); + Assert.IsNotNull(importBar ); + Assert.IsNotNull(importBaz ); + } + + /** + * Shorthand to get a FieldDescriptor for a field of unittest::TestAllTypes. + */ + private FieldDescriptor f(String name) { + FieldDescriptor result; + if (extensionRegistry == null) { + result = baseDescriptor.FindDescriptor(name); + } else { + result = file.FindTypeByName(name + "_extension"); + } + Assert.IsNotNull(result); + return result; + } + + /** + * Calls {@code parent.CreateBuilderForField()} or uses the + * {@code ExtensionRegistry} to find an appropriateIBuilder, depending + * on what type is being tested. + */ + private IBuilder CreateBuilderForField(IBuilder parent, FieldDescriptor field) { + if (extensionRegistry == null) { + return parent.CreateBuilderForField(field); + } else { + ExtensionInfo extension = extensionRegistry[field.ContainingType, field.FieldNumber]; + Assert.IsNotNull(extension); + Assert.IsNotNull(extension.DefaultInstance); + return extension.DefaultInstance.CreateBuilderForType(); + } + } + + // ------------------------------------------------------------------- + + /** + * Set every field of {@code message} to the values expected by + * {@code assertAllFieldsSet()}, using the {@link MessageIBuilder} + * reflection interface. + */ + internal void SetAllFieldsViaReflection(IBuilder message) { + message[f("optional_int32" )] = 101 ; + message[f("optional_int64" )] = 102L; + message[f("optional_uint32" )] = 103 ; + message[f("optional_uint64" )] = 104L; + message[f("optional_sint32" )] = 105 ; + message[f("optional_sint64" )] = 106L; + message[f("optional_fixed32" )] = 107 ; + message[f("optional_fixed64" )] = 108L; + message[f("optional_sfixed32")] = 109 ; + message[f("optional_sfixed64")] = 110L; + message[f("optional_float" )] = 111F; + message[f("optional_double" )] = 112D; + message[f("optional_bool" )] = true; + message[f("optional_string" )] = "115"; + message[f("optional_bytes")] = TestUtil.ToBytes("116"); + + message[f("optionalgroup")] = CreateBuilderForField(message, f("optionalgroup")).SetField(groupA, 117).Build(); + message[f("optional_nested_message")] = CreateBuilderForField(message, f("optional_nested_message")).SetField(nestedB, 118).Build(); + message[f("optional_foreign_message")] = CreateBuilderForField(message, f("optional_foreign_message")).SetField(foreignC, 119).Build(); + message[f("optional_import_message")] = CreateBuilderForField(message, f("optional_import_message")).SetField(importD, 120).Build(); + + message[f("optional_nested_enum" )] = nestedBaz; + message[f("optional_foreign_enum")] = foreignBaz; + message[f("optional_import_enum" )] = importBaz; + + message[f("optional_string_piece" )] = "124"; + message[f("optional_cord" )] = "125"; + + // ----------------------------------------------------------------- + + message.AddRepeatedField(f("repeated_int32" ), 201 ); + message.AddRepeatedField(f("repeated_int64" ), 202L); + message.AddRepeatedField(f("repeated_uint32" ), 203 ); + message.AddRepeatedField(f("repeated_uint64" ), 204L); + message.AddRepeatedField(f("repeated_sint32" ), 205 ); + message.AddRepeatedField(f("repeated_sint64" ), 206L); + message.AddRepeatedField(f("repeated_fixed32" ), 207 ); + message.AddRepeatedField(f("repeated_fixed64" ), 208L); + message.AddRepeatedField(f("repeated_sfixed32"), 209 ); + message.AddRepeatedField(f("repeated_sfixed64"), 210L); + message.AddRepeatedField(f("repeated_float" ), 211F); + message.AddRepeatedField(f("repeated_double" ), 212D); + message.AddRepeatedField(f("repeated_bool" ), true); + message.AddRepeatedField(f("repeated_string" ), "215"); + message.AddRepeatedField(f("repeated_bytes" ), TestUtil.ToBytes("216")); + + + message.AddRepeatedField(f("repeatedgroup"), CreateBuilderForField(message, f("repeatedgroup")).SetField(repeatedGroupA, 217).Build()); + message.AddRepeatedField(f("repeated_nested_message"), CreateBuilderForField(message, f("repeated_nested_message")).SetField(nestedB, 218).Build()); + message.AddRepeatedField(f("repeated_foreign_message"), CreateBuilderForField(message, f("repeated_foreign_message")).SetField(foreignC, 219).Build()); + message.AddRepeatedField(f("repeated_import_message"), CreateBuilderForField(message, f("repeated_import_message")).SetField(importD, 220).Build()); + + message.AddRepeatedField(f("repeated_nested_enum" ), nestedBar); + message.AddRepeatedField(f("repeated_foreign_enum"), foreignBar); + message.AddRepeatedField(f("repeated_import_enum" ), importBar); + + message.AddRepeatedField(f("repeated_string_piece" ), "224"); + message.AddRepeatedField(f("repeated_cord" ), "225"); + + // Add a second one of each field. + message.AddRepeatedField(f("repeated_int32" ), 301 ); + message.AddRepeatedField(f("repeated_int64" ), 302L); + message.AddRepeatedField(f("repeated_uint32" ), 303 ); + message.AddRepeatedField(f("repeated_uint64" ), 304L); + message.AddRepeatedField(f("repeated_sint32" ), 305 ); + message.AddRepeatedField(f("repeated_sint64" ), 306L); + message.AddRepeatedField(f("repeated_fixed32" ), 307 ); + message.AddRepeatedField(f("repeated_fixed64" ), 308L); + message.AddRepeatedField(f("repeated_sfixed32"), 309 ); + message.AddRepeatedField(f("repeated_sfixed64"), 310L); + message.AddRepeatedField(f("repeated_float" ), 311F); + message.AddRepeatedField(f("repeated_double" ), 312D); + message.AddRepeatedField(f("repeated_bool" ), false); + message.AddRepeatedField(f("repeated_string" ), "315"); + message.AddRepeatedField(f("repeated_bytes" ), TestUtil.ToBytes("316")); + + message.AddRepeatedField(f("repeatedgroup"), + CreateBuilderForField(message, f("repeatedgroup")) + .SetField(repeatedGroupA, 317).Build()); + message.AddRepeatedField(f("repeated_nested_message"), + CreateBuilderForField(message, f("repeated_nested_message")) + .SetField(nestedB, 318).Build()); + message.AddRepeatedField(f("repeated_foreign_message"), + CreateBuilderForField(message, f("repeated_foreign_message")) + .SetField(foreignC, 319).Build()); + message.AddRepeatedField(f("repeated_import_message"), + CreateBuilderForField(message, f("repeated_import_message")) + .SetField(importD, 320).Build()); + + message.AddRepeatedField(f("repeated_nested_enum" ), nestedBaz); + message.AddRepeatedField(f("repeated_foreign_enum"), foreignBaz); + message.AddRepeatedField(f("repeated_import_enum" ), importBaz); + + message.AddRepeatedField(f("repeated_string_piece" ), "324"); + message.AddRepeatedField(f("repeated_cord" ), "325"); + + // ----------------------------------------------------------------- + + message[f("default_int32" )] = 401 ; + message[f("default_int64" )] = 402L; + message[f("default_uint32" )] = 403 ; + message[f("default_uint64" )] = 404L; + message[f("default_sint32" )] = 405 ; + message[f("default_sint64" )] = 406L; + message[f("default_fixed32" )] = 407 ; + message[f("default_fixed64" )] = 408L; + message[f("default_sfixed32")] = 409 ; + message[f("default_sfixed64")] = 410L; + message[f("default_float" )] = 411F; + message[f("default_double" )] = 412D; + message[f("default_bool" )] = false; + message[f("default_string" )] = "415"; + message[f("default_bytes" )] = TestUtil.ToBytes("416"); + + message[f("default_nested_enum" )] = nestedFoo; + message[f("default_foreign_enum")] = foreignFoo; + message[f("default_import_enum" )] = importFoo; + + message[f("default_string_piece" )] = "424"; + message[f("default_cord" )] = "425"; + } + + // ------------------------------------------------------------------- + + /// + /// Modify the repeated fields of the specified message to contain the + /// values expected by AssertRepeatedFieldsModified, using the IBuilder + /// reflection interface. + /// + internal void ModifyRepeatedFieldsViaReflection(IBuilder message) { + message[f("repeated_int32" ), 1] = 501 ; + message[f("repeated_int64" ), 1] = 502L; + message[f("repeated_uint32" ), 1] = 503 ; + message[f("repeated_uint64" ), 1] = 504L; + message[f("repeated_sint32" ), 1] = 505 ; + message[f("repeated_sint64" ), 1] = 506L; + message[f("repeated_fixed32" ), 1] = 507 ; + message[f("repeated_fixed64" ), 1] = 508L; + message[f("repeated_sfixed32"), 1] = 509 ; + message[f("repeated_sfixed64"), 1] = 510L; + message[f("repeated_float" ), 1] = 511F; + message[f("repeated_double" ), 1] = 512D; + message[f("repeated_bool" ), 1] = true; + message[f("repeated_string" ), 1] = "515"; + message.SetRepeatedField(f("repeated_bytes" ), 1, TestUtil.ToBytes("516")); + + message.SetRepeatedField(f("repeatedgroup"), 1, CreateBuilderForField(message, f("repeatedgroup")).SetField(repeatedGroupA, 517).Build()); + message.SetRepeatedField(f("repeated_nested_message"), 1, CreateBuilderForField(message, f("repeated_nested_message")).SetField(nestedB, 518).Build()); + message.SetRepeatedField(f("repeated_foreign_message"), 1, CreateBuilderForField(message, f("repeated_foreign_message")).SetField(foreignC, 519).Build()); + message.SetRepeatedField(f("repeated_import_message"), 1, CreateBuilderForField(message, f("repeated_import_message")).SetField(importD, 520).Build()); + + message[f("repeated_nested_enum" ), 1] = nestedFoo; + message[f("repeated_foreign_enum"), 1] = foreignFoo; + message[f("repeated_import_enum" ), 1] = importFoo; + + message[f("repeated_string_piece"), 1] = "524"; + message[f("repeated_cord"), 1] = "525"; + } + + // ------------------------------------------------------------------- + + /// + /// Asserts that all fields of the specified message are set to the values + /// assigned by SetAllFields, using the IMessage reflection interface. + /// + public void assertAllFieldsSetViaReflection(IMessage message) { + Assert.IsTrue(message.HasField(f("optional_int32" ))); + Assert.IsTrue(message.HasField(f("optional_int64" ))); + Assert.IsTrue(message.HasField(f("optional_uint32" ))); + Assert.IsTrue(message.HasField(f("optional_uint64" ))); + Assert.IsTrue(message.HasField(f("optional_sint32" ))); + Assert.IsTrue(message.HasField(f("optional_sint64" ))); + Assert.IsTrue(message.HasField(f("optional_fixed32" ))); + Assert.IsTrue(message.HasField(f("optional_fixed64" ))); + Assert.IsTrue(message.HasField(f("optional_sfixed32"))); + Assert.IsTrue(message.HasField(f("optional_sfixed64"))); + Assert.IsTrue(message.HasField(f("optional_float" ))); + Assert.IsTrue(message.HasField(f("optional_double" ))); + Assert.IsTrue(message.HasField(f("optional_bool" ))); + Assert.IsTrue(message.HasField(f("optional_string" ))); + Assert.IsTrue(message.HasField(f("optional_bytes" ))); + + Assert.IsTrue(message.HasField(f("optionalgroup" ))); + Assert.IsTrue(message.HasField(f("optional_nested_message" ))); + Assert.IsTrue(message.HasField(f("optional_foreign_message"))); + Assert.IsTrue(message.HasField(f("optional_import_message" ))); + + Assert.IsTrue(((IMessage)message[f("optionalgroup")]).HasField(groupA)); + Assert.IsTrue(((IMessage)message[f("optional_nested_message")]).HasField(nestedB)); + Assert.IsTrue(((IMessage)message[f("optional_foreign_message")]).HasField(foreignC)); + Assert.IsTrue(((IMessage)message[f("optional_import_message")]).HasField(importD)); + + Assert.IsTrue(message.HasField(f("optional_nested_enum" ))); + Assert.IsTrue(message.HasField(f("optional_foreign_enum"))); + Assert.IsTrue(message.HasField(f("optional_import_enum" ))); + + Assert.IsTrue(message.HasField(f("optional_string_piece"))); + Assert.IsTrue(message.HasField(f("optional_cord"))); + + Assert.AreEqual(101 , message[f("optional_int32" )]); + Assert.AreEqual(102L , message[f("optional_int64" )]); + Assert.AreEqual(103 , message[f("optional_uint32" )]); + Assert.AreEqual(104L , message[f("optional_uint64" )]); + Assert.AreEqual(105 , message[f("optional_sint32" )]); + Assert.AreEqual(106L , message[f("optional_sint64" )]); + Assert.AreEqual(107 , message[f("optional_fixed32" )]); + Assert.AreEqual(108L , message[f("optional_fixed64" )]); + Assert.AreEqual(109 , message[f("optional_sfixed32")]); + Assert.AreEqual(110L , message[f("optional_sfixed64")]); + Assert.AreEqual(111F , message[f("optional_float" )]); + Assert.AreEqual(112D , message[f("optional_double" )]); + Assert.AreEqual(true , message[f("optional_bool" )]); + Assert.AreEqual("115", message[f("optional_string" )]); + Assert.AreEqual(TestUtil.ToBytes("116"), message[f("optional_bytes")]); + + Assert.AreEqual(117,((IMessage)message[f("optionalgroup")])[groupA]); + Assert.AreEqual(118,((IMessage)message[f("optional_nested_message")])[nestedB]); + Assert.AreEqual(119,((IMessage)message[f("optional_foreign_message")])[foreignC]); + Assert.AreEqual(120,((IMessage)message[f("optional_import_message")])[importD]); + + Assert.AreEqual( nestedBaz, message[f("optional_nested_enum" )]); + Assert.AreEqual(foreignBaz, message[f("optional_foreign_enum")]); + Assert.AreEqual( importBaz, message[f("optional_import_enum" )]); + + Assert.AreEqual("124", message[f("optional_string_piece")]); + Assert.AreEqual("125", message[f("optional_cord")]); + + // ----------------------------------------------------------------- + + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_int32" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_int64" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_uint32" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_uint64" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_sint32" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_sint64" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_fixed32" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_fixed64" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_sfixed32"))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_sfixed64"))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_float" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_double" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_bool" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_string" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_bytes" ))); + + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeatedgroup" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_nested_message" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_foreign_message"))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_import_message" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_nested_enum" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_foreign_enum" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_import_enum" ))); + + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_string_piece"))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_cord"))); + + Assert.AreEqual(201 , message[f("repeated_int32" ), 0]); + Assert.AreEqual(202L , message[f("repeated_int64" ), 0]); + Assert.AreEqual(203 , message[f("repeated_uint32" ), 0]); + Assert.AreEqual(204L , message[f("repeated_uint64" ), 0]); + Assert.AreEqual(205 , message[f("repeated_sint32" ), 0]); + Assert.AreEqual(206L , message[f("repeated_sint64" ), 0]); + Assert.AreEqual(207 , message[f("repeated_fixed32" ), 0]); + Assert.AreEqual(208L , message[f("repeated_fixed64" ), 0]); + Assert.AreEqual(209 , message[f("repeated_sfixed32"), 0]); + Assert.AreEqual(210L , message[f("repeated_sfixed64"), 0]); + Assert.AreEqual(211F , message[f("repeated_float" ), 0]); + Assert.AreEqual(212D , message[f("repeated_double" ), 0]); + Assert.AreEqual(true , message[f("repeated_bool" ), 0]); + Assert.AreEqual("215", message[f("repeated_string" ), 0]); + Assert.AreEqual(TestUtil.ToBytes("216"), message[f("repeated_bytes"), 0]); + + Assert.AreEqual(217,((IMessage)message[f("repeatedgroup"), 0])[repeatedGroupA]); + Assert.AreEqual(218,((IMessage)message[f("repeated_nested_message"), 0])[nestedB]); + Assert.AreEqual(219,((IMessage)message[f("repeated_foreign_message"), 0])[foreignC]); + Assert.AreEqual(220,((IMessage)message[f("repeated_import_message"), 0])[importD]); + + Assert.AreEqual( nestedBar, message[f("repeated_nested_enum" ),0]); + Assert.AreEqual(foreignBar, message[f("repeated_foreign_enum"),0]); + Assert.AreEqual( importBar, message[f("repeated_import_enum" ),0]); + + Assert.AreEqual("224", message[f("repeated_string_piece"), 0]); + Assert.AreEqual("225", message[f("repeated_cord"), 0]); + + Assert.AreEqual(301 , message[f("repeated_int32" ), 1]); + Assert.AreEqual(302L , message[f("repeated_int64" ), 1]); + Assert.AreEqual(303 , message[f("repeated_uint32" ), 1]); + Assert.AreEqual(304L , message[f("repeated_uint64" ), 1]); + Assert.AreEqual(305 , message[f("repeated_sint32" ), 1]); + Assert.AreEqual(306L , message[f("repeated_sint64" ), 1]); + Assert.AreEqual(307 , message[f("repeated_fixed32" ), 1]); + Assert.AreEqual(308L , message[f("repeated_fixed64" ), 1]); + Assert.AreEqual(309 , message[f("repeated_sfixed32"), 1]); + Assert.AreEqual(310L , message[f("repeated_sfixed64"), 1]); + Assert.AreEqual(311F , message[f("repeated_float" ), 1]); + Assert.AreEqual(312D , message[f("repeated_double" ), 1]); + Assert.AreEqual(false, message[f("repeated_bool" ), 1]); + Assert.AreEqual("315", message[f("repeated_string" ), 1]); + Assert.AreEqual(TestUtil.ToBytes("316"), message[f("repeated_bytes"), 1]); + + Assert.AreEqual(317,((IMessage)message[f("repeatedgroup"), 1])[repeatedGroupA]); + Assert.AreEqual(318,((IMessage)message[f("repeated_nested_message"), 1])[nestedB]); + Assert.AreEqual(319, + ((IMessage)message[f("repeated_foreign_message"), 1]) + [foreignC]); + Assert.AreEqual(320, + ((IMessage)message[f("repeated_import_message"), 1]) + [importD]); + + Assert.AreEqual( nestedBaz, message[f("repeated_nested_enum" ),1]); + Assert.AreEqual(foreignBaz, message[f("repeated_foreign_enum"),1]); + Assert.AreEqual( importBaz, message[f("repeated_import_enum" ),1]); + + Assert.AreEqual("324", message[f("repeated_string_piece"), 1]); + Assert.AreEqual("325", message[f("repeated_cord"), 1]); + + // ----------------------------------------------------------------- + + Assert.IsTrue(message.HasField(f("default_int32" ))); + Assert.IsTrue(message.HasField(f("default_int64" ))); + Assert.IsTrue(message.HasField(f("default_uint32" ))); + Assert.IsTrue(message.HasField(f("default_uint64" ))); + Assert.IsTrue(message.HasField(f("default_sint32" ))); + Assert.IsTrue(message.HasField(f("default_sint64" ))); + Assert.IsTrue(message.HasField(f("default_fixed32" ))); + Assert.IsTrue(message.HasField(f("default_fixed64" ))); + Assert.IsTrue(message.HasField(f("default_sfixed32"))); + Assert.IsTrue(message.HasField(f("default_sfixed64"))); + Assert.IsTrue(message.HasField(f("default_float" ))); + Assert.IsTrue(message.HasField(f("default_double" ))); + Assert.IsTrue(message.HasField(f("default_bool" ))); + Assert.IsTrue(message.HasField(f("default_string" ))); + Assert.IsTrue(message.HasField(f("default_bytes" ))); + + Assert.IsTrue(message.HasField(f("default_nested_enum" ))); + Assert.IsTrue(message.HasField(f("default_foreign_enum"))); + Assert.IsTrue(message.HasField(f("default_import_enum" ))); + + Assert.IsTrue(message.HasField(f("default_string_piece"))); + Assert.IsTrue(message.HasField(f("default_cord"))); + + Assert.AreEqual(401 , message[f("default_int32" )]); + Assert.AreEqual(402L , message[f("default_int64" )]); + Assert.AreEqual(403 , message[f("default_uint32" )]); + Assert.AreEqual(404L , message[f("default_uint64" )]); + Assert.AreEqual(405 , message[f("default_sint32" )]); + Assert.AreEqual(406L , message[f("default_sint64" )]); + Assert.AreEqual(407 , message[f("default_fixed32" )]); + Assert.AreEqual(408L , message[f("default_fixed64" )]); + Assert.AreEqual(409 , message[f("default_sfixed32")]); + Assert.AreEqual(410L , message[f("default_sfixed64")]); + Assert.AreEqual(411F , message[f("default_float" )]); + Assert.AreEqual(412D , message[f("default_double" )]); + Assert.AreEqual(false, message[f("default_bool" )]); + Assert.AreEqual("415", message[f("default_string" )]); + Assert.AreEqual(TestUtil.ToBytes("416"), message[f("default_bytes")]); + + Assert.AreEqual( nestedFoo, message[f("default_nested_enum" )]); + Assert.AreEqual(foreignFoo, message[f("default_foreign_enum")]); + Assert.AreEqual( importFoo, message[f("default_import_enum" )]); + + Assert.AreEqual("424", message[f("default_string_piece")]); + Assert.AreEqual("425", message[f("default_cord")]); + } + + // ------------------------------------------------------------------- + + /** + * Assert (using {@code junit.framework.Assert}} that all fields of + * {@code message} are cleared, and that getting the fields returns their + * default values, using the {@link Message} reflection interface. + */ + public void assertClearViaReflection(IMessage message) { + // has_blah() should initially be false for all optional fields. + Assert.IsFalse(message.HasField(f("optional_int32" ))); + Assert.IsFalse(message.HasField(f("optional_int64" ))); + Assert.IsFalse(message.HasField(f("optional_uint32" ))); + Assert.IsFalse(message.HasField(f("optional_uint64" ))); + Assert.IsFalse(message.HasField(f("optional_sint32" ))); + Assert.IsFalse(message.HasField(f("optional_sint64" ))); + Assert.IsFalse(message.HasField(f("optional_fixed32" ))); + Assert.IsFalse(message.HasField(f("optional_fixed64" ))); + Assert.IsFalse(message.HasField(f("optional_sfixed32"))); + Assert.IsFalse(message.HasField(f("optional_sfixed64"))); + Assert.IsFalse(message.HasField(f("optional_float" ))); + Assert.IsFalse(message.HasField(f("optional_double" ))); + Assert.IsFalse(message.HasField(f("optional_bool" ))); + Assert.IsFalse(message.HasField(f("optional_string" ))); + Assert.IsFalse(message.HasField(f("optional_bytes" ))); + + Assert.IsFalse(message.HasField(f("optionalgroup" ))); + Assert.IsFalse(message.HasField(f("optional_nested_message" ))); + Assert.IsFalse(message.HasField(f("optional_foreign_message"))); + Assert.IsFalse(message.HasField(f("optional_import_message" ))); + + Assert.IsFalse(message.HasField(f("optional_nested_enum" ))); + Assert.IsFalse(message.HasField(f("optional_foreign_enum"))); + Assert.IsFalse(message.HasField(f("optional_import_enum" ))); + + Assert.IsFalse(message.HasField(f("optional_string_piece"))); + Assert.IsFalse(message.HasField(f("optional_cord"))); + + // Optional fields without defaults are set to zero or something like it. + Assert.AreEqual(0 , message[f("optional_int32" )]); + Assert.AreEqual(0L , message[f("optional_int64" )]); + Assert.AreEqual(0 , message[f("optional_uint32" )]); + Assert.AreEqual(0L , message[f("optional_uint64" )]); + Assert.AreEqual(0 , message[f("optional_sint32" )]); + Assert.AreEqual(0L , message[f("optional_sint64" )]); + Assert.AreEqual(0 , message[f("optional_fixed32" )]); + Assert.AreEqual(0L , message[f("optional_fixed64" )]); + Assert.AreEqual(0 , message[f("optional_sfixed32")]); + Assert.AreEqual(0L , message[f("optional_sfixed64")]); + Assert.AreEqual(0F , message[f("optional_float" )]); + Assert.AreEqual(0D , message[f("optional_double" )]); + Assert.AreEqual(false, message[f("optional_bool" )]); + Assert.AreEqual("" , message[f("optional_string" )]); + Assert.AreEqual(ByteString.Empty, message[f("optional_bytes")]); + + // Embedded messages should also be clear. + Assert.IsFalse( + ((IMessage)message[f("optionalgroup")]).HasField(groupA)); + Assert.IsFalse( + ((IMessage)message[f("optional_nested_message")]) + .HasField(nestedB)); + Assert.IsFalse( + ((IMessage)message[f("optional_foreign_message")]) + .HasField(foreignC)); + Assert.IsFalse( + ((IMessage)message[f("optional_import_message")]) + .HasField(importD)); + + Assert.AreEqual(0,((IMessage)message[f("optionalgroup")])[groupA]); + Assert.AreEqual(0,((IMessage)message[f("optional_nested_message")])[nestedB]); + Assert.AreEqual(0,((IMessage)message[f("optional_foreign_message")])[foreignC]); + Assert.AreEqual(0,((IMessage)message[f("optional_import_message")])[importD]); + + // Enums without defaults are set to the first value in the enum. + Assert.AreEqual( nestedFoo, message[f("optional_nested_enum" )]); + Assert.AreEqual(foreignFoo, message[f("optional_foreign_enum")]); + Assert.AreEqual( importFoo, message[f("optional_import_enum" )]); + + Assert.AreEqual("", message[f("optional_string_piece")]); + Assert.AreEqual("", message[f("optional_cord")]); + + // Repeated fields are empty. + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_int32" ))); + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_int64" ))); + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_uint32" ))); + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_uint64" ))); + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_sint32" ))); + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_sint64" ))); + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_fixed32" ))); + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_fixed64" ))); + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_sfixed32"))); + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_sfixed64"))); + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_float" ))); + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_double" ))); + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_bool" ))); + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_string" ))); + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_bytes" ))); + + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeatedgroup" ))); + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_nested_message" ))); + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_foreign_message"))); + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_import_message" ))); + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_nested_enum" ))); + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_foreign_enum" ))); + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_import_enum" ))); + + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_string_piece"))); + Assert.AreEqual(0, message.GetRepeatedFieldCount(f("repeated_cord"))); + + // has_blah() should also be false for all default fields. + Assert.IsFalse(message.HasField(f("default_int32" ))); + Assert.IsFalse(message.HasField(f("default_int64" ))); + Assert.IsFalse(message.HasField(f("default_uint32" ))); + Assert.IsFalse(message.HasField(f("default_uint64" ))); + Assert.IsFalse(message.HasField(f("default_sint32" ))); + Assert.IsFalse(message.HasField(f("default_sint64" ))); + Assert.IsFalse(message.HasField(f("default_fixed32" ))); + Assert.IsFalse(message.HasField(f("default_fixed64" ))); + Assert.IsFalse(message.HasField(f("default_sfixed32"))); + Assert.IsFalse(message.HasField(f("default_sfixed64"))); + Assert.IsFalse(message.HasField(f("default_float" ))); + Assert.IsFalse(message.HasField(f("default_double" ))); + Assert.IsFalse(message.HasField(f("default_bool" ))); + Assert.IsFalse(message.HasField(f("default_string" ))); + Assert.IsFalse(message.HasField(f("default_bytes" ))); + + Assert.IsFalse(message.HasField(f("default_nested_enum" ))); + Assert.IsFalse(message.HasField(f("default_foreign_enum"))); + Assert.IsFalse(message.HasField(f("default_import_enum" ))); + + Assert.IsFalse(message.HasField(f("default_string_piece" ))); + Assert.IsFalse(message.HasField(f("default_cord" ))); + + // Fields with defaults have their default values (duh). + Assert.AreEqual( 41 , message[f("default_int32" )]); + Assert.AreEqual( 42L , message[f("default_int64" )]); + Assert.AreEqual( 43 , message[f("default_uint32" )]); + Assert.AreEqual( 44L , message[f("default_uint64" )]); + Assert.AreEqual(-45 , message[f("default_sint32" )]); + Assert.AreEqual( 46L , message[f("default_sint64" )]); + Assert.AreEqual( 47 , message[f("default_fixed32" )]); + Assert.AreEqual( 48L , message[f("default_fixed64" )]); + Assert.AreEqual( 49 , message[f("default_sfixed32")]); + Assert.AreEqual(-50L , message[f("default_sfixed64")]); + Assert.AreEqual( 51.5F , message[f("default_float" )]); + Assert.AreEqual( 52e3D , message[f("default_double" )]); + Assert.AreEqual(true , message[f("default_bool" )]); + Assert.AreEqual("hello", message[f("default_string" )]); + Assert.AreEqual(TestUtil.ToBytes("world"), message[f("default_bytes")]); + + Assert.AreEqual( nestedBar, message[f("default_nested_enum" )]); + Assert.AreEqual(foreignBar, message[f("default_foreign_enum")]); + Assert.AreEqual( importBar, message[f("default_import_enum" )]); + + Assert.AreEqual("abc", message[f("default_string_piece")]); + Assert.AreEqual("123", message[f("default_cord")]); + } + + // --------------------------------------------------------------- + + internal void AssertRepeatedFieldsModifiedViaReflection(IMessage message) { + // ModifyRepeatedFields only sets the second repeated element of each + // field. In addition to verifying this, we also verify that the first + // element and size were *not* modified. + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_int32" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_int64" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_uint32" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_uint64" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_sint32" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_sint64" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_fixed32" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_fixed64" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_sfixed32"))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_sfixed64"))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_float" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_double" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_bool" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_string" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_bytes" ))); + + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeatedgroup" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_nested_message" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_foreign_message"))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_import_message" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_nested_enum" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_foreign_enum" ))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_import_enum" ))); + + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_string_piece"))); + Assert.AreEqual(2, message.GetRepeatedFieldCount(f("repeated_cord"))); + + Assert.AreEqual(201 , message[f("repeated_int32" ), 0]); + Assert.AreEqual(202L , message[f("repeated_int64" ), 0]); + Assert.AreEqual(203 , message[f("repeated_uint32" ), 0]); + Assert.AreEqual(204L , message[f("repeated_uint64" ), 0]); + Assert.AreEqual(205 , message[f("repeated_sint32" ), 0]); + Assert.AreEqual(206L , message[f("repeated_sint64" ), 0]); + Assert.AreEqual(207 , message[f("repeated_fixed32" ), 0]); + Assert.AreEqual(208L , message[f("repeated_fixed64" ), 0]); + Assert.AreEqual(209 , message[f("repeated_sfixed32"), 0]); + Assert.AreEqual(210L , message[f("repeated_sfixed64"), 0]); + Assert.AreEqual(211F , message[f("repeated_float" ), 0]); + Assert.AreEqual(212D , message[f("repeated_double" ), 0]); + Assert.AreEqual(true , message[f("repeated_bool" ), 0]); + Assert.AreEqual("215", message[f("repeated_string" ), 0]); + Assert.AreEqual(TestUtil.ToBytes("216"), message[f("repeated_bytes"), 0]); + + Assert.AreEqual(217,((IMessage)message[f("repeatedgroup"), 0])[repeatedGroupA]); + Assert.AreEqual(218,((IMessage)message[f("repeated_nested_message"), 0])[nestedB]); + Assert.AreEqual(219,((IMessage)message[f("repeated_foreign_message"), 0])[foreignC]); + Assert.AreEqual(220,((IMessage)message[f("repeated_import_message"), 0])[importD]); + + Assert.AreEqual( nestedBar, message[f("repeated_nested_enum" ),0]); + Assert.AreEqual(foreignBar, message[f("repeated_foreign_enum"),0]); + Assert.AreEqual( importBar, message[f("repeated_import_enum" ),0]); + + Assert.AreEqual("224", message[f("repeated_string_piece"), 0]); + Assert.AreEqual("225", message[f("repeated_cord"), 0]); + + Assert.AreEqual(501 , message[f("repeated_int32" ), 1]); + Assert.AreEqual(502L , message[f("repeated_int64" ), 1]); + Assert.AreEqual(503 , message[f("repeated_uint32" ), 1]); + Assert.AreEqual(504L , message[f("repeated_uint64" ), 1]); + Assert.AreEqual(505 , message[f("repeated_sint32" ), 1]); + Assert.AreEqual(506L , message[f("repeated_sint64" ), 1]); + Assert.AreEqual(507 , message[f("repeated_fixed32" ), 1]); + Assert.AreEqual(508L , message[f("repeated_fixed64" ), 1]); + Assert.AreEqual(509 , message[f("repeated_sfixed32"), 1]); + Assert.AreEqual(510L , message[f("repeated_sfixed64"), 1]); + Assert.AreEqual(511F , message[f("repeated_float" ), 1]); + Assert.AreEqual(512D , message[f("repeated_double" ), 1]); + Assert.AreEqual(true , message[f("repeated_bool" ), 1]); + Assert.AreEqual("515", message[f("repeated_string" ), 1]); + Assert.AreEqual(TestUtil.ToBytes("516"), message[f("repeated_bytes"), 1]); + + Assert.AreEqual(517,((IMessage)message[f("repeatedgroup"), 1])[repeatedGroupA]); + Assert.AreEqual(518,((IMessage)message[f("repeated_nested_message"), 1])[nestedB]); + Assert.AreEqual(519,((IMessage)message[f("repeated_foreign_message"), 1])[foreignC]); + Assert.AreEqual(520,((IMessage)message[f("repeated_import_message"), 1])[importD]); + + Assert.AreEqual( nestedFoo, message[f("repeated_nested_enum" ),1]); + Assert.AreEqual(foreignFoo, message[f("repeated_foreign_enum"),1]); + Assert.AreEqual( importFoo, message[f("repeated_import_enum" ),1]); + + Assert.AreEqual("524", message[f("repeated_string_piece"), 1]); + Assert.AreEqual("525", message[f("repeated_cord"), 1]); + } + } +} diff --git a/csharp/ProtocolBuffers.Test/TestProtos/UnitTestEmbedOptimizeForProtoFile.cs b/csharp/ProtocolBuffers.Test/TestProtos/UnitTestEmbedOptimizeForProtoFile.cs index f3228fe828..dd07da89a6 100644 --- a/csharp/ProtocolBuffers.Test/TestProtos/UnitTestEmbedOptimizeForProtoFile.cs +++ b/csharp/ProtocolBuffers.Test/TestProtos/UnitTestEmbedOptimizeForProtoFile.cs @@ -40,7 +40,6 @@ namespace Google.ProtocolBuffers.TestProtos { #endregion #region Extensions - /**/ #endregion #region Static variables @@ -219,6 +218,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestEmbedOptimizedForSize) { return MergeFrom((self::TestEmbedOptimizedForSize) other); diff --git a/csharp/ProtocolBuffers.Test/TestProtos/UnitTestImportProtoFile.cs b/csharp/ProtocolBuffers.Test/TestProtos/UnitTestImportProtoFile.cs index e0f3500088..c7e68878ef 100644 --- a/csharp/ProtocolBuffers.Test/TestProtos/UnitTestImportProtoFile.cs +++ b/csharp/ProtocolBuffers.Test/TestProtos/UnitTestImportProtoFile.cs @@ -34,7 +34,6 @@ namespace Google.ProtocolBuffers.TestProtos { #endregion #region Extensions - /**/ #endregion #region Static variables @@ -192,6 +191,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::ImportMessage) { return MergeFrom((self::ImportMessage) other); diff --git a/csharp/ProtocolBuffers.Test/TestProtos/UnitTestMessageSetProtoFile.cs b/csharp/ProtocolBuffers.Test/TestProtos/UnitTestMessageSetProtoFile.cs index 77b43d2aeb..4a8fc79446 100644 --- a/csharp/ProtocolBuffers.Test/TestProtos/UnitTestMessageSetProtoFile.cs +++ b/csharp/ProtocolBuffers.Test/TestProtos/UnitTestMessageSetProtoFile.cs @@ -55,7 +55,6 @@ namespace Google.ProtocolBuffers.TestProtos { #endregion #region Extensions - /**/ #endregion #region Static variables @@ -197,7 +196,7 @@ namespace Google.ProtocolBuffers.TestProtos { return (Builder) new Builder().MergeFrom(prototype); } - public sealed partial class Builder : pb::GeneratedBuilder.ExtendableBuilder { + public sealed partial class Builder : pb::ExtendableBuilder { // Construct using self::TestMessageSet.CreateBuilder() internal Builder() {} @@ -230,6 +229,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestMessageSet) { return MergeFrom((self::TestMessageSet) other); @@ -409,6 +412,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestMessageSetContainer) { return MergeFrom((self::TestMessageSetContainer) other); @@ -639,6 +646,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestMessageSetExtension1) { return MergeFrom((self::TestMessageSetExtension1) other); @@ -848,6 +859,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestMessageSetExtension2) { return MergeFrom((self::TestMessageSetExtension2) other); @@ -1091,6 +1106,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::RawMessageSet.Types.Item) { return MergeFrom((self::RawMessageSet.Types.Item) other); @@ -1309,6 +1328,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::RawMessageSet) { return MergeFrom((self::RawMessageSet) other); diff --git a/csharp/ProtocolBuffers.Test/TestProtos/UnitTestOptimizeForProtoFile.cs b/csharp/ProtocolBuffers.Test/TestProtos/UnitTestOptimizeForProtoFile.cs index ead26b3abd..f950d8f662 100644 --- a/csharp/ProtocolBuffers.Test/TestProtos/UnitTestOptimizeForProtoFile.cs +++ b/csharp/ProtocolBuffers.Test/TestProtos/UnitTestOptimizeForProtoFile.cs @@ -39,7 +39,6 @@ namespace Google.ProtocolBuffers.TestProtos { #endregion #region Extensions - /**/ #endregion #region Static variables @@ -146,7 +145,7 @@ namespace Google.ProtocolBuffers.TestProtos { return (Builder) new Builder().MergeFrom(prototype); } - public sealed partial class Builder : pb::GeneratedBuilder.ExtendableBuilder { + public sealed partial class Builder : pb::ExtendableBuilder { // Construct using self::TestOptimizedForSize.CreateBuilder() internal Builder() {} diff --git a/csharp/ProtocolBuffers.Test/TestProtos/UnitTestProtoFile.cs b/csharp/ProtocolBuffers.Test/TestProtos/UnitTestProtoFile.cs index 7868649f27..e5099ce896 100644 --- a/csharp/ProtocolBuffers.Test/TestProtos/UnitTestProtoFile.cs +++ b/csharp/ProtocolBuffers.Test/TestProtos/UnitTestProtoFile.cs @@ -632,7 +632,7 @@ namespace Google.ProtocolBuffers.TestProtos { #endregion #region Extensions - /*public static readonly pb::GeneratedExtensionBase OptionalInt32Extension = + public static readonly pb::GeneratedExtensionBase OptionalInt32Extension = pb::GeneratedSingleExtension.CreateInstance(Descriptor.Extensions[0]); public static readonly pb::GeneratedExtensionBase OptionalInt64Extension = pb::GeneratedSingleExtension.CreateInstance(Descriptor.Extensions[1]); @@ -681,76 +681,76 @@ namespace Google.ProtocolBuffers.TestProtos { public static readonly pb::GeneratedExtensionBase OptionalCordExtension = pb::GeneratedSingleExtension.CreateInstance(Descriptor.Extensions[23]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedInt32Extension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[24]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedInt64Extension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[25]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedUint32Extension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[26]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedUint64Extension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[27]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedSint32Extension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[28]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedSint64Extension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[29]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedFixed32Extension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[30]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedFixed64Extension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[31]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedSfixed32Extension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[32]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedSfixed64Extension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[33]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedFloatExtension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[34]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedDoubleExtension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[35]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedBoolExtension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[36]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedStringExtension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[37]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedBytesExtension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[38]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedGroupExtension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[39]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedNestedMessageExtension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[40]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedForeignMessageExtension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[41]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedImportMessageExtension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[42]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedNestedEnumExtension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[43]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedForeignEnumExtension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[44]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedImportEnumExtension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[45]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedStringPieceExtension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[46]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> RepeatedCordExtension = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[47]); public static readonly pb::GeneratedExtensionBase DefaultInt32Extension = pb::GeneratedSingleExtension.CreateInstance(Descriptor.Extensions[48]); @@ -796,7 +796,6 @@ namespace Google.ProtocolBuffers.TestProtos { pb::GeneratedSingleExtension.CreateInstance(Descriptor.Extensions[68]); public static readonly pb::GeneratedExtensionBase MyExtensionInt = pb::GeneratedSingleExtension.CreateInstance(Descriptor.Extensions[69]); - */ #endregion #region Static variables @@ -1195,6 +1194,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestAllTypes.Types.NestedMessage) { return MergeFrom((self::TestAllTypes.Types.NestedMessage) other); @@ -1397,6 +1400,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestAllTypes.Types.OptionalGroup) { return MergeFrom((self::TestAllTypes.Types.OptionalGroup) other); @@ -1599,6 +1606,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestAllTypes.Types.RepeatedGroup) { return MergeFrom((self::TestAllTypes.Types.RepeatedGroup) other); @@ -2949,6 +2960,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestAllTypes) { return MergeFrom((self::TestAllTypes) other); @@ -5485,6 +5500,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::ForeignMessage) { return MergeFrom((self::ForeignMessage) other); @@ -5642,7 +5661,7 @@ namespace Google.ProtocolBuffers.TestProtos { return (Builder) new Builder().MergeFrom(prototype); } - public sealed partial class Builder : pb::GeneratedBuilder.ExtendableBuilder { + public sealed partial class Builder : pb::ExtendableBuilder { // Construct using self::TestAllExtensions.CreateBuilder() internal Builder() {} @@ -5675,6 +5694,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestAllExtensions) { return MergeFrom((self::TestAllExtensions) other); @@ -5851,6 +5874,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::OptionalGroup_extension) { return MergeFrom((self::OptionalGroup_extension) other); @@ -6053,6 +6080,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::RepeatedGroup_extension) { return MergeFrom((self::RepeatedGroup_extension) other); @@ -6148,7 +6179,7 @@ namespace Google.ProtocolBuffers.TestProtos { public static readonly pb::GeneratedExtensionBase Single = pb::GeneratedSingleExtension.CreateInstance(Descriptor.Extensions[0]); public static readonly - pb::GeneratedExtensionBase> name = + pb::GeneratedExtensionBase> Multi = pb::GeneratedRepeatExtension.CreateInstance(Descriptor.Extensions[1]); } #endregion @@ -6780,6 +6811,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestRequired) { return MergeFrom((self::TestRequired) other); @@ -7857,6 +7892,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestRequiredForeign) { return MergeFrom((self::TestRequiredForeign) other); @@ -8162,6 +8201,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestForeignNested) { return MergeFrom((self::TestForeignNested) other); @@ -8369,6 +8412,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestEmptyMessage) { return MergeFrom((self::TestEmptyMessage) other); @@ -8500,7 +8547,7 @@ namespace Google.ProtocolBuffers.TestProtos { return (Builder) new Builder().MergeFrom(prototype); } - public sealed partial class Builder : pb::GeneratedBuilder.ExtendableBuilder { + public sealed partial class Builder : pb::ExtendableBuilder { // Construct using self::TestEmptyMessageWithExtensions.CreateBuilder() internal Builder() {} @@ -8533,6 +8580,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestEmptyMessageWithExtensions) { return MergeFrom((self::TestEmptyMessageWithExtensions) other); @@ -8725,6 +8776,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestReallyLargeTagNumber) { return MergeFrom((self::TestReallyLargeTagNumber) other); @@ -8969,6 +9024,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestRecursiveMessage) { return MergeFrom((self::TestRecursiveMessage) other); @@ -9218,6 +9277,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestMutualRecursionA) { return MergeFrom((self::TestMutualRecursionA) other); @@ -9457,6 +9520,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestMutualRecursionB) { return MergeFrom((self::TestMutualRecursionB) other); @@ -9729,6 +9796,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestDupFieldNumber.Types.Foo) { return MergeFrom((self::TestDupFieldNumber.Types.Foo) other); @@ -9931,6 +10002,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestDupFieldNumber.Types.Bar) { return MergeFrom((self::TestDupFieldNumber.Types.Bar) other); @@ -10147,6 +10222,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestDupFieldNumber) { return MergeFrom((self::TestDupFieldNumber) other); @@ -10491,6 +10570,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestNestedMessageHasBits.Types.NestedMessage) { return MergeFrom((self::TestNestedMessageHasBits.Types.NestedMessage) other); @@ -10748,6 +10831,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestNestedMessageHasBits) { return MergeFrom((self::TestNestedMessageHasBits) other); @@ -11171,6 +11258,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestCamelCaseFieldNames) { return MergeFrom((self::TestCamelCaseFieldNames) other); @@ -11810,7 +11901,7 @@ namespace Google.ProtocolBuffers.TestProtos { return (Builder) new Builder().MergeFrom(prototype); } - public sealed partial class Builder : pb::GeneratedBuilder.ExtendableBuilder { + public sealed partial class Builder : pb::ExtendableBuilder { // Construct using self::TestFieldOrderings.CreateBuilder() internal Builder() {} @@ -11843,6 +11934,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestFieldOrderings) { return MergeFrom((self::TestFieldOrderings) other); @@ -12177,6 +12272,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::TestExtremeDefaultValues) { return MergeFrom((self::TestExtremeDefaultValues) other); @@ -12493,6 +12592,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::FooRequest) { return MergeFrom((self::FooRequest) other); @@ -12653,6 +12756,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::FooResponse) { return MergeFrom((self::FooResponse) other); @@ -12813,6 +12920,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::BarRequest) { return MergeFrom((self::BarRequest) other); @@ -12973,6 +13084,10 @@ namespace Google.ProtocolBuffers.TestProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::BarResponse) { return MergeFrom((self::BarResponse) other); diff --git a/csharp/ProtocolBuffers.Test/TestUtil.cs b/csharp/ProtocolBuffers.Test/TestUtil.cs index 190e8f7593..2cc1b5a2fc 100644 --- a/csharp/ProtocolBuffers.Test/TestUtil.cs +++ b/csharp/ProtocolBuffers.Test/TestUtil.cs @@ -8,9 +8,10 @@ using NUnit.Framework; namespace Google.ProtocolBuffers { internal static class TestUtil { - private static DirectoryInfo testDataDirectory; + private static string testDataDirectory; + private static ByteString goldenMessage = null; - internal static DirectoryInfo TestDataDirectory { + internal static string TestDataDirectory { get { if (testDataDirectory != null) { return testDataDirectory; @@ -21,7 +22,7 @@ namespace Google.ProtocolBuffers { while (ancestor != null) { string candidate = Path.Combine(ancestor.FullName, "src/google/protobuf"); if (Directory.Exists(candidate)) { - testDataDirectory = new DirectoryInfo(candidate); + testDataDirectory = Path.Combine(ancestor.FullName, "src/google/protobuf/testdata"); return testDataDirectory; } ancestor = ancestor.Parent; @@ -31,10 +32,113 @@ namespace Google.ProtocolBuffers { } } + internal static ByteString GoldenMessage { + get { + if (goldenMessage == null) { + goldenMessage = ReadBytesFromFile("golden_message"); + } + return goldenMessage; + } + } + + /// + /// Creates an unmodifiable ExtensionRegistry containing all the extensions + /// of TestAllExtensions. + /// + /// + internal static ExtensionRegistry CreateExtensionRegistry() { + ExtensionRegistry registry = ExtensionRegistry.CreateInstance(); + RegisterAllExtensions(registry); + return registry.AsReadOnly(); + } + + /// + /// Registers all of the extensions in TestAllExtensions with the given + /// ExtensionRegistry. + /// + internal static void RegisterAllExtensions(ExtensionRegistry registry) { + registry.Add(UnitTestProtoFile.OptionalInt32Extension); + registry.Add(UnitTestProtoFile.OptionalInt64Extension); + registry.Add(UnitTestProtoFile.OptionalUint32Extension); + registry.Add(UnitTestProtoFile.OptionalUint64Extension); + registry.Add(UnitTestProtoFile.OptionalSint32Extension); + registry.Add(UnitTestProtoFile.OptionalSint64Extension); + registry.Add(UnitTestProtoFile.OptionalFixed32Extension); + registry.Add(UnitTestProtoFile.OptionalFixed64Extension); + registry.Add(UnitTestProtoFile.OptionalSfixed32Extension); + registry.Add(UnitTestProtoFile.OptionalSfixed64Extension); + registry.Add(UnitTestProtoFile.OptionalFloatExtension); + registry.Add(UnitTestProtoFile.OptionalDoubleExtension); + registry.Add(UnitTestProtoFile.OptionalBoolExtension); + registry.Add(UnitTestProtoFile.OptionalStringExtension); + registry.Add(UnitTestProtoFile.OptionalBytesExtension); + registry.Add(UnitTestProtoFile.OptionalGroupExtension); + registry.Add(UnitTestProtoFile.OptionalNestedMessageExtension); + registry.Add(UnitTestProtoFile.OptionalForeignMessageExtension); + registry.Add(UnitTestProtoFile.OptionalImportMessageExtension); + registry.Add(UnitTestProtoFile.OptionalNestedEnumExtension); + registry.Add(UnitTestProtoFile.OptionalForeignEnumExtension); + registry.Add(UnitTestProtoFile.OptionalImportEnumExtension); + registry.Add(UnitTestProtoFile.OptionalStringPieceExtension); + registry.Add(UnitTestProtoFile.OptionalCordExtension); + + registry.Add(UnitTestProtoFile.RepeatedInt32Extension); + registry.Add(UnitTestProtoFile.RepeatedInt64Extension); + registry.Add(UnitTestProtoFile.RepeatedUint32Extension); + registry.Add(UnitTestProtoFile.RepeatedUint64Extension); + registry.Add(UnitTestProtoFile.RepeatedSint32Extension); + registry.Add(UnitTestProtoFile.RepeatedSint64Extension); + registry.Add(UnitTestProtoFile.RepeatedFixed32Extension); + registry.Add(UnitTestProtoFile.RepeatedFixed64Extension); + registry.Add(UnitTestProtoFile.RepeatedSfixed32Extension); + registry.Add(UnitTestProtoFile.RepeatedSfixed64Extension); + registry.Add(UnitTestProtoFile.RepeatedFloatExtension); + registry.Add(UnitTestProtoFile.RepeatedDoubleExtension); + registry.Add(UnitTestProtoFile.RepeatedBoolExtension); + registry.Add(UnitTestProtoFile.RepeatedStringExtension); + registry.Add(UnitTestProtoFile.RepeatedBytesExtension); + registry.Add(UnitTestProtoFile.RepeatedGroupExtension); + registry.Add(UnitTestProtoFile.RepeatedNestedMessageExtension); + registry.Add(UnitTestProtoFile.RepeatedForeignMessageExtension); + registry.Add(UnitTestProtoFile.RepeatedImportMessageExtension); + registry.Add(UnitTestProtoFile.RepeatedNestedEnumExtension); + registry.Add(UnitTestProtoFile.RepeatedForeignEnumExtension); + registry.Add(UnitTestProtoFile.RepeatedImportEnumExtension); + registry.Add(UnitTestProtoFile.RepeatedStringPieceExtension); + registry.Add(UnitTestProtoFile.RepeatedCordExtension); + + registry.Add(UnitTestProtoFile.DefaultInt32Extension); + registry.Add(UnitTestProtoFile.DefaultInt64Extension); + registry.Add(UnitTestProtoFile.DefaultUint32Extension); + registry.Add(UnitTestProtoFile.DefaultUint64Extension); + registry.Add(UnitTestProtoFile.DefaultSint32Extension); + registry.Add(UnitTestProtoFile.DefaultSint64Extension); + registry.Add(UnitTestProtoFile.DefaultFixed32Extension); + registry.Add(UnitTestProtoFile.DefaultFixed64Extension); + registry.Add(UnitTestProtoFile.DefaultSfixed32Extension); + registry.Add(UnitTestProtoFile.DefaultSfixed64Extension); + registry.Add(UnitTestProtoFile.DefaultFloatExtension); + registry.Add(UnitTestProtoFile.DefaultDoubleExtension); + registry.Add(UnitTestProtoFile.DefaultBoolExtension); + registry.Add(UnitTestProtoFile.DefaultStringExtension); + registry.Add(UnitTestProtoFile.DefaultBytesExtension); + registry.Add(UnitTestProtoFile.DefaultNestedEnumExtension); + registry.Add(UnitTestProtoFile.DefaultForeignEnumExtension); + registry.Add(UnitTestProtoFile.DefaultImportEnumExtension); + registry.Add(UnitTestProtoFile.DefaultStringPieceExtension); + registry.Add(UnitTestProtoFile.DefaultCordExtension); + } + + + internal static ByteString ReadBytesFromFile(String filename) { + byte[] data = File.ReadAllBytes(Path.Combine(TestDataDirectory, filename)); + return ByteString.CopyFrom(data); + } + /// /// Helper to convert a String to ByteString. /// - private static ByteString ToBytes(String str) { + internal static ByteString ToBytes(String str) { return ByteString.CopyFrom(Encoding.UTF8.GetBytes(str)); } @@ -362,5 +466,275 @@ namespace Google.ProtocolBuffers { Assert.AreEqual("425", message.DefaultCord); } + internal static void AssertClear(TestAllTypes message) { + // HasBlah() should initially be false for all optional fields. + Assert.IsFalse(message.HasOptionalInt32); + Assert.IsFalse(message.HasOptionalInt64); + Assert.IsFalse(message.HasOptionalUint32); + Assert.IsFalse(message.HasOptionalUint64); + Assert.IsFalse(message.HasOptionalSint32); + Assert.IsFalse(message.HasOptionalSint64); + Assert.IsFalse(message.HasOptionalFixed32); + Assert.IsFalse(message.HasOptionalFixed64); + Assert.IsFalse(message.HasOptionalSfixed32); + Assert.IsFalse(message.HasOptionalSfixed64); + Assert.IsFalse(message.HasOptionalFloat); + Assert.IsFalse(message.HasOptionalDouble); + Assert.IsFalse(message.HasOptionalBool); + Assert.IsFalse(message.HasOptionalString); + Assert.IsFalse(message.HasOptionalBytes); + + Assert.IsFalse(message.HasOptionalGroup); + Assert.IsFalse(message.HasOptionalNestedMessage); + Assert.IsFalse(message.HasOptionalForeignMessage); + Assert.IsFalse(message.HasOptionalImportMessage); + + Assert.IsFalse(message.HasOptionalNestedEnum); + Assert.IsFalse(message.HasOptionalForeignEnum); + Assert.IsFalse(message.HasOptionalImportEnum); + + Assert.IsFalse(message.HasOptionalStringPiece); + Assert.IsFalse(message.HasOptionalCord); + + // Optional fields without defaults are set to zero or something like it. + Assert.AreEqual(0, message.OptionalInt32); + Assert.AreEqual(0, message.OptionalInt64); + Assert.AreEqual(0, message.OptionalUint32); + Assert.AreEqual(0, message.OptionalUint64); + Assert.AreEqual(0, message.OptionalSint32); + Assert.AreEqual(0, message.OptionalSint64); + Assert.AreEqual(0, message.OptionalFixed32); + Assert.AreEqual(0, message.OptionalFixed64); + Assert.AreEqual(0, message.OptionalSfixed32); + Assert.AreEqual(0, message.OptionalSfixed64); + Assert.AreEqual(0, message.OptionalFloat); + Assert.AreEqual(0, message.OptionalDouble); + Assert.AreEqual(false, message.OptionalBool); + Assert.AreEqual("", message.OptionalString); + Assert.AreEqual(ByteString.Empty, message.OptionalBytes); + + // Embedded messages should also be clear. + Assert.IsFalse(message.OptionalGroup.HasA); + Assert.IsFalse(message.OptionalNestedMessage.HasBb); + Assert.IsFalse(message.OptionalForeignMessage.HasC); + Assert.IsFalse(message.OptionalImportMessage.HasD); + + Assert.AreEqual(0, message.OptionalGroup.A); + Assert.AreEqual(0, message.OptionalNestedMessage.Bb); + Assert.AreEqual(0, message.OptionalForeignMessage.C); + Assert.AreEqual(0, message.OptionalImportMessage.D); + + // Enums without defaults are set to the first value in the enum. + Assert.AreEqual(TestAllTypes.Types.NestedEnum.FOO, message.OptionalNestedEnum); + Assert.AreEqual(ForeignEnum.FOREIGN_FOO, message.OptionalForeignEnum); + Assert.AreEqual(ImportEnum.IMPORT_FOO, message.OptionalImportEnum); + + Assert.AreEqual("", message.OptionalStringPiece); + Assert.AreEqual("", message.OptionalCord); + + // Repeated fields are empty. + Assert.AreEqual(0, message.RepeatedInt32Count); + Assert.AreEqual(0, message.RepeatedInt64Count); + Assert.AreEqual(0, message.RepeatedUint32Count); + Assert.AreEqual(0, message.RepeatedUint64Count); + Assert.AreEqual(0, message.RepeatedSint32Count); + Assert.AreEqual(0, message.RepeatedSint64Count); + Assert.AreEqual(0, message.RepeatedFixed32Count); + Assert.AreEqual(0, message.RepeatedFixed64Count); + Assert.AreEqual(0, message.RepeatedSfixed32Count); + Assert.AreEqual(0, message.RepeatedSfixed64Count); + Assert.AreEqual(0, message.RepeatedFloatCount); + Assert.AreEqual(0, message.RepeatedDoubleCount); + Assert.AreEqual(0, message.RepeatedBoolCount); + Assert.AreEqual(0, message.RepeatedStringCount); + Assert.AreEqual(0, message.RepeatedBytesCount); + + Assert.AreEqual(0, message.RepeatedGroupCount); + Assert.AreEqual(0, message.RepeatedNestedMessageCount); + Assert.AreEqual(0, message.RepeatedForeignMessageCount); + Assert.AreEqual(0, message.RepeatedImportMessageCount); + Assert.AreEqual(0, message.RepeatedNestedEnumCount); + Assert.AreEqual(0, message.RepeatedForeignEnumCount); + Assert.AreEqual(0, message.RepeatedImportEnumCount); + + Assert.AreEqual(0, message.RepeatedStringPieceCount); + Assert.AreEqual(0, message.RepeatedCordCount); + + // HasBlah() should also be false for all default fields. + Assert.IsFalse(message.HasDefaultInt32); + Assert.IsFalse(message.HasDefaultInt64); + Assert.IsFalse(message.HasDefaultUint32); + Assert.IsFalse(message.HasDefaultUint64); + Assert.IsFalse(message.HasDefaultSint32); + Assert.IsFalse(message.HasDefaultSint64); + Assert.IsFalse(message.HasDefaultFixed32); + Assert.IsFalse(message.HasDefaultFixed64); + Assert.IsFalse(message.HasDefaultSfixed32); + Assert.IsFalse(message.HasDefaultSfixed64); + Assert.IsFalse(message.HasDefaultFloat); + Assert.IsFalse(message.HasDefaultDouble); + Assert.IsFalse(message.HasDefaultBool); + Assert.IsFalse(message.HasDefaultString); + Assert.IsFalse(message.HasDefaultBytes); + + Assert.IsFalse(message.HasDefaultNestedEnum); + Assert.IsFalse(message.HasDefaultForeignEnum); + Assert.IsFalse(message.HasDefaultImportEnum); + + Assert.IsFalse(message.HasDefaultStringPiece); + Assert.IsFalse(message.HasDefaultCord); + + // Fields with defaults have their default values (duh). + Assert.AreEqual(41, message.DefaultInt32); + Assert.AreEqual(42, message.DefaultInt64); + Assert.AreEqual(43, message.DefaultUint32); + Assert.AreEqual(44, message.DefaultUint64); + Assert.AreEqual(-45, message.DefaultSint32); + Assert.AreEqual(46, message.DefaultSint64); + Assert.AreEqual(47, message.DefaultFixed32); + Assert.AreEqual(48, message.DefaultFixed64); + Assert.AreEqual(49, message.DefaultSfixed32); + Assert.AreEqual(-50, message.DefaultSfixed64); + Assert.AreEqual(51.5, message.DefaultFloat, 0.0); + Assert.AreEqual(52e3, message.DefaultDouble, 0.0); + Assert.AreEqual(true, message.DefaultBool); + Assert.AreEqual("hello", message.DefaultString); + Assert.AreEqual(ToBytes("world"), message.DefaultBytes); + + Assert.AreEqual(TestAllTypes.Types.NestedEnum.BAR, message.DefaultNestedEnum); + Assert.AreEqual(ForeignEnum.FOREIGN_BAR, message.DefaultForeignEnum); + Assert.AreEqual(ImportEnum.IMPORT_BAR, message.DefaultImportEnum); + + Assert.AreEqual("abc", message.DefaultStringPiece); + Assert.AreEqual("123", message.DefaultCord); + } + + /// + /// Get a TestAllExtensions with all fields set as they would be by + /// SetAllExtensions(TestAllExtensions.Builder). + /// + internal static TestAllExtensions GetAllExtensionsSet() { + TestAllExtensions.Builder builder = TestAllExtensions.CreateBuilder(); + SetAllExtensions(builder); + return builder.Build(); + } + + /// + /// Sets every field of the specified builder to the values expected by + /// AssertAllExtensionsSet. + /// + internal static void SetAllExtensions(TestAllExtensions.Builder message) { + message.SetExtension(UnitTestProtoFile.OptionalInt32Extension, 101); + message.SetExtension(UnitTestProtoFile.OptionalInt64Extension, 102L); + message.SetExtension(UnitTestProtoFile.OptionalUint32Extension, 103U); + message.SetExtension(UnitTestProtoFile.OptionalUint64Extension, 104UL); + message.SetExtension(UnitTestProtoFile.OptionalSint32Extension, 105); + message.SetExtension(UnitTestProtoFile.OptionalSint64Extension, 106L); + message.SetExtension(UnitTestProtoFile.OptionalFixed32Extension, 107U); + message.SetExtension(UnitTestProtoFile.OptionalFixed64Extension, 108UL); + message.SetExtension(UnitTestProtoFile.OptionalSfixed32Extension, 109); + message.SetExtension(UnitTestProtoFile.OptionalSfixed64Extension, 110L); + message.SetExtension(UnitTestProtoFile.OptionalFloatExtension, 111F); + message.SetExtension(UnitTestProtoFile.OptionalDoubleExtension, 112D); + message.SetExtension(UnitTestProtoFile.OptionalBoolExtension, true); + message.SetExtension(UnitTestProtoFile.OptionalStringExtension, "115"); + message.SetExtension(UnitTestProtoFile.OptionalBytesExtension, ToBytes("116")); + + message.SetExtension(UnitTestProtoFile.OptionalGroupExtension, OptionalGroup_extension.CreateBuilder().SetA(117).Build()); + message.SetExtension(UnitTestProtoFile.OptionalNestedMessageExtension, TestAllTypes.Types.NestedMessage.CreateBuilder().SetBb(118).Build()); + message.SetExtension(UnitTestProtoFile.OptionalForeignMessageExtension, ForeignMessage.CreateBuilder().SetC(119).Build()); + message.SetExtension(UnitTestProtoFile.OptionalImportMessageExtension, ImportMessage.CreateBuilder().SetD(120).Build()); + + message.SetExtension(UnitTestProtoFile.OptionalNestedEnumExtension, TestAllTypes.Types.NestedEnum.BAZ); + message.SetExtension(UnitTestProtoFile.OptionalForeignEnumExtension, ForeignEnum.FOREIGN_BAZ); + message.SetExtension(UnitTestProtoFile.OptionalImportEnumExtension, ImportEnum.IMPORT_BAZ); + + message.SetExtension(UnitTestProtoFile.OptionalStringPieceExtension, "124"); + message.SetExtension(UnitTestProtoFile.OptionalCordExtension, "125"); + + // ----------------------------------------------------------------- + + message.AddExtension(UnitTestProtoFile.RepeatedInt32Extension, 201); + message.AddExtension(UnitTestProtoFile.RepeatedInt64Extension, 202L); + message.AddExtension(UnitTestProtoFile.RepeatedUint32Extension, 203U); + message.AddExtension(UnitTestProtoFile.RepeatedUint64Extension, 204UL); + message.AddExtension(UnitTestProtoFile.RepeatedSint32Extension, 205); + message.AddExtension(UnitTestProtoFile.RepeatedSint64Extension, 206L); + message.AddExtension(UnitTestProtoFile.RepeatedFixed32Extension, 207U); + message.AddExtension(UnitTestProtoFile.RepeatedFixed64Extension, 208UL); + message.AddExtension(UnitTestProtoFile.RepeatedSfixed32Extension, 209); + message.AddExtension(UnitTestProtoFile.RepeatedSfixed64Extension, 210L); + message.AddExtension(UnitTestProtoFile.RepeatedFloatExtension, 211F); + message.AddExtension(UnitTestProtoFile.RepeatedDoubleExtension, 212D); + message.AddExtension(UnitTestProtoFile.RepeatedBoolExtension, true); + message.AddExtension(UnitTestProtoFile.RepeatedStringExtension, "215"); + message.AddExtension(UnitTestProtoFile.RepeatedBytesExtension, ToBytes("216")); + + message.AddExtension(UnitTestProtoFile.RepeatedGroupExtension, RepeatedGroup_extension.CreateBuilder().SetA(217).Build()); + message.AddExtension(UnitTestProtoFile.RepeatedNestedMessageExtension, TestAllTypes.Types.NestedMessage.CreateBuilder().SetBb(218).Build()); + message.AddExtension(UnitTestProtoFile.RepeatedForeignMessageExtension, ForeignMessage.CreateBuilder().SetC(219).Build()); + message.AddExtension(UnitTestProtoFile.RepeatedImportMessageExtension, ImportMessage.CreateBuilder().SetD(220).Build()); + + message.AddExtension(UnitTestProtoFile.RepeatedNestedEnumExtension, TestAllTypes.Types.NestedEnum.BAR); + message.AddExtension(UnitTestProtoFile.RepeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAR); + message.AddExtension(UnitTestProtoFile.RepeatedImportEnumExtension, ImportEnum.IMPORT_BAR); + + message.AddExtension(UnitTestProtoFile.RepeatedStringPieceExtension, "224"); + message.AddExtension(UnitTestProtoFile.RepeatedCordExtension, "225"); + + // Add a second one of each field. + message.AddExtension(UnitTestProtoFile.RepeatedInt32Extension, 301); + message.AddExtension(UnitTestProtoFile.RepeatedInt64Extension, 302L); + message.AddExtension(UnitTestProtoFile.RepeatedUint32Extension, 303U); + message.AddExtension(UnitTestProtoFile.RepeatedUint64Extension, 304UL); + message.AddExtension(UnitTestProtoFile.RepeatedSint32Extension, 305); + message.AddExtension(UnitTestProtoFile.RepeatedSint64Extension, 306L); + message.AddExtension(UnitTestProtoFile.RepeatedFixed32Extension, 307U); + message.AddExtension(UnitTestProtoFile.RepeatedFixed64Extension, 308UL); + message.AddExtension(UnitTestProtoFile.RepeatedSfixed32Extension, 309); + message.AddExtension(UnitTestProtoFile.RepeatedSfixed64Extension, 310L); + message.AddExtension(UnitTestProtoFile.RepeatedFloatExtension, 311F); + message.AddExtension(UnitTestProtoFile.RepeatedDoubleExtension, 312D); + message.AddExtension(UnitTestProtoFile.RepeatedBoolExtension, false); + message.AddExtension(UnitTestProtoFile.RepeatedStringExtension, "315"); + message.AddExtension(UnitTestProtoFile.RepeatedBytesExtension, ToBytes("316")); + + message.AddExtension(UnitTestProtoFile.RepeatedGroupExtension, RepeatedGroup_extension.CreateBuilder().SetA(317).Build()); + message.AddExtension(UnitTestProtoFile.RepeatedNestedMessageExtension, TestAllTypes.Types.NestedMessage.CreateBuilder().SetBb(318).Build()); + message.AddExtension(UnitTestProtoFile.RepeatedForeignMessageExtension, ForeignMessage.CreateBuilder().SetC(319).Build()); + message.AddExtension(UnitTestProtoFile.RepeatedImportMessageExtension, ImportMessage.CreateBuilder().SetD(320).Build()); + + message.AddExtension(UnitTestProtoFile.RepeatedNestedEnumExtension, TestAllTypes.Types.NestedEnum.BAZ); + message.AddExtension(UnitTestProtoFile.RepeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAZ); + message.AddExtension(UnitTestProtoFile.RepeatedImportEnumExtension, ImportEnum.IMPORT_BAZ); + + message.AddExtension(UnitTestProtoFile.RepeatedStringPieceExtension, "324"); + message.AddExtension(UnitTestProtoFile.RepeatedCordExtension, "325"); + + // ----------------------------------------------------------------- + + message.SetExtension(UnitTestProtoFile.DefaultInt32Extension, 401); + message.SetExtension(UnitTestProtoFile.DefaultInt64Extension, 402L); + message.SetExtension(UnitTestProtoFile.DefaultUint32Extension, 403U); + message.SetExtension(UnitTestProtoFile.DefaultUint64Extension, 404UL); + message.SetExtension(UnitTestProtoFile.DefaultSint32Extension, 405); + message.SetExtension(UnitTestProtoFile.DefaultSint64Extension, 406L); + message.SetExtension(UnitTestProtoFile.DefaultFixed32Extension, 407U); + message.SetExtension(UnitTestProtoFile.DefaultFixed64Extension, 408UL); + message.SetExtension(UnitTestProtoFile.DefaultSfixed32Extension, 409); + message.SetExtension(UnitTestProtoFile.DefaultSfixed64Extension, 410L); + message.SetExtension(UnitTestProtoFile.DefaultFloatExtension, 411F); + message.SetExtension(UnitTestProtoFile.DefaultDoubleExtension, 412D); + message.SetExtension(UnitTestProtoFile.DefaultBoolExtension, false); + message.SetExtension(UnitTestProtoFile.DefaultStringExtension, "415"); + message.SetExtension(UnitTestProtoFile.DefaultBytesExtension, ToBytes("416")); + + message.SetExtension(UnitTestProtoFile.DefaultNestedEnumExtension, TestAllTypes.Types.NestedEnum.FOO); + message.SetExtension(UnitTestProtoFile.DefaultForeignEnumExtension, ForeignEnum.FOREIGN_FOO); + message.SetExtension(UnitTestProtoFile.DefaultImportEnumExtension, ImportEnum.IMPORT_FOO); + + message.SetExtension(UnitTestProtoFile.DefaultStringPieceExtension, "424"); + message.SetExtension(UnitTestProtoFile.DefaultCordExtension, "425"); + } } } diff --git a/csharp/ProtocolBuffers/AbstractBuilder.cs b/csharp/ProtocolBuffers/AbstractBuilder.cs index 256975e9ed..d65c091109 100644 --- a/csharp/ProtocolBuffers/AbstractBuilder.cs +++ b/csharp/ProtocolBuffers/AbstractBuilder.cs @@ -8,6 +8,7 @@ using System.IO; namespace Google.ProtocolBuffers { /// /// Implementation of the non-generic IMessage interface as far as possible. + /// TODO(jonskeet): Make this generic, to avoid so much casting in DynamicMessage. /// public abstract class AbstractBuilder : IBuilder { #region Unimplemented members of IBuilder @@ -57,7 +58,7 @@ namespace Google.ProtocolBuffers { } #endregion - public IBuilder Clear() { + public virtual IBuilder Clear() { foreach(FieldDescriptor field in AllFields.Keys) { ClearFieldImpl(field); } @@ -168,5 +169,15 @@ namespace Google.ProtocolBuffers { } public abstract UnknownFieldSet UnknownFields { get; set; } + + public IBuilder SetField(FieldDescriptor field, object value) { + this[field] = value; + return this; + } + + public IBuilder SetRepeatedField(FieldDescriptor field, int index, object value) { + this[field, index] = value; + return this; + } } } diff --git a/csharp/ProtocolBuffers/AbstractMessage.cs b/csharp/ProtocolBuffers/AbstractMessage.cs index 9f855a455e..6dfcc46d37 100644 --- a/csharp/ProtocolBuffers/AbstractMessage.cs +++ b/csharp/ProtocolBuffers/AbstractMessage.cs @@ -16,6 +16,7 @@ using System.Collections; using System.Collections.Generic; using System.IO; +using Google.ProtocolBuffers.Collections; using Google.ProtocolBuffers.Descriptors; namespace Google.ProtocolBuffers { @@ -171,15 +172,13 @@ namespace Google.ProtocolBuffers { if (otherMessage == null || otherMessage.DescriptorForType != DescriptorForType) { return false; } - // TODO(jonskeet): Check that dictionaries support equality appropriately - // (I suspect they don't!) - return AllFields.Equals(otherMessage.AllFields); + return Dictionaries.Equals(AllFields, otherMessage.AllFields); } public override int GetHashCode() { int hash = 41; hash = (19 * hash) + DescriptorForType.GetHashCode(); - hash = (53 * hash) + AllFields.GetHashCode(); + hash = (53 * hash) + Dictionaries.GetHashCode(AllFields); return hash; } } diff --git a/csharp/ProtocolBuffers/Collections/Dictionaries.cs b/csharp/ProtocolBuffers/Collections/Dictionaries.cs index fb0ebdd2a1..640b65977f 100644 --- a/csharp/ProtocolBuffers/Collections/Dictionaries.cs +++ b/csharp/ProtocolBuffers/Collections/Dictionaries.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Text; +using System.Collections; +using Google.ProtocolBuffers.Descriptors; namespace Google.ProtocolBuffers.Collections { @@ -9,8 +11,85 @@ namespace Google.ProtocolBuffers.Collections { /// in the generic class. /// public static class Dictionaries { + + /// + /// Compares two dictionaries for equality. Each value is compared with equality using Equals + /// for non-IEnumerable implementations, and using EnumerableEquals otherwise. + /// TODO(jonskeet): This is clearly pretty slow, and involves lots of boxing/unboxing... + /// + public static bool Equals(IDictionary left, IDictionary right) { + if (left.Count != right.Count) { + return false; + } + foreach (KeyValuePair leftEntry in left) + { + TValue rightValue; + if (!right.TryGetValue(leftEntry.Key, out rightValue)) { + return false; + } + + IEnumerable leftEnumerable = leftEntry.Value as IEnumerable; + IEnumerable rightEnumerable = rightValue as IEnumerable; + if (leftEnumerable == null || rightEnumerable == null) { + if (!object.Equals(leftEntry.Value, rightValue)) { + return false; + } + } else { + IEnumerator leftEnumerator = leftEnumerable.GetEnumerator(); + try { + foreach (object rightObject in rightEnumerable) { + if (!leftEnumerator.MoveNext()) { + return false; + } + if (!object.Equals(leftEnumerator.Current, rightObject)) { + return false; + } + } + if (leftEnumerator.MoveNext()) { + return false; + } + } finally { + if (leftEnumerator is IDisposable) { + ((IDisposable)leftEnumerator).Dispose(); + } + } + } + } + return true; + } + public static IDictionary AsReadOnly (IDictionary dictionary) { return dictionary.IsReadOnly ? dictionary : new ReadOnlyDictionary(dictionary); } + + /// + /// Creates a hashcode for a dictionary by XORing the hashcodes of all the fields + /// and values. (By XORing, we avoid ordering issues.) + /// TODO(jonskeet): Currently XORs other stuff too, and assumes non-null values. + /// + public static int GetHashCode(IDictionary dictionary) { + int ret = 31; + foreach (KeyValuePair entry in dictionary) { + int hash = entry.Key.GetHashCode() ^ GetDeepHashCode(entry.Value); + ret ^= hash; + } + return ret; + } + + /// + /// Determines the hash of a value by either taking it directly or hashing all the elements + /// for IEnumerable implementations. + /// + private static int GetDeepHashCode(object value) { + IEnumerable iterable = value as IEnumerable; + if (iterable == null) { + return value.GetHashCode(); + } + int hash = 29; + foreach (object element in iterable) { + hash = hash * 37 + element.GetHashCode(); + } + return hash; + } } } diff --git a/csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs b/csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs index ed15922975..14e1f1771f 100644 --- a/csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs +++ b/csharp/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs @@ -161,7 +161,6 @@ namespace Google.ProtocolBuffers.DescriptorProtos { #endregion #region Extensions - /**/ #endregion #region Static variables @@ -547,6 +546,10 @@ namespace Google.ProtocolBuffers.DescriptorProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::FileDescriptorProto) { return MergeFrom((self::FileDescriptorProto) other); @@ -1128,6 +1131,10 @@ namespace Google.ProtocolBuffers.DescriptorProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::DescriptorProto.Types.ExtensionRange) { return MergeFrom((self::DescriptorProto.Types.ExtensionRange) other); @@ -1459,6 +1466,10 @@ namespace Google.ProtocolBuffers.DescriptorProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::DescriptorProto) { return MergeFrom((self::DescriptorProto) other); @@ -2130,6 +2141,10 @@ namespace Google.ProtocolBuffers.DescriptorProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::FieldDescriptorProto) { return MergeFrom((self::FieldDescriptorProto) other); @@ -2582,6 +2597,10 @@ namespace Google.ProtocolBuffers.DescriptorProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::EnumDescriptorProto) { return MergeFrom((self::EnumDescriptorProto) other); @@ -2919,6 +2938,10 @@ namespace Google.ProtocolBuffers.DescriptorProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::EnumValueDescriptorProto) { return MergeFrom((self::EnumValueDescriptorProto) other); @@ -3231,6 +3254,10 @@ namespace Google.ProtocolBuffers.DescriptorProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::ServiceDescriptorProto) { return MergeFrom((self::ServiceDescriptorProto) other); @@ -3584,6 +3611,10 @@ namespace Google.ProtocolBuffers.DescriptorProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::MethodDescriptorProto) { return MergeFrom((self::MethodDescriptorProto) other); @@ -4022,6 +4053,10 @@ namespace Google.ProtocolBuffers.DescriptorProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::FileOptions) { return MergeFrom((self::FileOptions) other); @@ -4437,6 +4472,10 @@ namespace Google.ProtocolBuffers.DescriptorProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::MessageOptions) { return MergeFrom((self::MessageOptions) other); @@ -4664,6 +4703,10 @@ namespace Google.ProtocolBuffers.DescriptorProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::FieldOptions) { return MergeFrom((self::FieldOptions) other); @@ -4881,6 +4924,10 @@ namespace Google.ProtocolBuffers.DescriptorProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::EnumOptions) { return MergeFrom((self::EnumOptions) other); @@ -5041,6 +5088,10 @@ namespace Google.ProtocolBuffers.DescriptorProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::EnumValueOptions) { return MergeFrom((self::EnumValueOptions) other); @@ -5201,6 +5252,10 @@ namespace Google.ProtocolBuffers.DescriptorProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::ServiceOptions) { return MergeFrom((self::ServiceOptions) other); @@ -5361,6 +5416,10 @@ namespace Google.ProtocolBuffers.DescriptorProtos { return returnMe; } + protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { + return MergeFrom(data, extensionRegistry); + } + public override IBuilder MergeFrom(pb::IMessage other) { if (other is self::MethodOptions) { return MergeFrom((self::MethodOptions) other); diff --git a/csharp/ProtocolBuffers/Descriptors/EnumDescriptor.cs b/csharp/ProtocolBuffers/Descriptors/EnumDescriptor.cs index 838075826b..a28efc5f94 100644 --- a/csharp/ProtocolBuffers/Descriptors/EnumDescriptor.cs +++ b/csharp/ProtocolBuffers/Descriptors/EnumDescriptor.cs @@ -43,7 +43,8 @@ namespace Google.ProtocolBuffers.Descriptors { /// Finds an enum value by number. If multiple enum values have the /// same number, this returns the first defined value with that number. /// - internal EnumValueDescriptor FindValueByNumber(int number) { + // TODO(jonskeet): Make internal and use InternalsVisibleTo? + public EnumValueDescriptor FindValueByNumber(int number) { return File.DescriptorPool.FindEnumValueByNumber(this, number); } @@ -52,7 +53,8 @@ namespace Google.ProtocolBuffers.Descriptors { /// /// The unqualified name of the value (e.g. "FOO"). /// The value's descriptor, or null if not found. - internal EnumValueDescriptor FindValueByName(string name) { + // TODO(jonskeet): Make internal and use InternalsVisibleTo? + public EnumValueDescriptor FindValueByName(string name) { return File.DescriptorPool.FindSymbol(FullName + "." + name); } } diff --git a/csharp/ProtocolBuffers/DynamicMessage.cs b/csharp/ProtocolBuffers/DynamicMessage.cs index 8a18375c65..5b22d38b93 100644 --- a/csharp/ProtocolBuffers/DynamicMessage.cs +++ b/csharp/ProtocolBuffers/DynamicMessage.cs @@ -1,11 +1,381 @@ using System; using System.Collections.Generic; +using System.IO; using System.Text; +using Google.ProtocolBuffers.Descriptors; namespace Google.ProtocolBuffers { - public class DynamicMessage { - internal static object GetDefaultInstance(Google.ProtocolBuffers.Descriptors.MessageDescriptor messageDescriptor) { - throw new NotImplementedException(); + public class DynamicMessage : AbstractMessage { + + private readonly MessageDescriptor type; + private readonly FieldSet fields; + private readonly UnknownFieldSet unknownFields; + private int memoizedSize = -1; + + /// + /// Creates a DynamicMessage with the given FieldSet. + /// + /// + /// + /// + private DynamicMessage(MessageDescriptor type, FieldSet fields, UnknownFieldSet unknownFields) { + this.type = type; + this.fields = fields; + this.unknownFields = unknownFields; + } + + /// + /// Returns a DynamicMessage representing the default instance of the given type. + /// + /// + /// + public static DynamicMessage GetDefaultInstance(MessageDescriptor type) { + return new DynamicMessage(type, FieldSet.DefaultInstance, UnknownFieldSet.DefaultInstance); + } + + /// + /// Parses a message of the given type from the given stream. + /// + public static DynamicMessage ParseFrom(MessageDescriptor type, CodedInputStream input) { + IBuilder builder = CreateBuilder(type); + Builder dynamicBuilder = (Builder)builder.MergeFrom(input); + return dynamicBuilder.BuildParsed(); + + } + + /// + /// Parse a message of the given type from the given stream and extension registry. + /// + /// + /// + /// + /// + public static DynamicMessage ParseFrom(MessageDescriptor type, CodedInputStream input, ExtensionRegistry extensionRegistry) { + IBuilder builder = CreateBuilder(type); + Builder dynamicBuilder = (Builder) builder.MergeFrom(input, extensionRegistry); + return dynamicBuilder.BuildParsed(); + } + + /// + /// Parses a message of the given type from the given stream. + /// + public static DynamicMessage ParseFrom(MessageDescriptor type, Stream input) { + IBuilder builder = CreateBuilder(type); + Builder dynamicBuilder = (Builder)builder.MergeFrom(input); + return dynamicBuilder.BuildParsed(); + } + + /// + /// Parse a message of the given type from the given stream and extension registry. + /// + /// + /// + /// + /// + public static DynamicMessage ParseFrom(MessageDescriptor type, Stream input, ExtensionRegistry extensionRegistry) { + IBuilder builder = CreateBuilder(type); + Builder dynamicBuilder = (Builder)builder.MergeFrom(input, extensionRegistry); + return dynamicBuilder.BuildParsed(); + } + + /// + /// Parse as a message of the given type and return it. + /// + public static DynamicMessage ParseFrom(MessageDescriptor type, ByteString data) { + IBuilder builder = CreateBuilder(type); + Builder dynamicBuilder = (Builder)builder.MergeFrom(data); + return dynamicBuilder.BuildParsed(); + } + + /// + /// Parse as a message of the given type and return it. + /// + public static DynamicMessage ParseFrom(MessageDescriptor type, ByteString data, ExtensionRegistry extensionRegistry) { + IBuilder builder = CreateBuilder(type); + Builder dynamicBuilder = (Builder)builder.MergeFrom(data, extensionRegistry); + return dynamicBuilder.BuildParsed(); + + } + + /// + /// Parse as a message of the given type and return it. + /// + public static DynamicMessage ParseFrom(MessageDescriptor type, byte[] data) { + IBuilder builder = CreateBuilder(type); + Builder dynamicBuilder = (Builder)builder.MergeFrom(data); + return dynamicBuilder.BuildParsed(); + } + + /// + /// Parse as a message of the given type and return it. + /// + public static DynamicMessage ParseFrom(MessageDescriptor type, byte[] data, ExtensionRegistry extensionRegistry) { + IBuilder builder = CreateBuilder(type); + Builder dynamicBuilder = (Builder)builder.MergeFrom(data, extensionRegistry); + return dynamicBuilder.BuildParsed(); + } + + /// + /// Constructs a builder for the given type. + /// + public static Builder CreateBuilder(MessageDescriptor type) { + return new Builder(type); + } + + /// + /// Constructs a builder for a message of the same type as , + /// and initializes it with the same contents. + /// + /// + /// + public static Builder CreateBuilder(IMessage prototype) { + return (Builder) new Builder(prototype.DescriptorForType).MergeFrom(prototype); + } + + // ----------------------------------------------------------------- + // Implementation of IMessage interface. + + public override MessageDescriptor DescriptorForType { + get { return type; } + } + + protected override IMessage DefaultInstanceForTypeImpl { + get { return GetDefaultInstance(type); } + } + + public override IDictionary AllFields { + get { return fields.AllFields; } + } + + public override bool HasField(FieldDescriptor field) { + VerifyContainingType(field); + return fields.HasField(field); + } + + public override object this[FieldDescriptor field] { + get { + VerifyContainingType(field); + object result = fields[field]; + if (result == null) { + result = GetDefaultInstance(field.MessageType); + } + return result; + } + } + + public override int GetRepeatedFieldCount(FieldDescriptor field) { + VerifyContainingType(field); + return fields.GetRepeatedFieldCount(field); + } + + public override object this[FieldDescriptor field, int index] { + get { + VerifyContainingType(field); + return fields[field, index]; + } + } + + public override UnknownFieldSet UnknownFields { + get { return unknownFields; } + } + + public bool Initialized { + get { return fields.IsInitializedWithRespectTo(type); } + } + + public override void WriteTo(CodedOutputStream output) { + fields.WriteTo(output); + if (type.Options.MessageSetWireFormat) { + unknownFields.WriteAsMessageSetTo(output); + } else { + unknownFields.WriteTo(output); + } + } + + public override int SerializedSize { + get { + int size = memoizedSize; + if (size != -1) return size; + + size = fields.SerializedSize; + if (type.Options.MessageSetWireFormat) { + size += unknownFields.SerializedSizeAsMessageSet; + } else { + size += unknownFields.SerializedSize; + } + + memoizedSize = size; + return size; + } + } + + protected override IBuilder CreateBuilderForTypeImpl() { + return new Builder(type); + } + + /// + /// Verifies that the field is a field of this message. + /// + private void VerifyContainingType(FieldDescriptor field) { + if (field.ContainingType != type) { + throw new ArgumentException("FieldDescriptor does not match message type."); + } + } + + public class Builder : AbstractBuilder { + private readonly MessageDescriptor type; + private FieldSet fields; + private UnknownFieldSet unknownFields; + + internal Builder(MessageDescriptor type) { + this.type = type; + this.fields = FieldSet.CreateFieldSet(); + this.unknownFields = UnknownFieldSet.DefaultInstance; + } + + public override IBuilder Clear() { + fields.Clear(); + return this; + } + + public override IBuilder MergeFrom(IMessage other) { + if (other.DescriptorForType != type) { + throw new ArgumentException("MergeFrom(IMessage) can only merge messages of the same type."); + } + fields.MergeFrom(other); + return this; + } + + protected override IMessage BuildImpl() { + if (!Initialized) { + throw new UninitializedMessageException(new DynamicMessage(type, fields, unknownFields)); + } + return BuildPartialImpl(); + } + + /// + /// Helper for DynamicMessage.ParseFrom() methods to call. Throws + /// InvalidProtocolBufferException + /// + /// + internal DynamicMessage BuildParsed() { + if (!Initialized) { + throw new UninitializedMessageException(new DynamicMessage(type, fields, unknownFields)).AsInvalidProtocolBufferException(); + } + return (DynamicMessage) BuildPartialImpl(); + } + + protected override IMessage BuildPartialImpl() { + fields.MakeImmutable(); + DynamicMessage result = new DynamicMessage(type, fields, unknownFields); + fields = null; + unknownFields = null; + return result; + } + + protected override IBuilder CloneImpl() { + Builder result = new Builder(type); + result.fields.MergeFrom(fields); + return result; + } + + public override bool Initialized { + get { return fields.IsInitializedWithRespectTo(type); } + } + + protected override IBuilder MergeFromImpl(CodedInputStream input, ExtensionRegistry extensionRegistry) { + UnknownFieldSet.Builder unknownFieldsBuilder = UnknownFieldSet.CreateBuilder(unknownFields); + FieldSet.MergeFrom(input, unknownFieldsBuilder, extensionRegistry, this); + unknownFields = unknownFieldsBuilder.Build(); + return this; + } + + public override MessageDescriptor DescriptorForType { + get { return type; } + } + + protected override IMessage DefaultInstanceForTypeImpl { + get { return GetDefaultInstance(type); } + } + + public override IDictionary AllFields { + get { return fields.AllFields; } + } + + public override IBuilder CreateBuilderForField(FieldDescriptor field) { + VerifyContainingType(field); + if (field.MappedType != MappedType.Message) { + throw new ArgumentException("CreateBuilderForField is only valid for fields with message type."); + } + return new Builder(field.MessageType); + } + + public override bool HasField(FieldDescriptor field) { + VerifyContainingType(field); + return fields.HasField(field); + } + + public override object this[FieldDescriptor field, int index] { + get { + VerifyContainingType(field); + return fields[field, index]; + } + set { + VerifyContainingType(field); + fields[field, index] = value; + } + } + + public override object this[FieldDescriptor field] { + get { + VerifyContainingType(field); + object result = fields[field]; + if (result == null) { + result = GetDefaultInstance(field.MessageType); + } + return result; + } + set { + VerifyContainingType(field); + fields[field] = value; + } + } + + protected override IBuilder ClearFieldImpl(FieldDescriptor field) { + VerifyContainingType(field); + fields.ClearField(field); + return this; + } + + public override int GetRepeatedFieldCount(FieldDescriptor field) { + VerifyContainingType(field); + return fields.GetRepeatedFieldCount(field); + } + + protected override IBuilder AddRepeatedFieldImpl(FieldDescriptor field, object value) { + VerifyContainingType(field); + fields.AddRepeatedField(field, value); + return this; + } + + public override UnknownFieldSet UnknownFields { + get { + return unknownFields; + } + set { + unknownFields = value; + } + } + + /// + /// Verifies that the field is a field of this message. + /// + /// + private void VerifyContainingType(FieldDescriptor field) { + if (field.ContainingType != type) { + throw new ArgumentException("FieldDescriptor does not match message type."); + } + } } } } diff --git a/csharp/ProtocolBuffers/ExtendableBuilder.cs b/csharp/ProtocolBuffers/ExtendableBuilder.cs new file mode 100644 index 0000000000..3f5a81622a --- /dev/null +++ b/csharp/ProtocolBuffers/ExtendableBuilder.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Google.ProtocolBuffers.Descriptors; + +namespace Google.ProtocolBuffers { + public abstract class ExtendableBuilder : GeneratedBuilder + where TMessage : ExtendableMessage + where TBuilder : GeneratedBuilder { + + protected ExtendableBuilder() {} + + /// + /// Checks if a singular extension is present + /// + public bool HasExtension(GeneratedExtensionBase extension) { + return MessageBeingBuilt.HasExtension(extension); + } + + /// + /// Returns the number of elements in a repeated extension. + /// + public int GetExtensionCount(GeneratedExtensionBase> extension) { + return MessageBeingBuilt.GetExtensionCount(extension); + } + + /// + /// Returns the value of an extension. + /// + public TExtension GetExtension(GeneratedExtensionBase extension) { + return MessageBeingBuilt.GetExtension(extension); + } + + /// + /// Returns one element of a repeated extension. + /// + public TExtension GetExtension(GeneratedExtensionBase> extension, int index) { + return MessageBeingBuilt.GetExtension(extension, index); + } + + /// + /// Sets the value of an extension. + /// + public ExtendableBuilder SetExtension(GeneratedExtensionBase extension, TExtension value) { + ExtendableMessage message = MessageBeingBuilt; + message.VerifyExtensionContainingType(extension); + message.Extensions[extension.Descriptor] = extension.ToReflectionType(value); + return this; + } + + /// + /// Sets the value of one element of a repeated extension. + /// + public ExtendableBuilder SetExtension( + GeneratedExtensionBase> extension, int index, Type value) { + ExtendableMessage message = MessageBeingBuilt; + message.VerifyExtensionContainingType(extension); + message.Extensions[extension.Descriptor, index] = extension.SingularToReflectionType(value); + return this; + } + + /// + /// Appends a value to a repeated extension. + /// + public ExtendableBuilder AddExtension( + GeneratedExtensionBase> extension, TExtension value) { + ExtendableMessage message = MessageBeingBuilt; + message.VerifyExtensionContainingType(extension); + message.Extensions.AddRepeatedField(extension.Descriptor, extension.SingularToReflectionType(value)); + return this; + } + + /// + /// Clears an extension. + /// + public ExtendableBuilder ClearExtension( + GeneratedExtensionBase extension) { + ExtendableMessage message = MessageBeingBuilt; + message.VerifyExtensionContainingType(extension); + message.Extensions.ClearField(extension.Descriptor); + return this; + } + + /// + /// Called by subclasses to parse an unknown field or an extension. + /// + /// true unless the tag is an end-group tag + protected override bool ParseUnknownField(CodedInputStream input, UnknownFieldSet.Builder unknownFields, + ExtensionRegistry extensionRegistry, uint tag) { + return FieldSet.MergeFieldFrom(input, unknownFields, extensionRegistry, this, tag); + } + + // --------------------------------------------------------------- + // Reflection + + + public override object this[FieldDescriptor field, int index] { + set { + if (field.IsExtension) { + ExtendableMessage message = MessageBeingBuilt; + // TODO(jonskeet): Figure out how to call this! + // message.VerifyExtensionContainingType(field); + message.Extensions[field, index] = value; + } else { + base[field, index] = value; + } + } + } + + + public override object this[FieldDescriptor field] { + set { + if (field.IsExtension) { + ExtendableMessage message = MessageBeingBuilt; + // TODO(jonskeet): Figure out how to call this! + // message.VerifyExtensionContainingType(field); + message.Extensions[field] = value; + } else { + base[field] = value; + } + InternalFieldAccessors[field].SetValue(this, value); + } + } + + public override IBuilder ClearField(FieldDescriptor field) { + if (field.IsExtension) { + ExtendableMessage message = MessageBeingBuilt; + message.VerifyContainingType(field); + message.Extensions.ClearField(field); + return this; + } else { + return base.ClearField(field); + } + } + + public override IBuilder AddRepeatedField(FieldDescriptor field, object value) { + if (field.IsExtension) { + ExtendableMessage message = MessageBeingBuilt; + message.VerifyContainingType(field); + message.Extensions.AddRepeatedField(field, value); + return this; + } else { + return base.AddRepeatedField(field, value); + } + } + } +} diff --git a/csharp/ProtocolBuffers/ExtendableMessage.cs b/csharp/ProtocolBuffers/ExtendableMessage.cs index 872b15b6ad..0a2d03173c 100644 --- a/csharp/ProtocolBuffers/ExtendableMessage.cs +++ b/csharp/ProtocolBuffers/ExtendableMessage.cs @@ -12,10 +12,17 @@ namespace Google.ProtocolBuffers { protected ExtendableMessage() {} private readonly FieldSet extensions = FieldSet.CreateFieldSet(); + /// + /// Access for the builder. + /// + internal FieldSet Extensions { + get { return extensions; } + } + /// /// Checks if a singular extension is present. /// - public bool HasExtension(GeneratedExtensionBase extension) { + public bool HasExtension(GeneratedExtensionBase extension) { return extensions.HasField(extension.Descriptor); } @@ -111,7 +118,7 @@ namespace Google.ProtocolBuffers { } } - private void VerifyContainingType(FieldDescriptor field) { + internal void VerifyContainingType(FieldDescriptor field) { if (field.ContainingType != DescriptorForType) { throw new ArgumentException("FieldDescriptor does not match message type."); } @@ -161,5 +168,13 @@ namespace Google.ProtocolBuffers { protected int ExtensionsSerializedSize { get { return extensions.SerializedSize; } } + + internal void VerifyExtensionContainingType(GeneratedExtensionBase extension) { + if (extension.Descriptor.ContainingType != DescriptorForType) { + // This can only happen if someone uses unchecked operations. + throw new ArgumentException("Extension is for type \"" + extension.Descriptor.ContainingType.FullName + + "\" which does not match message type \"" + DescriptorForType.FullName + "\"."); + } + } } } diff --git a/csharp/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs b/csharp/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs index 11611b64db..15ea6253b9 100644 --- a/csharp/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs +++ b/csharp/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs @@ -73,7 +73,7 @@ namespace Google.ProtocolBuffers.FieldAccess { } public int GetRepeatedCount(IMessage message) { - return (int) countProperty.GetValue(null, null); + return (int) countProperty.GetValue(message, null); } public virtual object GetRepeatedValue(IMessage message, int index) { diff --git a/csharp/ProtocolBuffers/GeneratedBuilder.cs b/csharp/ProtocolBuffers/GeneratedBuilder.cs index 4b3567d080..154aa05f99 100644 --- a/csharp/ProtocolBuffers/GeneratedBuilder.cs +++ b/csharp/ProtocolBuffers/GeneratedBuilder.cs @@ -65,7 +65,7 @@ namespace Google.ProtocolBuffers { /// Called by derived classes to parse an unknown field. /// /// true unless the tag is an end-group tag - protected bool ParseUnknownField(CodedInputStream input, UnknownFieldSet.Builder unknownFields, + protected virtual bool ParseUnknownField(CodedInputStream input, UnknownFieldSet.Builder unknownFields, ExtensionRegistry extensionRegistry, uint tag) { return unknownFields.MergeFieldFrom(tag, input); } @@ -115,7 +115,7 @@ namespace Google.ProtocolBuffers { return AddRepeatedField(field, value); } - public IBuilder ClearField(FieldDescriptor field) { + public virtual IBuilder ClearField(FieldDescriptor field) { InternalFieldAccessors[field].Clear(this); return this; } @@ -155,7 +155,7 @@ namespace Google.ProtocolBuffers { return this; } - public IBuilder AddRepeatedField(FieldDescriptor field, object value) { + public virtual IBuilder AddRepeatedField(FieldDescriptor field, object value) { InternalFieldAccessors[field].AddRepeated(this, value); return this; } @@ -190,19 +190,21 @@ namespace Google.ProtocolBuffers { return this; } + /// + /// Overridden when optimized for speed. + /// public virtual IBuilder MergeFrom(CodedInputStream input) { ((IBuilder)this).MergeFrom(input); return this; } + /// + /// Overridden when optimized for speed. + /// public virtual IBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) { ((IBuilder)this).MergeFrom(input, extensionRegistry); return this; } - - protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) { - return MergeFrom(data, extensionRegistry); - } /// /// Like Build(), but will wrap UninitializedMessageException in diff --git a/csharp/ProtocolBuffers/GeneratedExtensionBase.cs b/csharp/ProtocolBuffers/GeneratedExtensionBase.cs index 401183883d..2ab6d7a65c 100644 --- a/csharp/ProtocolBuffers/GeneratedExtensionBase.cs +++ b/csharp/ProtocolBuffers/GeneratedExtensionBase.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Reflection; using System.Text; @@ -33,14 +34,14 @@ namespace Google.ProtocolBuffers { private readonly FieldDescriptor descriptor; private readonly IMessage messageDefaultInstance; - protected GeneratedExtensionBase(FieldDescriptor descriptor) { + protected GeneratedExtensionBase(FieldDescriptor descriptor, Type singularExtensionType) { if (!descriptor.IsExtension) { throw new ArgumentException("GeneratedExtension given a regular (non-extension) field."); } this.descriptor = descriptor; if (descriptor.MappedType == MappedType.Message) { - PropertyInfo defaultInstanceProperty = typeof(TExtension) + PropertyInfo defaultInstanceProperty = singularExtensionType .GetProperty("DefaultInstance", BindingFlags.Static | BindingFlags.Public); if (defaultInstanceProperty == null) { throw new ArgumentException("No public static DefaultInstance property for type " + typeof(TExtension).Name); @@ -83,6 +84,38 @@ namespace Google.ProtocolBuffers { } } + /// + /// Converts from the type used by the native accessors to the type + /// used by reflection accessors. For example, the reflection accessors + /// for enums use EnumValueDescriptors but the native accessors use + /// the generated enum type. + /// + public object ToReflectionType(object value) { + if (descriptor.IsRepeated) { + if (descriptor.MappedType == MappedType.Enum) { + // Must convert the whole list. + IList result = new List(); + foreach (object element in (IEnumerable) value) { + result.Add(SingularToReflectionType(element)); + } + return result; + } else { + return value; + } + } else { + return SingularToReflectionType(value); + } + } + + /// + /// Like ToReflectionType(object) but for a single element. + /// + internal Object SingularToReflectionType(object value) { + return descriptor.MappedType == MappedType.Enum + ? descriptor.EnumType.FindValueByNumber((int) value) + : value; + } + public abstract object FromReflectionType(object value); } } \ No newline at end of file diff --git a/csharp/ProtocolBuffers/GeneratedMessage.cs b/csharp/ProtocolBuffers/GeneratedMessage.cs index 2aa8e842d5..37fd2e6b66 100644 --- a/csharp/ProtocolBuffers/GeneratedMessage.cs +++ b/csharp/ProtocolBuffers/GeneratedMessage.cs @@ -48,8 +48,11 @@ namespace Google.ProtocolBuffers { MessageDescriptor descriptor = DescriptorForType; foreach (FieldDescriptor field in descriptor.Fields) { IFieldAccessor accessor = InternalFieldAccessors[field]; - if ((field.IsRepeated && accessor.GetRepeatedCount(this) != 0) - || accessor.Has(this)) { + if (field.IsRepeated) { + if (accessor.GetRepeatedCount(this) != 0) { + ret[field] = accessor.GetValue(this); + } + } else if (HasField(field)) { ret[field] = accessor.GetValue(this); } } diff --git a/csharp/ProtocolBuffers/GeneratedRepeatException.cs b/csharp/ProtocolBuffers/GeneratedRepeatException.cs index d766d7f643..a38f5c1bac 100644 --- a/csharp/ProtocolBuffers/GeneratedRepeatException.cs +++ b/csharp/ProtocolBuffers/GeneratedRepeatException.cs @@ -8,11 +8,11 @@ namespace Google.ProtocolBuffers { /// Class used to represent repeat extensions in generated classes. /// public class GeneratedRepeatExtension : GeneratedExtensionBase> { - private GeneratedRepeatExtension(FieldDescriptor field) : base(field) { + private GeneratedRepeatExtension(FieldDescriptor field) : base(field, typeof(TExtensionElement)) { } public static GeneratedExtensionBase> CreateInstance(FieldDescriptor descriptor) { - if (descriptor.IsRepeated) { + if (!descriptor.IsRepeated) { throw new ArgumentException("Must call GeneratedRepeatExtension.CreateInstance() for repeated types."); } return new GeneratedRepeatExtension(descriptor); diff --git a/csharp/ProtocolBuffers/GeneratedSingleExtension.cs b/csharp/ProtocolBuffers/GeneratedSingleExtension.cs index 118052934d..0adcd7ef74 100644 --- a/csharp/ProtocolBuffers/GeneratedSingleExtension.cs +++ b/csharp/ProtocolBuffers/GeneratedSingleExtension.cs @@ -9,7 +9,7 @@ namespace Google.ProtocolBuffers { public class GeneratedSingleExtension : GeneratedExtensionBase where TContainer : IMessage { - internal GeneratedSingleExtension(FieldDescriptor descriptor) : base(descriptor) { + internal GeneratedSingleExtension(FieldDescriptor descriptor) : base(descriptor, typeof(TExtension)) { } public static GeneratedSingleExtension CreateInstance(FieldDescriptor descriptor) { diff --git a/csharp/ProtocolBuffers/IBuilder.cs b/csharp/ProtocolBuffers/IBuilder.cs index f847f217ab..b46842cdf6 100644 --- a/csharp/ProtocolBuffers/IBuilder.cs +++ b/csharp/ProtocolBuffers/IBuilder.cs @@ -50,6 +50,18 @@ namespace Google.ProtocolBuffers { /// object this[FieldDescriptor field] { get; set; } + /// + /// Only present in the nongeneric interface - useful for tests, but + /// not as much in real life. + /// + IBuilder SetField(FieldDescriptor field, object value); + + /// + /// Only present in the nongeneric interface - useful for tests, but + /// not as much in real life. + /// + IBuilder SetRepeatedField(FieldDescriptor field, int index, object value); + /// /// Get the message's type's descriptor. /// diff --git a/csharp/ProtocolBuffers/ProtocolBuffers.csproj b/csharp/ProtocolBuffers/ProtocolBuffers.csproj index 3735adb762..6c97e8d1fb 100644 --- a/csharp/ProtocolBuffers/ProtocolBuffers.csproj +++ b/csharp/ProtocolBuffers/ProtocolBuffers.csproj @@ -68,6 +68,7 @@ + diff --git a/csharp/ProtocolBuffers/TextGenerator.cs b/csharp/ProtocolBuffers/TextGenerator.cs index 724c1a8f81..b583750462 100644 --- a/csharp/ProtocolBuffers/TextGenerator.cs +++ b/csharp/ProtocolBuffers/TextGenerator.cs @@ -70,6 +70,9 @@ namespace Google.ProtocolBuffers { } private void Write(string data) { + if (data.Length == 0) { + return; + } if (atStartOfLine) { atStartOfLine = false; writer.Write(indent);