From bfee2dfe137b07e64ebd46baf71d932d58d01b1f Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Tue, 23 Jun 2015 16:09:27 +0100 Subject: [PATCH 1/4] Implement freezing for messages and repeated fields. Fixes issue #523. --- csharp/src/AddressBook/Addressbook.cs | 62 +- .../GeneratedMessageTest.cs | 20 +- .../ProtocolBuffers.Test/RepeatedFieldTest.cs | 47 +- .../TestProtos/UnittestImportProto3.cs | 16 +- .../TestProtos/UnittestImportPublicProto3.cs | 16 +- .../TestProtos/UnittestIssues.cs | 78 +- .../TestProtos/UnittestProto3.cs | 789 +++++++++++++++--- .../Collections/RepeatedField.cs | 35 +- .../DescriptorProtos/DescriptorProtoFile.cs | 710 ++++++++++++---- csharp/src/ProtocolBuffers/Freezable.cs | 60 ++ csharp/src/ProtocolBuffers/IMessage.cs | 36 +- .../ProtocolBuffers/ProtocolBuffers.csproj | 1 + .../compiler/csharp/csharp_field_base.cc | 5 + .../compiler/csharp/csharp_field_base.h | 1 + .../compiler/csharp/csharp_message.cc | 36 +- .../protobuf/compiler/csharp/csharp_message.h | 1 + .../compiler/csharp/csharp_message_field.cc | 13 +- .../compiler/csharp/csharp_message_field.h | 1 + .../compiler/csharp/csharp_primitive_field.cc | 15 +- .../csharp/csharp_repeated_enum_field.cc | 5 + .../csharp/csharp_repeated_enum_field.h | 1 + .../csharp/csharp_repeated_message_field.cc | 5 + .../csharp/csharp_repeated_message_field.h | 1 + .../csharp/csharp_repeated_primitive_field.cc | 5 + .../csharp/csharp_repeated_primitive_field.h | 1 + 25 files changed, 1668 insertions(+), 292 deletions(-) create mode 100644 csharp/src/ProtocolBuffers/Freezable.cs diff --git a/csharp/src/AddressBook/Addressbook.cs b/csharp/src/AddressBook/Addressbook.cs index cd1f6231f7..2fb6be8359 100644 --- a/csharp/src/AddressBook/Addressbook.cs +++ b/csharp/src/AddressBook/Addressbook.cs @@ -76,6 +76,9 @@ namespace Google.ProtocolBuffers.Examples.AddressBook { get { return global::Google.ProtocolBuffers.Examples.AddressBook.Addressbook.internal__static_tutorial_Person__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public Person() { } public Person(Person other) { @@ -89,30 +92,44 @@ namespace Google.ProtocolBuffers.Examples.AddressBook { return new Person(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + phone_.Freeze(); + } + public const int NameFieldNumber = 1; private string name_ = ""; public string Name { get { return name_; } - set { name_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + name_ = value ?? ""; + } } - public const int IdFieldNumber = 2; private int id_; public int Id { get { return id_; } - set { id_ = value; } + set { + pb::Freezable.CheckMutable(this); + id_ = value; + } } - public const int EmailFieldNumber = 3; private string email_ = ""; public string Email { get { return email_; } - set { email_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + email_ = value ?? ""; + } } - public const int PhoneFieldNumber = 4; private readonly pbc::RepeatedField phone_ = new pbc::RepeatedField(); public pbc::RepeatedField Phone { @@ -254,6 +271,9 @@ namespace Google.ProtocolBuffers.Examples.AddressBook { get { return global::Google.ProtocolBuffers.Examples.AddressBook.Addressbook.internal__static_tutorial_Person_PhoneNumber__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public PhoneNumber() { } public PhoneNumber(PhoneNumber other) { @@ -265,22 +285,33 @@ namespace Google.ProtocolBuffers.Examples.AddressBook { return new PhoneNumber(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int NumberFieldNumber = 1; private string number_ = ""; public string Number { get { return number_; } - set { number_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + number_ = value ?? ""; + } } - public const int TypeFieldNumber = 2; private global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneType type_ = global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneType.HOME; public global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneType Type { get { return type_; } - set { type_ = value; } + set { + pb::Freezable.CheckMutable(this); + type_ = value; + } } - public override bool Equals(object other) { return Equals(other as PhoneNumber); } @@ -382,6 +413,9 @@ namespace Google.ProtocolBuffers.Examples.AddressBook { get { return global::Google.ProtocolBuffers.Examples.AddressBook.Addressbook.internal__static_tutorial_AddressBook__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public AddressBook() { } public AddressBook(AddressBook other) { @@ -392,6 +426,14 @@ namespace Google.ProtocolBuffers.Examples.AddressBook { return new AddressBook(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + person_.Freeze(); + } + public const int PersonFieldNumber = 1; private readonly pbc::RepeatedField person_ = new pbc::RepeatedField(); public pbc::RepeatedField Person { diff --git a/csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs b/csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs index e21d904da4..2616542813 100644 --- a/csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs +++ b/csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs @@ -1,4 +1,5 @@ -using Google.Protobuf.TestProtos; +using System; +using Google.Protobuf.TestProtos; using NUnit.Framework; namespace Google.Protobuf @@ -257,5 +258,22 @@ namespace Google.Protobuf original.OneofNestedMessage.Bb = 30; Assert.AreNotEqual(original, clone); } + + [Test] + public void Freeze() + { + var frozen = new TestAllTypes(); + frozen.Freeze(); + Assert.IsTrue(frozen.IsFrozen); + + Assert.Throws(() => frozen.ClearOneofField()); + Assert.Throws(() => frozen.SingleInt32 = 0); + Assert.Throws(() => frozen.SingleNestedMessage = null); + Assert.Throws(() => frozen.SingleNestedEnum = 0); + Assert.Throws(() => frozen.OneofString = null); + Assert.Throws(() => frozen.OneofUint32 = 0U); + Assert.Throws(() => frozen.RepeatedDouble.Add(0.0)); + Assert.Throws(() => frozen.RepeatedNestedMessage.Add(new TestAllTypes.Types.NestedMessage())); + } } } diff --git a/csharp/src/ProtocolBuffers.Test/RepeatedFieldTest.cs b/csharp/src/ProtocolBuffers.Test/RepeatedFieldTest.cs index cbe792947c..c01cd8ffe5 100644 --- a/csharp/src/ProtocolBuffers.Test/RepeatedFieldTest.cs +++ b/csharp/src/ProtocolBuffers.Test/RepeatedFieldTest.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Google.Protobuf.Collections; +using Google.Protobuf.TestProtos; using NUnit.Framework; namespace Google.Protobuf @@ -11,8 +12,8 @@ namespace Google.Protobuf public void NullValuesRejected() { var list = new RepeatedField(); - Assert.Throws(() => list.Add((string) null)); - Assert.Throws(() => list.Add((IEnumerable) null)); + Assert.Throws(() => list.Add((string)null)); + Assert.Throws(() => list.Add((IEnumerable)null)); Assert.Throws(() => list.Add((RepeatedField)null)); Assert.Throws(() => list.Contains(null)); Assert.Throws(() => list.IndexOf(null)); @@ -47,5 +48,47 @@ namespace Google.Protobuf Assert.AreEqual("foo", list[1]); Assert.AreEqual("bar", list[2]); } + + [Test] + public void Freeze_FreezesElements() + { + var list = new RepeatedField { new TestAllTypes() }; + Assert.IsFalse(list[0].IsFrozen); + list.Freeze(); + Assert.IsTrue(list[0].IsFrozen); + } + + [Test] + public void Freeze_PreventsMutations() + { + var list = new RepeatedField { 0 }; + list.Freeze(); + Assert.Throws(() => list.Add(1)); + Assert.Throws(() => list[0] = 1); + Assert.Throws(() => list.Clear()); + Assert.Throws(() => list.RemoveAt(0)); + Assert.Throws(() => list.Remove(0)); + Assert.Throws(() => list.Insert(0, 0)); + } + + [Test] + public void Freeze_ReportsFrozen() + { + var list = new RepeatedField { 0 }; + Assert.IsFalse(list.IsFrozen); + Assert.IsFalse(list.IsReadOnly); + list.Freeze(); + Assert.IsTrue(list.IsFrozen); + Assert.IsTrue(list.IsReadOnly); + } + + [Test] + public void Clone_ReturnsMutable() + { + var list = new RepeatedField { 0 }; + list.Freeze(); + var clone = list.Clone(); + clone[0] = 1; + } } } diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs index 30256972ae..a32d19c233 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs @@ -74,6 +74,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestImportProto3.internal__static_protobuf_unittest_import_ImportMessage__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public ImportMessage() { } public ImportMessage(ImportMessage other) { @@ -84,14 +87,23 @@ namespace Google.Protobuf.TestProtos { return new ImportMessage(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int DFieldNumber = 1; private int d_; public int D { get { return d_; } - set { d_ = value; } + set { + pb::Freezable.CheckMutable(this); + d_ = value; + } } - public override bool Equals(object other) { return Equals(other as ImportMessage); } diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportPublicProto3.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportPublicProto3.cs index cb7292f3d1..2c8b0a310d 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportPublicProto3.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportPublicProto3.cs @@ -59,6 +59,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestImportPublicProto3.internal__static_protobuf_unittest_import_PublicImportMessage__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public PublicImportMessage() { } public PublicImportMessage(PublicImportMessage other) { @@ -69,14 +72,23 @@ namespace Google.Protobuf.TestProtos { return new PublicImportMessage(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int EFieldNumber = 1; private int e_; public int E { get { return e_; } - set { e_ = value; } + set { + pb::Freezable.CheckMutable(this); + e_ = value; + } } - public override bool Equals(object other) { return Equals(other as PublicImportMessage); } diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs index d32718d51b..28508a3bdf 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs @@ -104,6 +104,9 @@ namespace UnitTest.Issues.TestProtos { get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_NegativeEnumMessage__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public NegativeEnumMessage() { } public NegativeEnumMessage(NegativeEnumMessage other) { @@ -116,14 +119,25 @@ namespace UnitTest.Issues.TestProtos { return new NegativeEnumMessage(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + values_.Freeze(); + packedValues_.Freeze(); + } + public const int ValueFieldNumber = 1; private global::UnitTest.Issues.TestProtos.NegativeEnum value_ = global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO; public global::UnitTest.Issues.TestProtos.NegativeEnum Value { get { return value_; } - set { value_ = value; } + set { + pb::Freezable.CheckMutable(this); + value_ = value; + } } - public const int ValuesFieldNumber = 2; private readonly pbc::RepeatedField values_ = new pbc::RepeatedField(); public pbc::RepeatedField Values { @@ -255,6 +269,9 @@ namespace UnitTest.Issues.TestProtos { get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_DeprecatedChild__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public DeprecatedChild() { } public DeprecatedChild(DeprecatedChild other) { @@ -264,6 +281,13 @@ namespace UnitTest.Issues.TestProtos { return new DeprecatedChild(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public override bool Equals(object other) { return Equals(other as DeprecatedChild); } @@ -328,6 +352,9 @@ namespace UnitTest.Issues.TestProtos { get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public DeprecatedFieldsMessage() { } public DeprecatedFieldsMessage(DeprecatedFieldsMessage other) { @@ -343,15 +370,28 @@ namespace UnitTest.Issues.TestProtos { return new DeprecatedFieldsMessage(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + primitiveArray_.Freeze(); + if (messageValue_ != null) MessageValue.Freeze(); + messageArray_.Freeze(); + enumArray_.Freeze(); + } + public const int PrimitiveValueFieldNumber = 1; private int primitiveValue_; [global::System.ObsoleteAttribute()] public int PrimitiveValue { get { return primitiveValue_; } - set { primitiveValue_ = value; } + set { + pb::Freezable.CheckMutable(this); + primitiveValue_ = value; + } } - public const int PrimitiveArrayFieldNumber = 2; private readonly pbc::RepeatedField primitiveArray_ = new pbc::RepeatedField(); [global::System.ObsoleteAttribute()] @@ -364,7 +404,10 @@ namespace UnitTest.Issues.TestProtos { [global::System.ObsoleteAttribute()] public global::UnitTest.Issues.TestProtos.DeprecatedChild MessageValue { get { return messageValue_; } - set { messageValue_ = value; } + set { + pb::Freezable.CheckMutable(this); + messageValue_ = value; + } } public const int MessageArrayFieldNumber = 4; @@ -379,10 +422,12 @@ namespace UnitTest.Issues.TestProtos { [global::System.ObsoleteAttribute()] public global::UnitTest.Issues.TestProtos.DeprecatedEnum EnumValue { get { return enumValue_; } - set { enumValue_ = value; } + set { + pb::Freezable.CheckMutable(this); + enumValue_ = value; + } } - public const int EnumArrayFieldNumber = 6; private readonly pbc::RepeatedField enumArray_ = new pbc::RepeatedField(); [global::System.ObsoleteAttribute()] @@ -403,7 +448,8 @@ namespace UnitTest.Issues.TestProtos { } if (PrimitiveValue != other.PrimitiveValue) return false; if(!primitiveArray_.Equals(other.primitiveArray_)) return false; - if (!object.Equals(MessageValue, other.MessageValue)) return false;if(!messageArray_.Equals(other.messageArray_)) return false; + if (!object.Equals(MessageValue, other.MessageValue)) return false; + if(!messageArray_.Equals(other.messageArray_)) return false; if (EnumValue != other.EnumValue) return false; if(!enumArray_.Equals(other.enumArray_)) return false; return true; @@ -563,6 +609,9 @@ namespace UnitTest.Issues.TestProtos { get { return global::UnitTest.Issues.TestProtos.UnittestIssues.internal__static_unittest_issues_ItemField__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public ItemField() { } public ItemField(ItemField other) { @@ -573,14 +622,23 @@ namespace UnitTest.Issues.TestProtos { return new ItemField(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int ItemFieldNumber = 1; private int item_; public int Item { get { return item_; } - set { item_ = value; } + set { + pb::Freezable.CheckMutable(this); + item_ = value; + } } - public override bool Equals(object other) { return Equals(other as ItemField); } diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs index d9d33b104e..d758ef5c5f 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs @@ -416,6 +416,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestAllTypes__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public TestAllTypes() { } public TestAllTypes(TestAllTypes other) { @@ -484,176 +487,258 @@ namespace Google.Protobuf.TestProtos { return new TestAllTypes(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + if (singleNestedMessage_ != null) SingleNestedMessage.Freeze(); + if (singleForeignMessage_ != null) SingleForeignMessage.Freeze(); + if (singleImportMessage_ != null) SingleImportMessage.Freeze(); + if (singlePublicImportMessage_ != null) SinglePublicImportMessage.Freeze(); + repeatedInt32_.Freeze(); + repeatedInt64_.Freeze(); + repeatedUint32_.Freeze(); + repeatedUint64_.Freeze(); + repeatedSint32_.Freeze(); + repeatedSint64_.Freeze(); + repeatedFixed32_.Freeze(); + repeatedFixed64_.Freeze(); + repeatedSfixed32_.Freeze(); + repeatedSfixed64_.Freeze(); + repeatedFloat_.Freeze(); + repeatedDouble_.Freeze(); + repeatedBool_.Freeze(); + repeatedString_.Freeze(); + repeatedBytes_.Freeze(); + repeatedNestedMessage_.Freeze(); + repeatedForeignMessage_.Freeze(); + repeatedImportMessage_.Freeze(); + repeatedNestedEnum_.Freeze(); + repeatedForeignEnum_.Freeze(); + repeatedImportEnum_.Freeze(); + repeatedPublicImportMessage_.Freeze(); + if (oneofField_ is IFreezable) ((IFreezable) oneofField_).Freeze(); + } + public const int SingleInt32FieldNumber = 1; private int singleInt32_; public int SingleInt32 { get { return singleInt32_; } - set { singleInt32_ = value; } + set { + pb::Freezable.CheckMutable(this); + singleInt32_ = value; + } } - public const int SingleInt64FieldNumber = 2; private long singleInt64_; public long SingleInt64 { get { return singleInt64_; } - set { singleInt64_ = value; } + set { + pb::Freezable.CheckMutable(this); + singleInt64_ = value; + } } - public const int SingleUint32FieldNumber = 3; private uint singleUint32_; public uint SingleUint32 { get { return singleUint32_; } - set { singleUint32_ = value; } + set { + pb::Freezable.CheckMutable(this); + singleUint32_ = value; + } } - public const int SingleUint64FieldNumber = 4; private ulong singleUint64_; public ulong SingleUint64 { get { return singleUint64_; } - set { singleUint64_ = value; } + set { + pb::Freezable.CheckMutable(this); + singleUint64_ = value; + } } - public const int SingleSint32FieldNumber = 5; private int singleSint32_; public int SingleSint32 { get { return singleSint32_; } - set { singleSint32_ = value; } + set { + pb::Freezable.CheckMutable(this); + singleSint32_ = value; + } } - public const int SingleSint64FieldNumber = 6; private long singleSint64_; public long SingleSint64 { get { return singleSint64_; } - set { singleSint64_ = value; } + set { + pb::Freezable.CheckMutable(this); + singleSint64_ = value; + } } - public const int SingleFixed32FieldNumber = 7; private uint singleFixed32_; public uint SingleFixed32 { get { return singleFixed32_; } - set { singleFixed32_ = value; } + set { + pb::Freezable.CheckMutable(this); + singleFixed32_ = value; + } } - public const int SingleFixed64FieldNumber = 8; private ulong singleFixed64_; public ulong SingleFixed64 { get { return singleFixed64_; } - set { singleFixed64_ = value; } + set { + pb::Freezable.CheckMutable(this); + singleFixed64_ = value; + } } - public const int SingleSfixed32FieldNumber = 9; private int singleSfixed32_; public int SingleSfixed32 { get { return singleSfixed32_; } - set { singleSfixed32_ = value; } + set { + pb::Freezable.CheckMutable(this); + singleSfixed32_ = value; + } } - public const int SingleSfixed64FieldNumber = 10; private long singleSfixed64_; public long SingleSfixed64 { get { return singleSfixed64_; } - set { singleSfixed64_ = value; } + set { + pb::Freezable.CheckMutable(this); + singleSfixed64_ = value; + } } - public const int SingleFloatFieldNumber = 11; private float singleFloat_; public float SingleFloat { get { return singleFloat_; } - set { singleFloat_ = value; } + set { + pb::Freezable.CheckMutable(this); + singleFloat_ = value; + } } - public const int SingleDoubleFieldNumber = 12; private double singleDouble_; public double SingleDouble { get { return singleDouble_; } - set { singleDouble_ = value; } + set { + pb::Freezable.CheckMutable(this); + singleDouble_ = value; + } } - public const int SingleBoolFieldNumber = 13; private bool singleBool_; public bool SingleBool { get { return singleBool_; } - set { singleBool_ = value; } + set { + pb::Freezable.CheckMutable(this); + singleBool_ = value; + } } - public const int SingleStringFieldNumber = 14; private string singleString_ = ""; public string SingleString { get { return singleString_; } - set { singleString_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + singleString_ = value ?? ""; + } } - public const int SingleBytesFieldNumber = 15; private pb::ByteString singleBytes_ = pb::ByteString.Empty; public pb::ByteString SingleBytes { get { return singleBytes_; } - set { singleBytes_ = value ?? pb::ByteString.Empty; } + set { + pb::Freezable.CheckMutable(this); + singleBytes_ = value ?? pb::ByteString.Empty; + } } - public const int SingleNestedMessageFieldNumber = 18; private global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage singleNestedMessage_; public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage SingleNestedMessage { get { return singleNestedMessage_; } - set { singleNestedMessage_ = value; } + set { + pb::Freezable.CheckMutable(this); + singleNestedMessage_ = value; + } } public const int SingleForeignMessageFieldNumber = 19; private global::Google.Protobuf.TestProtos.ForeignMessage singleForeignMessage_; public global::Google.Protobuf.TestProtos.ForeignMessage SingleForeignMessage { get { return singleForeignMessage_; } - set { singleForeignMessage_ = value; } + set { + pb::Freezable.CheckMutable(this); + singleForeignMessage_ = value; + } } public const int SingleImportMessageFieldNumber = 20; private global::Google.Protobuf.TestProtos.ImportMessage singleImportMessage_; public global::Google.Protobuf.TestProtos.ImportMessage SingleImportMessage { get { return singleImportMessage_; } - set { singleImportMessage_ = value; } + set { + pb::Freezable.CheckMutable(this); + singleImportMessage_ = value; + } } public const int SingleNestedEnumFieldNumber = 21; private global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum singleNestedEnum_ = global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.NESTED_ENUM_UNSPECIFIED; public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum SingleNestedEnum { get { return singleNestedEnum_; } - set { singleNestedEnum_ = value; } + set { + pb::Freezable.CheckMutable(this); + singleNestedEnum_ = value; + } } - public const int SingleForeignEnumFieldNumber = 22; private global::Google.Protobuf.TestProtos.ForeignEnum singleForeignEnum_ = global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED; public global::Google.Protobuf.TestProtos.ForeignEnum SingleForeignEnum { get { return singleForeignEnum_; } - set { singleForeignEnum_ = value; } + set { + pb::Freezable.CheckMutable(this); + singleForeignEnum_ = value; + } } - public const int SingleImportEnumFieldNumber = 23; private global::Google.Protobuf.TestProtos.ImportEnum singleImportEnum_ = global::Google.Protobuf.TestProtos.ImportEnum.IMPORT_ENUM_UNSPECIFIED; public global::Google.Protobuf.TestProtos.ImportEnum SingleImportEnum { get { return singleImportEnum_; } - set { singleImportEnum_ = value; } + set { + pb::Freezable.CheckMutable(this); + singleImportEnum_ = value; + } } - public const int SinglePublicImportMessageFieldNumber = 26; private global::Google.Protobuf.TestProtos.PublicImportMessage singlePublicImportMessage_; public global::Google.Protobuf.TestProtos.PublicImportMessage SinglePublicImportMessage { get { return singlePublicImportMessage_; } - set { singlePublicImportMessage_ = value; } + set { + pb::Freezable.CheckMutable(this); + singlePublicImportMessage_ = value; + } } public const int RepeatedInt32FieldNumber = 31; @@ -792,6 +877,7 @@ namespace Google.Protobuf.TestProtos { public uint OneofUint32 { get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32 ? (uint) oneofField_ : 0; } set { + pb::Freezable.CheckMutable(this); oneofField_ = value; oneofFieldCase_ = OneofFieldOneofCase.OneofUint32; } @@ -801,6 +887,7 @@ namespace Google.Protobuf.TestProtos { public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage OneofNestedMessage { get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage) oneofField_ : null; } set { + pb::Freezable.CheckMutable(this); oneofField_ = value; oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.OneofNestedMessage; } @@ -810,6 +897,7 @@ namespace Google.Protobuf.TestProtos { public string OneofString { get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) oneofField_ : ""; } set { + pb::Freezable.CheckMutable(this); oneofField_ = value ?? ""; oneofFieldCase_ = OneofFieldOneofCase.OneofString; } @@ -819,6 +907,7 @@ namespace Google.Protobuf.TestProtos { public pb::ByteString OneofBytes { get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; } set { + pb::Freezable.CheckMutable(this); oneofField_ = value ?? pb::ByteString.Empty; oneofFieldCase_ = OneofFieldOneofCase.OneofBytes; } @@ -838,6 +927,7 @@ namespace Google.Protobuf.TestProtos { } public void ClearOneofField() { + pb::Freezable.CheckMutable(this); oneofFieldCase_ = OneofFieldOneofCase.None; oneofField_ = null; } @@ -868,10 +958,14 @@ namespace Google.Protobuf.TestProtos { if (SingleBool != other.SingleBool) return false; if (SingleString != other.SingleString) return false; if (SingleBytes != other.SingleBytes) return false; - if (!object.Equals(SingleNestedMessage, other.SingleNestedMessage)) return false;if (!object.Equals(SingleForeignMessage, other.SingleForeignMessage)) return false;if (!object.Equals(SingleImportMessage, other.SingleImportMessage)) return false;if (SingleNestedEnum != other.SingleNestedEnum) return false; + if (!object.Equals(SingleNestedMessage, other.SingleNestedMessage)) return false; + if (!object.Equals(SingleForeignMessage, other.SingleForeignMessage)) return false; + if (!object.Equals(SingleImportMessage, other.SingleImportMessage)) return false; + if (SingleNestedEnum != other.SingleNestedEnum) return false; if (SingleForeignEnum != other.SingleForeignEnum) return false; if (SingleImportEnum != other.SingleImportEnum) return false; - if (!object.Equals(SinglePublicImportMessage, other.SinglePublicImportMessage)) return false;if(!repeatedInt32_.Equals(other.repeatedInt32_)) return false; + if (!object.Equals(SinglePublicImportMessage, other.SinglePublicImportMessage)) return false; + if(!repeatedInt32_.Equals(other.repeatedInt32_)) return false; if(!repeatedInt64_.Equals(other.repeatedInt64_)) return false; if(!repeatedUint32_.Equals(other.repeatedUint32_)) return false; if(!repeatedUint64_.Equals(other.repeatedUint64_)) return false; @@ -894,7 +988,8 @@ namespace Google.Protobuf.TestProtos { if(!repeatedImportEnum_.Equals(other.repeatedImportEnum_)) return false; if(!repeatedPublicImportMessage_.Equals(other.repeatedPublicImportMessage_)) return false; if (OneofUint32 != other.OneofUint32) return false; - if (!object.Equals(OneofNestedMessage, other.OneofNestedMessage)) return false;if (OneofString != other.OneofString) return false; + if (!object.Equals(OneofNestedMessage, other.OneofNestedMessage)) return false; + if (OneofString != other.OneofString) return false; if (OneofBytes != other.OneofBytes) return false; return true; } @@ -1764,6 +1859,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestAllTypes_NestedMessage__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public NestedMessage() { } public NestedMessage(NestedMessage other) { @@ -1774,14 +1872,23 @@ namespace Google.Protobuf.TestProtos { return new NestedMessage(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int BbFieldNumber = 1; private int bb_; public int Bb { get { return bb_; } - set { bb_ = value; } + set { + pb::Freezable.CheckMutable(this); + bb_ = value; + } } - public override bool Equals(object other) { return Equals(other as NestedMessage); } @@ -1867,6 +1974,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_NestedTestAllTypes__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public NestedTestAllTypes() { } public NestedTestAllTypes(NestedTestAllTypes other) { @@ -1879,18 +1989,34 @@ namespace Google.Protobuf.TestProtos { return new NestedTestAllTypes(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + if (child_ != null) Child.Freeze(); + if (payload_ != null) Payload.Freeze(); + repeatedChild_.Freeze(); + } + public const int ChildFieldNumber = 1; private global::Google.Protobuf.TestProtos.NestedTestAllTypes child_; public global::Google.Protobuf.TestProtos.NestedTestAllTypes Child { get { return child_; } - set { child_ = value; } + set { + pb::Freezable.CheckMutable(this); + child_ = value; + } } public const int PayloadFieldNumber = 2; private global::Google.Protobuf.TestProtos.TestAllTypes payload_; public global::Google.Protobuf.TestProtos.TestAllTypes Payload { get { return payload_; } - set { payload_ = value; } + set { + pb::Freezable.CheckMutable(this); + payload_ = value; + } } public const int RepeatedChildFieldNumber = 3; @@ -1910,7 +2036,9 @@ namespace Google.Protobuf.TestProtos { if (ReferenceEquals(other, this)) { return true; } - if (!object.Equals(Child, other.Child)) return false;if (!object.Equals(Payload, other.Payload)) return false;if(!repeatedChild_.Equals(other.repeatedChild_)) return false; + if (!object.Equals(Child, other.Child)) return false; + if (!object.Equals(Payload, other.Payload)) return false; + if(!repeatedChild_.Equals(other.repeatedChild_)) return false; return true; } @@ -2021,6 +2149,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestDeprecatedFields__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public TestDeprecatedFields() { } public TestDeprecatedFields(TestDeprecatedFields other) { @@ -2031,15 +2162,24 @@ namespace Google.Protobuf.TestProtos { return new TestDeprecatedFields(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int DeprecatedInt32FieldNumber = 1; private int deprecatedInt32_; [global::System.ObsoleteAttribute()] public int DeprecatedInt32 { get { return deprecatedInt32_; } - set { deprecatedInt32_ = value; } + set { + pb::Freezable.CheckMutable(this); + deprecatedInt32_ = value; + } } - public override bool Equals(object other) { return Equals(other as TestDeprecatedFields); } @@ -2120,6 +2260,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_ForeignMessage__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public ForeignMessage() { } public ForeignMessage(ForeignMessage other) { @@ -2130,14 +2273,23 @@ namespace Google.Protobuf.TestProtos { return new ForeignMessage(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int CFieldNumber = 1; private int c_; public int C { get { return c_; } - set { c_ = value; } + set { + pb::Freezable.CheckMutable(this); + c_ = value; + } } - public override bool Equals(object other) { return Equals(other as ForeignMessage); } @@ -2218,6 +2370,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestReservedFields__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public TestReservedFields() { } public TestReservedFields(TestReservedFields other) { @@ -2227,6 +2382,13 @@ namespace Google.Protobuf.TestProtos { return new TestReservedFields(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public override bool Equals(object other) { return Equals(other as TestReservedFields); } @@ -2291,6 +2453,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestForeignNested__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public TestForeignNested() { } public TestForeignNested(TestForeignNested other) { @@ -2301,11 +2466,22 @@ namespace Google.Protobuf.TestProtos { return new TestForeignNested(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + if (foreignNested_ != null) ForeignNested.Freeze(); + } + public const int ForeignNestedFieldNumber = 1; private global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage foreignNested_; public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage ForeignNested { get { return foreignNested_; } - set { foreignNested_ = value; } + set { + pb::Freezable.CheckMutable(this); + foreignNested_ = value; + } } public override bool Equals(object other) { @@ -2319,7 +2495,8 @@ namespace Google.Protobuf.TestProtos { if (ReferenceEquals(other, this)) { return true; } - if (!object.Equals(ForeignNested, other.ForeignNested)) return false; return true; + if (!object.Equals(ForeignNested, other.ForeignNested)) return false; + return true; } public override int GetHashCode() { @@ -2393,6 +2570,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestReallyLargeTagNumber__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public TestReallyLargeTagNumber() { } public TestReallyLargeTagNumber(TestReallyLargeTagNumber other) { @@ -2404,22 +2584,33 @@ namespace Google.Protobuf.TestProtos { return new TestReallyLargeTagNumber(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int AFieldNumber = 1; private int a_; public int A { get { return a_; } - set { a_ = value; } + set { + pb::Freezable.CheckMutable(this); + a_ = value; + } } - public const int BbFieldNumber = 268435455; private int bb_; public int Bb { get { return bb_; } - set { bb_ = value; } + set { + pb::Freezable.CheckMutable(this); + bb_ = value; + } } - public override bool Equals(object other) { return Equals(other as TestReallyLargeTagNumber); } @@ -2516,6 +2707,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestRecursiveMessage__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public TestRecursiveMessage() { } public TestRecursiveMessage(TestRecursiveMessage other) { @@ -2527,21 +2721,34 @@ namespace Google.Protobuf.TestProtos { return new TestRecursiveMessage(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + if (a_ != null) A.Freeze(); + } + public const int AFieldNumber = 1; private global::Google.Protobuf.TestProtos.TestRecursiveMessage a_; public global::Google.Protobuf.TestProtos.TestRecursiveMessage A { get { return a_; } - set { a_ = value; } + set { + pb::Freezable.CheckMutable(this); + a_ = value; + } } public const int IFieldNumber = 2; private int i_; public int I { get { return i_; } - set { i_ = value; } + set { + pb::Freezable.CheckMutable(this); + i_ = value; + } } - public override bool Equals(object other) { return Equals(other as TestRecursiveMessage); } @@ -2553,7 +2760,8 @@ namespace Google.Protobuf.TestProtos { if (ReferenceEquals(other, this)) { return true; } - if (!object.Equals(A, other.A)) return false;if (I != other.I) return false; + if (!object.Equals(A, other.A)) return false; + if (I != other.I) return false; return true; } @@ -2643,6 +2851,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestMutualRecursionA__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public TestMutualRecursionA() { } public TestMutualRecursionA(TestMutualRecursionA other) { @@ -2653,11 +2864,22 @@ namespace Google.Protobuf.TestProtos { return new TestMutualRecursionA(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + if (bb_ != null) Bb.Freeze(); + } + public const int BbFieldNumber = 1; private global::Google.Protobuf.TestProtos.TestMutualRecursionB bb_; public global::Google.Protobuf.TestProtos.TestMutualRecursionB Bb { get { return bb_; } - set { bb_ = value; } + set { + pb::Freezable.CheckMutable(this); + bb_ = value; + } } public override bool Equals(object other) { @@ -2671,7 +2893,8 @@ namespace Google.Protobuf.TestProtos { if (ReferenceEquals(other, this)) { return true; } - if (!object.Equals(Bb, other.Bb)) return false; return true; + if (!object.Equals(Bb, other.Bb)) return false; + return true; } public override int GetHashCode() { @@ -2745,6 +2968,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestMutualRecursionB__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public TestMutualRecursionB() { } public TestMutualRecursionB(TestMutualRecursionB other) { @@ -2756,21 +2982,34 @@ namespace Google.Protobuf.TestProtos { return new TestMutualRecursionB(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + if (a_ != null) A.Freeze(); + } + public const int AFieldNumber = 1; private global::Google.Protobuf.TestProtos.TestMutualRecursionA a_; public global::Google.Protobuf.TestProtos.TestMutualRecursionA A { get { return a_; } - set { a_ = value; } + set { + pb::Freezable.CheckMutable(this); + a_ = value; + } } public const int OptionalInt32FieldNumber = 2; private int optionalInt32_; public int OptionalInt32 { get { return optionalInt32_; } - set { optionalInt32_ = value; } + set { + pb::Freezable.CheckMutable(this); + optionalInt32_ = value; + } } - public override bool Equals(object other) { return Equals(other as TestMutualRecursionB); } @@ -2782,7 +3021,8 @@ namespace Google.Protobuf.TestProtos { if (ReferenceEquals(other, this)) { return true; } - if (!object.Equals(A, other.A)) return false;if (OptionalInt32 != other.OptionalInt32) return false; + if (!object.Equals(A, other.A)) return false; + if (OptionalInt32 != other.OptionalInt32) return false; return true; } @@ -2872,6 +3112,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestCamelCaseFieldNames__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public TestCamelCaseFieldNames() { } public TestCamelCaseFieldNames(TestCamelCaseFieldNames other) { @@ -2889,35 +3132,56 @@ namespace Google.Protobuf.TestProtos { return new TestCamelCaseFieldNames(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + if (messageField_ != null) MessageField.Freeze(); + repeatedPrimitiveField_.Freeze(); + repeatedStringField_.Freeze(); + repeatedEnumField_.Freeze(); + repeatedMessageField_.Freeze(); + } + public const int PrimitiveFieldFieldNumber = 1; private int primitiveField_; public int PrimitiveField { get { return primitiveField_; } - set { primitiveField_ = value; } + set { + pb::Freezable.CheckMutable(this); + primitiveField_ = value; + } } - public const int StringFieldFieldNumber = 2; private string stringField_ = ""; public string StringField { get { return stringField_; } - set { stringField_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + stringField_ = value ?? ""; + } } - public const int EnumFieldFieldNumber = 3; private global::Google.Protobuf.TestProtos.ForeignEnum enumField_ = global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED; public global::Google.Protobuf.TestProtos.ForeignEnum EnumField { get { return enumField_; } - set { enumField_ = value; } + set { + pb::Freezable.CheckMutable(this); + enumField_ = value; + } } - public const int MessageFieldFieldNumber = 4; private global::Google.Protobuf.TestProtos.ForeignMessage messageField_; public global::Google.Protobuf.TestProtos.ForeignMessage MessageField { get { return messageField_; } - set { messageField_ = value; } + set { + pb::Freezable.CheckMutable(this); + messageField_ = value; + } } public const int RepeatedPrimitiveFieldFieldNumber = 7; @@ -2958,7 +3222,8 @@ namespace Google.Protobuf.TestProtos { if (PrimitiveField != other.PrimitiveField) return false; if (StringField != other.StringField) return false; if (EnumField != other.EnumField) return false; - if (!object.Equals(MessageField, other.MessageField)) return false;if(!repeatedPrimitiveField_.Equals(other.repeatedPrimitiveField_)) return false; + if (!object.Equals(MessageField, other.MessageField)) return false; + if(!repeatedPrimitiveField_.Equals(other.repeatedPrimitiveField_)) return false; if(!repeatedStringField_.Equals(other.repeatedStringField_)) return false; if(!repeatedEnumField_.Equals(other.repeatedEnumField_)) return false; if(!repeatedMessageField_.Equals(other.repeatedMessageField_)) return false; @@ -3151,6 +3416,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestFieldOrderings__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public TestFieldOrderings() { } public TestFieldOrderings(TestFieldOrderings other) { @@ -3164,35 +3432,52 @@ namespace Google.Protobuf.TestProtos { return new TestFieldOrderings(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + if (singleNestedMessage_ != null) SingleNestedMessage.Freeze(); + } + public const int MyStringFieldNumber = 11; private string myString_ = ""; public string MyString { get { return myString_; } - set { myString_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + myString_ = value ?? ""; + } } - public const int MyIntFieldNumber = 1; private long myInt_; public long MyInt { get { return myInt_; } - set { myInt_ = value; } + set { + pb::Freezable.CheckMutable(this); + myInt_ = value; + } } - public const int MyFloatFieldNumber = 101; private float myFloat_; public float MyFloat { get { return myFloat_; } - set { myFloat_ = value; } + set { + pb::Freezable.CheckMutable(this); + myFloat_ = value; + } } - public const int SingleNestedMessageFieldNumber = 200; private global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage singleNestedMessage_; public global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage SingleNestedMessage { get { return singleNestedMessage_; } - set { singleNestedMessage_ = value; } + set { + pb::Freezable.CheckMutable(this); + singleNestedMessage_ = value; + } } public override bool Equals(object other) { @@ -3209,7 +3494,8 @@ namespace Google.Protobuf.TestProtos { if (MyString != other.MyString) return false; if (MyInt != other.MyInt) return false; if (MyFloat != other.MyFloat) return false; - if (!object.Equals(SingleNestedMessage, other.SingleNestedMessage)) return false; return true; + if (!object.Equals(SingleNestedMessage, other.SingleNestedMessage)) return false; + return true; } public override int GetHashCode() { @@ -3329,6 +3615,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestFieldOrderings_NestedMessage__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public NestedMessage() { } public NestedMessage(NestedMessage other) { @@ -3340,22 +3629,33 @@ namespace Google.Protobuf.TestProtos { return new NestedMessage(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int OoFieldNumber = 2; private long oo_; public long Oo { get { return oo_; } - set { oo_ = value; } + set { + pb::Freezable.CheckMutable(this); + oo_ = value; + } } - public const int BbFieldNumber = 1; private int bb_; public int Bb { get { return bb_; } - set { bb_ = value; } + set { + pb::Freezable.CheckMutable(this); + bb_ = value; + } } - public override bool Equals(object other) { return Equals(other as NestedMessage); } @@ -3457,6 +3757,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_SparseEnumMessage__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public SparseEnumMessage() { } public SparseEnumMessage(SparseEnumMessage other) { @@ -3467,14 +3770,23 @@ namespace Google.Protobuf.TestProtos { return new SparseEnumMessage(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int SparseEnumFieldNumber = 1; private global::Google.Protobuf.TestProtos.TestSparseEnum sparseEnum_ = global::Google.Protobuf.TestProtos.TestSparseEnum.TEST_SPARSE_ENUM_UNSPECIFIED; public global::Google.Protobuf.TestProtos.TestSparseEnum SparseEnum { get { return sparseEnum_; } - set { sparseEnum_ = value; } + set { + pb::Freezable.CheckMutable(this); + sparseEnum_ = value; + } } - public override bool Equals(object other) { return Equals(other as SparseEnumMessage); } @@ -3555,6 +3867,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_OneString__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public OneString() { } public OneString(OneString other) { @@ -3565,14 +3880,23 @@ namespace Google.Protobuf.TestProtos { return new OneString(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int DataFieldNumber = 1; private string data_ = ""; public string Data { get { return data_; } - set { data_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + data_ = value ?? ""; + } } - public override bool Equals(object other) { return Equals(other as OneString); } @@ -3653,6 +3977,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_MoreString__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public MoreString() { } public MoreString(MoreString other) { @@ -3663,6 +3990,14 @@ namespace Google.Protobuf.TestProtos { return new MoreString(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + data_.Freeze(); + } + public const int DataFieldNumber = 1; private readonly pbc::RepeatedField data_ = new pbc::RepeatedField(); public pbc::RepeatedField Data { @@ -3751,6 +4086,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_OneBytes__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public OneBytes() { } public OneBytes(OneBytes other) { @@ -3761,14 +4099,23 @@ namespace Google.Protobuf.TestProtos { return new OneBytes(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int DataFieldNumber = 1; private pb::ByteString data_ = pb::ByteString.Empty; public pb::ByteString Data { get { return data_; } - set { data_ = value ?? pb::ByteString.Empty; } + set { + pb::Freezable.CheckMutable(this); + data_ = value ?? pb::ByteString.Empty; + } } - public override bool Equals(object other) { return Equals(other as OneBytes); } @@ -3849,6 +4196,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_MoreBytes__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public MoreBytes() { } public MoreBytes(MoreBytes other) { @@ -3859,14 +4209,23 @@ namespace Google.Protobuf.TestProtos { return new MoreBytes(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int DataFieldNumber = 1; private pb::ByteString data_ = pb::ByteString.Empty; public pb::ByteString Data { get { return data_; } - set { data_ = value ?? pb::ByteString.Empty; } + set { + pb::Freezable.CheckMutable(this); + data_ = value ?? pb::ByteString.Empty; + } } - public override bool Equals(object other) { return Equals(other as MoreBytes); } @@ -3947,6 +4306,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_Int32Message__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public Int32Message() { } public Int32Message(Int32Message other) { @@ -3957,14 +4319,23 @@ namespace Google.Protobuf.TestProtos { return new Int32Message(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int DataFieldNumber = 1; private int data_; public int Data { get { return data_; } - set { data_ = value; } + set { + pb::Freezable.CheckMutable(this); + data_ = value; + } } - public override bool Equals(object other) { return Equals(other as Int32Message); } @@ -4045,6 +4416,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_Uint32Message__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public Uint32Message() { } public Uint32Message(Uint32Message other) { @@ -4055,14 +4429,23 @@ namespace Google.Protobuf.TestProtos { return new Uint32Message(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int DataFieldNumber = 1; private uint data_; public uint Data { get { return data_; } - set { data_ = value; } + set { + pb::Freezable.CheckMutable(this); + data_ = value; + } } - public override bool Equals(object other) { return Equals(other as Uint32Message); } @@ -4143,6 +4526,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_Int64Message__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public Int64Message() { } public Int64Message(Int64Message other) { @@ -4153,14 +4539,23 @@ namespace Google.Protobuf.TestProtos { return new Int64Message(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int DataFieldNumber = 1; private long data_; public long Data { get { return data_; } - set { data_ = value; } + set { + pb::Freezable.CheckMutable(this); + data_ = value; + } } - public override bool Equals(object other) { return Equals(other as Int64Message); } @@ -4241,6 +4636,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_Uint64Message__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public Uint64Message() { } public Uint64Message(Uint64Message other) { @@ -4251,14 +4649,23 @@ namespace Google.Protobuf.TestProtos { return new Uint64Message(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int DataFieldNumber = 1; private ulong data_; public ulong Data { get { return data_; } - set { data_ = value; } + set { + pb::Freezable.CheckMutable(this); + data_ = value; + } } - public override bool Equals(object other) { return Equals(other as Uint64Message); } @@ -4339,6 +4746,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_BoolMessage__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public BoolMessage() { } public BoolMessage(BoolMessage other) { @@ -4349,14 +4759,23 @@ namespace Google.Protobuf.TestProtos { return new BoolMessage(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int DataFieldNumber = 1; private bool data_; public bool Data { get { return data_; } - set { data_ = value; } + set { + pb::Freezable.CheckMutable(this); + data_ = value; + } } - public override bool Equals(object other) { return Equals(other as BoolMessage); } @@ -4437,6 +4856,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestOneof__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public TestOneof() { } public TestOneof(TestOneof other) { @@ -4458,10 +4880,19 @@ namespace Google.Protobuf.TestProtos { return new TestOneof(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + if (foo_ is IFreezable) ((IFreezable) foo_).Freeze(); + } + public const int FooIntFieldNumber = 1; public int FooInt { get { return fooCase_ == FooOneofCase.FooInt ? (int) foo_ : 0; } set { + pb::Freezable.CheckMutable(this); foo_ = value; fooCase_ = FooOneofCase.FooInt; } @@ -4471,6 +4902,7 @@ namespace Google.Protobuf.TestProtos { public string FooString { get { return fooCase_ == FooOneofCase.FooString ? (string) foo_ : ""; } set { + pb::Freezable.CheckMutable(this); foo_ = value ?? ""; fooCase_ = FooOneofCase.FooString; } @@ -4480,6 +4912,7 @@ namespace Google.Protobuf.TestProtos { public global::Google.Protobuf.TestProtos.TestAllTypes FooMessage { get { return fooCase_ == FooOneofCase.FooMessage ? (global::Google.Protobuf.TestProtos.TestAllTypes) foo_ : null; } set { + pb::Freezable.CheckMutable(this); foo_ = value; fooCase_ = value == null ? FooOneofCase.None : FooOneofCase.FooMessage; } @@ -4498,6 +4931,7 @@ namespace Google.Protobuf.TestProtos { } public void ClearFoo() { + pb::Freezable.CheckMutable(this); fooCase_ = FooOneofCase.None; foo_ = null; } @@ -4515,7 +4949,8 @@ namespace Google.Protobuf.TestProtos { } if (FooInt != other.FooInt) return false; if (FooString != other.FooString) return false; - if (!object.Equals(FooMessage, other.FooMessage)) return false; return true; + if (!object.Equals(FooMessage, other.FooMessage)) return false; + return true; } public override int GetHashCode() { @@ -4621,6 +5056,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestPackedTypes__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public TestPackedTypes() { } public TestPackedTypes(TestPackedTypes other) { @@ -4644,6 +5082,27 @@ namespace Google.Protobuf.TestProtos { return new TestPackedTypes(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + packedInt32_.Freeze(); + packedInt64_.Freeze(); + packedUint32_.Freeze(); + packedUint64_.Freeze(); + packedSint32_.Freeze(); + packedSint64_.Freeze(); + packedFixed32_.Freeze(); + packedFixed64_.Freeze(); + packedSfixed32_.Freeze(); + packedSfixed64_.Freeze(); + packedFloat_.Freeze(); + packedDouble_.Freeze(); + packedBool_.Freeze(); + packedEnum_.Freeze(); + } + public const int PackedInt32FieldNumber = 90; private readonly pbc::RepeatedField packedInt32_ = new pbc::RepeatedField(); public pbc::RepeatedField PackedInt32 { @@ -5058,6 +5517,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestUnpackedTypes__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public TestUnpackedTypes() { } public TestUnpackedTypes(TestUnpackedTypes other) { @@ -5081,6 +5543,27 @@ namespace Google.Protobuf.TestProtos { return new TestUnpackedTypes(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + unpackedInt32_.Freeze(); + unpackedInt64_.Freeze(); + unpackedUint32_.Freeze(); + unpackedUint64_.Freeze(); + unpackedSint32_.Freeze(); + unpackedSint64_.Freeze(); + unpackedFixed32_.Freeze(); + unpackedFixed64_.Freeze(); + unpackedSfixed32_.Freeze(); + unpackedSfixed64_.Freeze(); + unpackedFloat_.Freeze(); + unpackedDouble_.Freeze(); + unpackedBool_.Freeze(); + unpackedEnum_.Freeze(); + } + public const int UnpackedInt32FieldNumber = 90; private readonly pbc::RepeatedField unpackedInt32_ = new pbc::RepeatedField(); public pbc::RepeatedField UnpackedInt32 { @@ -5481,6 +5964,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestRepeatedScalarDifferentTagSizes__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public TestRepeatedScalarDifferentTagSizes() { } public TestRepeatedScalarDifferentTagSizes(TestRepeatedScalarDifferentTagSizes other) { @@ -5496,6 +5982,19 @@ namespace Google.Protobuf.TestProtos { return new TestRepeatedScalarDifferentTagSizes(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + repeatedFixed32_.Freeze(); + repeatedInt32_.Freeze(); + repeatedFixed64_.Freeze(); + repeatedInt64_.Freeze(); + repeatedFloat_.Freeze(); + repeatedUint64_.Freeze(); + } + public const int RepeatedFixed32FieldNumber = 12; private readonly pbc::RepeatedField repeatedFixed32_ = new pbc::RepeatedField(); public pbc::RepeatedField RepeatedFixed32 { @@ -5710,6 +6209,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_TestCommentInjectionMessage__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public TestCommentInjectionMessage() { } public TestCommentInjectionMessage(TestCommentInjectionMessage other) { @@ -5720,14 +6222,23 @@ namespace Google.Protobuf.TestProtos { return new TestCommentInjectionMessage(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int AFieldNumber = 1; private string a_ = ""; public string A { get { return a_; } - set { a_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + a_ = value ?? ""; + } } - public override bool Equals(object other) { return Equals(other as TestCommentInjectionMessage); } @@ -5808,6 +6319,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_FooRequest__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public FooRequest() { } public FooRequest(FooRequest other) { @@ -5817,6 +6331,13 @@ namespace Google.Protobuf.TestProtos { return new FooRequest(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public override bool Equals(object other) { return Equals(other as FooRequest); } @@ -5881,6 +6402,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_FooResponse__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public FooResponse() { } public FooResponse(FooResponse other) { @@ -5890,6 +6414,13 @@ namespace Google.Protobuf.TestProtos { return new FooResponse(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public override bool Equals(object other) { return Equals(other as FooResponse); } @@ -5954,6 +6485,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_FooClientMessage__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public FooClientMessage() { } public FooClientMessage(FooClientMessage other) { @@ -5963,6 +6497,13 @@ namespace Google.Protobuf.TestProtos { return new FooClientMessage(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public override bool Equals(object other) { return Equals(other as FooClientMessage); } @@ -6027,6 +6568,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_FooServerMessage__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public FooServerMessage() { } public FooServerMessage(FooServerMessage other) { @@ -6036,6 +6580,13 @@ namespace Google.Protobuf.TestProtos { return new FooServerMessage(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public override bool Equals(object other) { return Equals(other as FooServerMessage); } @@ -6100,6 +6651,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_BarRequest__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public BarRequest() { } public BarRequest(BarRequest other) { @@ -6109,6 +6663,13 @@ namespace Google.Protobuf.TestProtos { return new BarRequest(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public override bool Equals(object other) { return Equals(other as BarRequest); } @@ -6173,6 +6734,9 @@ namespace Google.Protobuf.TestProtos { get { return global::Google.Protobuf.TestProtos.UnittestProto3.internal__static_protobuf_unittest_BarResponse__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public BarResponse() { } public BarResponse(BarResponse other) { @@ -6182,6 +6746,13 @@ namespace Google.Protobuf.TestProtos { return new BarResponse(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public override bool Equals(object other) { return Equals(other as BarResponse); } diff --git a/csharp/src/ProtocolBuffers/Collections/RepeatedField.cs b/csharp/src/ProtocolBuffers/Collections/RepeatedField.cs index 5100e4dbb7..ebfc522fcb 100644 --- a/csharp/src/ProtocolBuffers/Collections/RepeatedField.cs +++ b/csharp/src/ProtocolBuffers/Collections/RepeatedField.cs @@ -4,10 +4,16 @@ using System.Collections.Generic; namespace Google.Protobuf.Collections { - public sealed class RepeatedField : IList, IEquatable> + /// + /// The contents of a repeated field: essentially, a collection with some extra + /// restrictions (no null values) and capabilities (deep cloning and freezing). + /// + /// The element type of the repeated field. + public sealed class RepeatedField : IList, IDeepCloneable>, IEquatable>, IFreezable { private static readonly T[] EmptyArray = new T[0]; + private bool frozen; private const int MinArraySize = 8; private T[] array = EmptyArray; private int count = 0; @@ -26,6 +32,7 @@ namespace Google.Protobuf.Collections public RepeatedField Clone() { RepeatedField clone = new RepeatedField(); + // Clone is implicitly *not* frozen, even if this object is. if (array != EmptyArray) { clone.array = (T[])array.Clone(); @@ -42,6 +49,21 @@ namespace Google.Protobuf.Collections return clone; } + public bool IsFrozen { get { return frozen; } } + + public void Freeze() + { + frozen = true; + IFreezable[] freezableArray = array as IFreezable[]; + if (freezableArray != null) + { + for (int i = 0; i < count; i++) + { + freezableArray[i].Freeze(); + } + } + } + private void EnsureSize(int size) { size = Math.Max(size, MinArraySize); @@ -60,6 +82,7 @@ namespace Google.Protobuf.Collections { throw new ArgumentNullException("item"); } + this.CheckMutable(); EnsureSize(count + 1); array[count++] = item; } @@ -70,6 +93,7 @@ namespace Google.Protobuf.Collections /// internal void AddInt32(int item) { + this.CheckMutable(); EnsureSize(count + 1); int[] castArray = (int[]) (object) array; castArray[count++] = item; @@ -77,6 +101,7 @@ namespace Google.Protobuf.Collections public void Clear() { + this.CheckMutable(); array = EmptyArray; count = 0; } @@ -93,6 +118,7 @@ namespace Google.Protobuf.Collections public bool Remove(T item) { + this.CheckMutable(); int index = IndexOf(item); if (index == -1) { @@ -107,7 +133,7 @@ namespace Google.Protobuf.Collections public int Count { get { return count; } } // TODO(jonskeet): If we implement freezing, make this reflect it. - public bool IsReadOnly { get { return false; } } + public bool IsReadOnly { get { return IsFrozen; } } public void Add(RepeatedField values) { @@ -115,6 +141,7 @@ namespace Google.Protobuf.Collections { throw new ArgumentNullException("values"); } + this.CheckMutable(); EnsureSize(count + values.count); // We know that all the values will be valid, because it's a RepeatedField. Array.Copy(values.array, 0, array, count, values.count); @@ -127,6 +154,7 @@ namespace Google.Protobuf.Collections { throw new ArgumentNullException("values"); } + this.CheckMutable(); // TODO: Check for ICollection and get the Count? foreach (T item in values) { @@ -227,6 +255,7 @@ namespace Google.Protobuf.Collections { throw new ArgumentOutOfRangeException("index"); } + this.CheckMutable(); EnsureSize(count + 1); Array.Copy(array, index, array, index + 1, count - index); count++; @@ -238,6 +267,7 @@ namespace Google.Protobuf.Collections { throw new ArgumentOutOfRangeException("index"); } + this.CheckMutable(); Array.Copy(array, index + 1, array, index, count - index - 1); count--; array[count] = default(T); @@ -259,6 +289,7 @@ namespace Google.Protobuf.Collections { throw new ArgumentOutOfRangeException("index"); } + this.CheckMutable(); if (value == null) { throw new ArgumentNullException("value"); diff --git a/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs b/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs index 23d5e9648b..eedb21fe3a 100644 --- a/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs +++ b/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs @@ -292,6 +292,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FileDescriptorSet__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public FileDescriptorSet() { } public FileDescriptorSet(FileDescriptorSet other) { @@ -302,6 +305,14 @@ namespace Google.Protobuf.DescriptorProtos { return new FileDescriptorSet(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + file_.Freeze(); + } + public const int FileFieldNumber = 1; private readonly pbc::RepeatedField file_ = new pbc::RepeatedField(); public pbc::RepeatedField File { @@ -388,6 +399,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FileDescriptorProto__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public FileDescriptorProto() { } public FileDescriptorProto(FileDescriptorProto other) { @@ -409,22 +423,42 @@ namespace Google.Protobuf.DescriptorProtos { return new FileDescriptorProto(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + dependency_.Freeze(); + publicDependency_.Freeze(); + weakDependency_.Freeze(); + messageType_.Freeze(); + enumType_.Freeze(); + service_.Freeze(); + extension_.Freeze(); + if (options_ != null) Options.Freeze(); + if (sourceCodeInfo_ != null) SourceCodeInfo.Freeze(); + } + public const int NameFieldNumber = 1; private string name_ = ""; public string Name { get { return name_; } - set { name_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + name_ = value ?? ""; + } } - public const int PackageFieldNumber = 2; private string package_ = ""; public string Package { get { return package_; } - set { package_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + package_ = value ?? ""; + } } - public const int DependencyFieldNumber = 3; private readonly pbc::RepeatedField dependency_ = new pbc::RepeatedField(); public pbc::RepeatedField Dependency { @@ -471,24 +505,32 @@ namespace Google.Protobuf.DescriptorProtos { private global::Google.Protobuf.DescriptorProtos.FileOptions options_; public global::Google.Protobuf.DescriptorProtos.FileOptions Options { get { return options_; } - set { options_ = value; } + set { + pb::Freezable.CheckMutable(this); + options_ = value; + } } public const int SourceCodeInfoFieldNumber = 9; private global::Google.Protobuf.DescriptorProtos.SourceCodeInfo sourceCodeInfo_; public global::Google.Protobuf.DescriptorProtos.SourceCodeInfo SourceCodeInfo { get { return sourceCodeInfo_; } - set { sourceCodeInfo_ = value; } + set { + pb::Freezable.CheckMutable(this); + sourceCodeInfo_ = value; + } } public const int SyntaxFieldNumber = 12; private string syntax_ = ""; public string Syntax { get { return syntax_; } - set { syntax_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + syntax_ = value ?? ""; + } } - public override bool Equals(object other) { return Equals(other as FileDescriptorProto); } @@ -509,7 +551,9 @@ namespace Google.Protobuf.DescriptorProtos { if(!enumType_.Equals(other.enumType_)) return false; if(!service_.Equals(other.service_)) return false; if(!extension_.Equals(other.extension_)) return false; - if (!object.Equals(Options, other.Options)) return false;if (!object.Equals(SourceCodeInfo, other.SourceCodeInfo)) return false;if (Syntax != other.Syntax) return false; + if (!object.Equals(Options, other.Options)) return false; + if (!object.Equals(SourceCodeInfo, other.SourceCodeInfo)) return false; + if (Syntax != other.Syntax) return false; return true; } @@ -763,6 +807,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_DescriptorProto__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public DescriptorProto() { } public DescriptorProto(DescriptorProto other) { @@ -782,14 +829,32 @@ namespace Google.Protobuf.DescriptorProtos { return new DescriptorProto(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + field_.Freeze(); + extension_.Freeze(); + nestedType_.Freeze(); + enumType_.Freeze(); + extensionRange_.Freeze(); + oneofDecl_.Freeze(); + if (options_ != null) Options.Freeze(); + reservedRange_.Freeze(); + reservedName_.Freeze(); + } + public const int NameFieldNumber = 1; private string name_ = ""; public string Name { get { return name_; } - set { name_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + name_ = value ?? ""; + } } - public const int FieldFieldNumber = 2; private readonly pbc::RepeatedField field_ = new pbc::RepeatedField(); public pbc::RepeatedField Field { @@ -830,7 +895,10 @@ namespace Google.Protobuf.DescriptorProtos { private global::Google.Protobuf.DescriptorProtos.MessageOptions options_; public global::Google.Protobuf.DescriptorProtos.MessageOptions Options { get { return options_; } - set { options_ = value; } + set { + pb::Freezable.CheckMutable(this); + options_ = value; + } } public const int ReservedRangeFieldNumber = 9; @@ -863,7 +931,8 @@ namespace Google.Protobuf.DescriptorProtos { if(!enumType_.Equals(other.enumType_)) return false; if(!extensionRange_.Equals(other.extensionRange_)) return false; if(!oneofDecl_.Equals(other.oneofDecl_)) return false; - if (!object.Equals(Options, other.Options)) return false;if(!reservedRange_.Equals(other.reservedRange_)) return false; + if (!object.Equals(Options, other.Options)) return false; + if(!reservedRange_.Equals(other.reservedRange_)) return false; if(!reservedName_.Equals(other.reservedName_)) return false; return true; } @@ -1077,6 +1146,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_DescriptorProto_ExtensionRange__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public ExtensionRange() { } public ExtensionRange(ExtensionRange other) { @@ -1088,22 +1160,33 @@ namespace Google.Protobuf.DescriptorProtos { return new ExtensionRange(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int StartFieldNumber = 1; private int start_; public int Start { get { return start_; } - set { start_ = value; } + set { + pb::Freezable.CheckMutable(this); + start_ = value; + } } - public const int EndFieldNumber = 2; private int end_; public int End { get { return end_; } - set { end_ = value; } + set { + pb::Freezable.CheckMutable(this); + end_ = value; + } } - public override bool Equals(object other) { return Equals(other as ExtensionRange); } @@ -1200,6 +1283,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_DescriptorProto_ReservedRange__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public ReservedRange() { } public ReservedRange(ReservedRange other) { @@ -1211,22 +1297,33 @@ namespace Google.Protobuf.DescriptorProtos { return new ReservedRange(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int StartFieldNumber = 1; private int start_; public int Start { get { return start_; } - set { start_ = value; } + set { + pb::Freezable.CheckMutable(this); + start_ = value; + } } - public const int EndFieldNumber = 2; private int end_; public int End { get { return end_; } - set { end_ = value; } + set { + pb::Freezable.CheckMutable(this); + end_ = value; + } } - public override bool Equals(object other) { return Equals(other as ReservedRange); } @@ -1328,6 +1425,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FieldDescriptorProto__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public FieldDescriptorProto() { } public FieldDescriptorProto(FieldDescriptorProto other) { @@ -1346,75 +1446,102 @@ namespace Google.Protobuf.DescriptorProtos { return new FieldDescriptorProto(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + if (options_ != null) Options.Freeze(); + } + public const int NameFieldNumber = 1; private string name_ = ""; public string Name { get { return name_; } - set { name_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + name_ = value ?? ""; + } } - public const int NumberFieldNumber = 3; private int number_; public int Number { get { return number_; } - set { number_ = value; } + set { + pb::Freezable.CheckMutable(this); + number_ = value; + } } - public const int LabelFieldNumber = 4; private global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Label label_ = global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Label.LABEL_OPTIONAL; public global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Label Label { get { return label_; } - set { label_ = value; } + set { + pb::Freezable.CheckMutable(this); + label_ = value; + } } - public const int TypeFieldNumber = 5; private global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Type type_ = global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Type.TYPE_DOUBLE; public global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Type Type { get { return type_; } - set { type_ = value; } + set { + pb::Freezable.CheckMutable(this); + type_ = value; + } } - public const int TypeNameFieldNumber = 6; private string typeName_ = ""; public string TypeName { get { return typeName_; } - set { typeName_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + typeName_ = value ?? ""; + } } - public const int ExtendeeFieldNumber = 2; private string extendee_ = ""; public string Extendee { get { return extendee_; } - set { extendee_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + extendee_ = value ?? ""; + } } - public const int DefaultValueFieldNumber = 7; private string defaultValue_ = ""; public string DefaultValue { get { return defaultValue_; } - set { defaultValue_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + defaultValue_ = value ?? ""; + } } - public const int OneofIndexFieldNumber = 9; private int oneofIndex_; public int OneofIndex { get { return oneofIndex_; } - set { oneofIndex_ = value; } + set { + pb::Freezable.CheckMutable(this); + oneofIndex_ = value; + } } - public const int OptionsFieldNumber = 8; private global::Google.Protobuf.DescriptorProtos.FieldOptions options_; public global::Google.Protobuf.DescriptorProtos.FieldOptions Options { get { return options_; } - set { options_ = value; } + set { + pb::Freezable.CheckMutable(this); + options_ = value; + } } public override bool Equals(object other) { @@ -1436,7 +1563,8 @@ namespace Google.Protobuf.DescriptorProtos { if (Extendee != other.Extendee) return false; if (DefaultValue != other.DefaultValue) return false; if (OneofIndex != other.OneofIndex) return false; - if (!object.Equals(Options, other.Options)) return false; return true; + if (!object.Equals(Options, other.Options)) return false; + return true; } public override int GetHashCode() { @@ -1663,6 +1791,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_OneofDescriptorProto__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public OneofDescriptorProto() { } public OneofDescriptorProto(OneofDescriptorProto other) { @@ -1673,14 +1804,23 @@ namespace Google.Protobuf.DescriptorProtos { return new OneofDescriptorProto(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int NameFieldNumber = 1; private string name_ = ""; public string Name { get { return name_; } - set { name_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + name_ = value ?? ""; + } } - public override bool Equals(object other) { return Equals(other as OneofDescriptorProto); } @@ -1761,6 +1901,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_EnumDescriptorProto__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public EnumDescriptorProto() { } public EnumDescriptorProto(EnumDescriptorProto other) { @@ -1773,14 +1916,25 @@ namespace Google.Protobuf.DescriptorProtos { return new EnumDescriptorProto(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + value_.Freeze(); + if (options_ != null) Options.Freeze(); + } + public const int NameFieldNumber = 1; private string name_ = ""; public string Name { get { return name_; } - set { name_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + name_ = value ?? ""; + } } - public const int ValueFieldNumber = 2; private readonly pbc::RepeatedField value_ = new pbc::RepeatedField(); public pbc::RepeatedField Value { @@ -1791,7 +1945,10 @@ namespace Google.Protobuf.DescriptorProtos { private global::Google.Protobuf.DescriptorProtos.EnumOptions options_; public global::Google.Protobuf.DescriptorProtos.EnumOptions Options { get { return options_; } - set { options_ = value; } + set { + pb::Freezable.CheckMutable(this); + options_ = value; + } } public override bool Equals(object other) { @@ -1807,7 +1964,8 @@ namespace Google.Protobuf.DescriptorProtos { } if (Name != other.Name) return false; if(!value_.Equals(other.value_)) return false; - if (!object.Equals(Options, other.Options)) return false; return true; + if (!object.Equals(Options, other.Options)) return false; + return true; } public override int GetHashCode() { @@ -1911,6 +2069,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_EnumValueDescriptorProto__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public EnumValueDescriptorProto() { } public EnumValueDescriptorProto(EnumValueDescriptorProto other) { @@ -1923,27 +2084,42 @@ namespace Google.Protobuf.DescriptorProtos { return new EnumValueDescriptorProto(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + if (options_ != null) Options.Freeze(); + } + public const int NameFieldNumber = 1; private string name_ = ""; public string Name { get { return name_; } - set { name_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + name_ = value ?? ""; + } } - public const int NumberFieldNumber = 2; private int number_; public int Number { get { return number_; } - set { number_ = value; } + set { + pb::Freezable.CheckMutable(this); + number_ = value; + } } - public const int OptionsFieldNumber = 3; private global::Google.Protobuf.DescriptorProtos.EnumValueOptions options_; public global::Google.Protobuf.DescriptorProtos.EnumValueOptions Options { get { return options_; } - set { options_ = value; } + set { + pb::Freezable.CheckMutable(this); + options_ = value; + } } public override bool Equals(object other) { @@ -1959,7 +2135,8 @@ namespace Google.Protobuf.DescriptorProtos { } if (Name != other.Name) return false; if (Number != other.Number) return false; - if (!object.Equals(Options, other.Options)) return false; return true; + if (!object.Equals(Options, other.Options)) return false; + return true; } public override int GetHashCode() { @@ -2063,6 +2240,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_ServiceDescriptorProto__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public ServiceDescriptorProto() { } public ServiceDescriptorProto(ServiceDescriptorProto other) { @@ -2075,14 +2255,25 @@ namespace Google.Protobuf.DescriptorProtos { return new ServiceDescriptorProto(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + method_.Freeze(); + if (options_ != null) Options.Freeze(); + } + public const int NameFieldNumber = 1; private string name_ = ""; public string Name { get { return name_; } - set { name_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + name_ = value ?? ""; + } } - public const int MethodFieldNumber = 2; private readonly pbc::RepeatedField method_ = new pbc::RepeatedField(); public pbc::RepeatedField Method { @@ -2093,7 +2284,10 @@ namespace Google.Protobuf.DescriptorProtos { private global::Google.Protobuf.DescriptorProtos.ServiceOptions options_; public global::Google.Protobuf.DescriptorProtos.ServiceOptions Options { get { return options_; } - set { options_ = value; } + set { + pb::Freezable.CheckMutable(this); + options_ = value; + } } public override bool Equals(object other) { @@ -2109,7 +2303,8 @@ namespace Google.Protobuf.DescriptorProtos { } if (Name != other.Name) return false; if(!method_.Equals(other.method_)) return false; - if (!object.Equals(Options, other.Options)) return false; return true; + if (!object.Equals(Options, other.Options)) return false; + return true; } public override int GetHashCode() { @@ -2213,6 +2408,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_MethodDescriptorProto__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public MethodDescriptorProto() { } public MethodDescriptorProto(MethodDescriptorProto other) { @@ -2228,53 +2426,74 @@ namespace Google.Protobuf.DescriptorProtos { return new MethodDescriptorProto(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + if (options_ != null) Options.Freeze(); + } + public const int NameFieldNumber = 1; private string name_ = ""; public string Name { get { return name_; } - set { name_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + name_ = value ?? ""; + } } - public const int InputTypeFieldNumber = 2; private string inputType_ = ""; public string InputType { get { return inputType_; } - set { inputType_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + inputType_ = value ?? ""; + } } - public const int OutputTypeFieldNumber = 3; private string outputType_ = ""; public string OutputType { get { return outputType_; } - set { outputType_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + outputType_ = value ?? ""; + } } - public const int OptionsFieldNumber = 4; private global::Google.Protobuf.DescriptorProtos.MethodOptions options_; public global::Google.Protobuf.DescriptorProtos.MethodOptions Options { get { return options_; } - set { options_ = value; } + set { + pb::Freezable.CheckMutable(this); + options_ = value; + } } public const int ClientStreamingFieldNumber = 5; private bool clientStreaming_; public bool ClientStreaming { get { return clientStreaming_; } - set { clientStreaming_ = value; } + set { + pb::Freezable.CheckMutable(this); + clientStreaming_ = value; + } } - public const int ServerStreamingFieldNumber = 6; private bool serverStreaming_; public bool ServerStreaming { get { return serverStreaming_; } - set { serverStreaming_ = value; } + set { + pb::Freezable.CheckMutable(this); + serverStreaming_ = value; + } } - public override bool Equals(object other) { return Equals(other as MethodDescriptorProto); } @@ -2289,7 +2508,8 @@ namespace Google.Protobuf.DescriptorProtos { if (Name != other.Name) return false; if (InputType != other.InputType) return false; if (OutputType != other.OutputType) return false; - if (!object.Equals(Options, other.Options)) return false;if (ClientStreaming != other.ClientStreaming) return false; + if (!object.Equals(Options, other.Options)) return false; + if (ClientStreaming != other.ClientStreaming) return false; if (ServerStreaming != other.ServerStreaming) return false; return true; } @@ -2440,6 +2660,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FileOptions__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public FileOptions() { } public FileOptions(FileOptions other) { @@ -2464,118 +2687,154 @@ namespace Google.Protobuf.DescriptorProtos { return new FileOptions(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + uninterpretedOption_.Freeze(); + } + public const int JavaPackageFieldNumber = 1; private string javaPackage_ = ""; public string JavaPackage { get { return javaPackage_; } - set { javaPackage_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + javaPackage_ = value ?? ""; + } } - public const int JavaOuterClassnameFieldNumber = 8; private string javaOuterClassname_ = ""; public string JavaOuterClassname { get { return javaOuterClassname_; } - set { javaOuterClassname_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + javaOuterClassname_ = value ?? ""; + } } - public const int JavaMultipleFilesFieldNumber = 10; private bool javaMultipleFiles_; public bool JavaMultipleFiles { get { return javaMultipleFiles_; } - set { javaMultipleFiles_ = value; } + set { + pb::Freezable.CheckMutable(this); + javaMultipleFiles_ = value; + } } - public const int JavaGenerateEqualsAndHashFieldNumber = 20; private bool javaGenerateEqualsAndHash_; public bool JavaGenerateEqualsAndHash { get { return javaGenerateEqualsAndHash_; } - set { javaGenerateEqualsAndHash_ = value; } + set { + pb::Freezable.CheckMutable(this); + javaGenerateEqualsAndHash_ = value; + } } - public const int JavaStringCheckUtf8FieldNumber = 27; private bool javaStringCheckUtf8_; public bool JavaStringCheckUtf8 { get { return javaStringCheckUtf8_; } - set { javaStringCheckUtf8_ = value; } + set { + pb::Freezable.CheckMutable(this); + javaStringCheckUtf8_ = value; + } } - public const int OptimizeForFieldNumber = 9; private global::Google.Protobuf.DescriptorProtos.FileOptions.Types.OptimizeMode optimizeFor_ = global::Google.Protobuf.DescriptorProtos.FileOptions.Types.OptimizeMode.SPEED; public global::Google.Protobuf.DescriptorProtos.FileOptions.Types.OptimizeMode OptimizeFor { get { return optimizeFor_; } - set { optimizeFor_ = value; } + set { + pb::Freezable.CheckMutable(this); + optimizeFor_ = value; + } } - public const int GoPackageFieldNumber = 11; private string goPackage_ = ""; public string GoPackage { get { return goPackage_; } - set { goPackage_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + goPackage_ = value ?? ""; + } } - public const int CcGenericServicesFieldNumber = 16; private bool ccGenericServices_; public bool CcGenericServices { get { return ccGenericServices_; } - set { ccGenericServices_ = value; } + set { + pb::Freezable.CheckMutable(this); + ccGenericServices_ = value; + } } - public const int JavaGenericServicesFieldNumber = 17; private bool javaGenericServices_; public bool JavaGenericServices { get { return javaGenericServices_; } - set { javaGenericServices_ = value; } + set { + pb::Freezable.CheckMutable(this); + javaGenericServices_ = value; + } } - public const int PyGenericServicesFieldNumber = 18; private bool pyGenericServices_; public bool PyGenericServices { get { return pyGenericServices_; } - set { pyGenericServices_ = value; } + set { + pb::Freezable.CheckMutable(this); + pyGenericServices_ = value; + } } - public const int DeprecatedFieldNumber = 23; private bool deprecated_; public bool Deprecated { get { return deprecated_; } - set { deprecated_ = value; } + set { + pb::Freezable.CheckMutable(this); + deprecated_ = value; + } } - public const int CcEnableArenasFieldNumber = 31; private bool ccEnableArenas_; public bool CcEnableArenas { get { return ccEnableArenas_; } - set { ccEnableArenas_ = value; } + set { + pb::Freezable.CheckMutable(this); + ccEnableArenas_ = value; + } } - public const int ObjcClassPrefixFieldNumber = 36; private string objcClassPrefix_ = ""; public string ObjcClassPrefix { get { return objcClassPrefix_; } - set { objcClassPrefix_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + objcClassPrefix_ = value ?? ""; + } } - public const int CsharpNamespaceFieldNumber = 37; private string csharpNamespace_ = ""; public string CsharpNamespace { get { return csharpNamespace_; } - set { csharpNamespace_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + csharpNamespace_ = value ?? ""; + } } - public const int UninterpretedOptionFieldNumber = 999; private readonly pbc::RepeatedField uninterpretedOption_ = new pbc::RepeatedField(); public pbc::RepeatedField UninterpretedOption { @@ -2898,6 +3157,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_MessageOptions__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public MessageOptions() { } public MessageOptions(MessageOptions other) { @@ -2912,38 +3174,54 @@ namespace Google.Protobuf.DescriptorProtos { return new MessageOptions(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + uninterpretedOption_.Freeze(); + } + public const int MessageSetWireFormatFieldNumber = 1; private bool messageSetWireFormat_; public bool MessageSetWireFormat { get { return messageSetWireFormat_; } - set { messageSetWireFormat_ = value; } + set { + pb::Freezable.CheckMutable(this); + messageSetWireFormat_ = value; + } } - public const int NoStandardDescriptorAccessorFieldNumber = 2; private bool noStandardDescriptorAccessor_; public bool NoStandardDescriptorAccessor { get { return noStandardDescriptorAccessor_; } - set { noStandardDescriptorAccessor_ = value; } + set { + pb::Freezable.CheckMutable(this); + noStandardDescriptorAccessor_ = value; + } } - public const int DeprecatedFieldNumber = 3; private bool deprecated_; public bool Deprecated { get { return deprecated_; } - set { deprecated_ = value; } + set { + pb::Freezable.CheckMutable(this); + deprecated_ = value; + } } - public const int MapEntryFieldNumber = 7; private bool mapEntry_; public bool MapEntry { get { return mapEntry_; } - set { mapEntry_ = value; } + set { + pb::Freezable.CheckMutable(this); + mapEntry_ = value; + } } - public const int UninterpretedOptionFieldNumber = 999; private readonly pbc::RepeatedField uninterpretedOption_ = new pbc::RepeatedField(); public pbc::RepeatedField UninterpretedOption { @@ -3094,6 +3372,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_FieldOptions__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public FieldOptions() { } public FieldOptions(FieldOptions other) { @@ -3110,54 +3391,74 @@ namespace Google.Protobuf.DescriptorProtos { return new FieldOptions(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + uninterpretedOption_.Freeze(); + } + public const int CtypeFieldNumber = 1; private global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.CType ctype_ = global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.CType.STRING; public global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.CType Ctype { get { return ctype_; } - set { ctype_ = value; } + set { + pb::Freezable.CheckMutable(this); + ctype_ = value; + } } - public const int PackedFieldNumber = 2; private bool packed_; public bool Packed { get { return packed_; } - set { packed_ = value; } + set { + pb::Freezable.CheckMutable(this); + packed_ = value; + } } - public const int JstypeFieldNumber = 6; private global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.JSType jstype_ = global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.JSType.JS_NORMAL; public global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.JSType Jstype { get { return jstype_; } - set { jstype_ = value; } + set { + pb::Freezable.CheckMutable(this); + jstype_ = value; + } } - public const int LazyFieldNumber = 5; private bool lazy_; public bool Lazy { get { return lazy_; } - set { lazy_ = value; } + set { + pb::Freezable.CheckMutable(this); + lazy_ = value; + } } - public const int DeprecatedFieldNumber = 3; private bool deprecated_; public bool Deprecated { get { return deprecated_; } - set { deprecated_ = value; } + set { + pb::Freezable.CheckMutable(this); + deprecated_ = value; + } } - public const int WeakFieldNumber = 10; private bool weak_; public bool Weak { get { return weak_; } - set { weak_ = value; } + set { + pb::Freezable.CheckMutable(this); + weak_ = value; + } } - public const int UninterpretedOptionFieldNumber = 999; private readonly pbc::RepeatedField uninterpretedOption_ = new pbc::RepeatedField(); public pbc::RepeatedField UninterpretedOption { @@ -3358,6 +3659,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_EnumOptions__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public EnumOptions() { } public EnumOptions(EnumOptions other) { @@ -3370,22 +3674,34 @@ namespace Google.Protobuf.DescriptorProtos { return new EnumOptions(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + uninterpretedOption_.Freeze(); + } + public const int AllowAliasFieldNumber = 2; private bool allowAlias_; public bool AllowAlias { get { return allowAlias_; } - set { allowAlias_ = value; } + set { + pb::Freezable.CheckMutable(this); + allowAlias_ = value; + } } - public const int DeprecatedFieldNumber = 3; private bool deprecated_; public bool Deprecated { get { return deprecated_; } - set { deprecated_ = value; } + set { + pb::Freezable.CheckMutable(this); + deprecated_ = value; + } } - public const int UninterpretedOptionFieldNumber = 999; private readonly pbc::RepeatedField uninterpretedOption_ = new pbc::RepeatedField(); public pbc::RepeatedField UninterpretedOption { @@ -3504,6 +3820,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_EnumValueOptions__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public EnumValueOptions() { } public EnumValueOptions(EnumValueOptions other) { @@ -3515,14 +3834,24 @@ namespace Google.Protobuf.DescriptorProtos { return new EnumValueOptions(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + uninterpretedOption_.Freeze(); + } + public const int DeprecatedFieldNumber = 1; private bool deprecated_; public bool Deprecated { get { return deprecated_; } - set { deprecated_ = value; } + set { + pb::Freezable.CheckMutable(this); + deprecated_ = value; + } } - public const int UninterpretedOptionFieldNumber = 999; private readonly pbc::RepeatedField uninterpretedOption_ = new pbc::RepeatedField(); public pbc::RepeatedField UninterpretedOption { @@ -3625,6 +3954,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_ServiceOptions__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public ServiceOptions() { } public ServiceOptions(ServiceOptions other) { @@ -3636,14 +3968,24 @@ namespace Google.Protobuf.DescriptorProtos { return new ServiceOptions(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + uninterpretedOption_.Freeze(); + } + public const int DeprecatedFieldNumber = 33; private bool deprecated_; public bool Deprecated { get { return deprecated_; } - set { deprecated_ = value; } + set { + pb::Freezable.CheckMutable(this); + deprecated_ = value; + } } - public const int UninterpretedOptionFieldNumber = 999; private readonly pbc::RepeatedField uninterpretedOption_ = new pbc::RepeatedField(); public pbc::RepeatedField UninterpretedOption { @@ -3746,6 +4088,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_MethodOptions__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public MethodOptions() { } public MethodOptions(MethodOptions other) { @@ -3757,14 +4102,24 @@ namespace Google.Protobuf.DescriptorProtos { return new MethodOptions(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + uninterpretedOption_.Freeze(); + } + public const int DeprecatedFieldNumber = 33; private bool deprecated_; public bool Deprecated { get { return deprecated_; } - set { deprecated_ = value; } + set { + pb::Freezable.CheckMutable(this); + deprecated_ = value; + } } - public const int UninterpretedOptionFieldNumber = 999; private readonly pbc::RepeatedField uninterpretedOption_ = new pbc::RepeatedField(); public pbc::RepeatedField UninterpretedOption { @@ -3867,6 +4222,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_UninterpretedOption__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public UninterpretedOption() { } public UninterpretedOption(UninterpretedOption other) { @@ -3883,6 +4241,14 @@ namespace Google.Protobuf.DescriptorProtos { return new UninterpretedOption(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + name_.Freeze(); + } + public const int NameFieldNumber = 2; private readonly pbc::RepeatedField name_ = new pbc::RepeatedField(); public pbc::RepeatedField Name { @@ -3893,50 +4259,62 @@ namespace Google.Protobuf.DescriptorProtos { private string identifierValue_ = ""; public string IdentifierValue { get { return identifierValue_; } - set { identifierValue_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + identifierValue_ = value ?? ""; + } } - public const int PositiveIntValueFieldNumber = 4; private ulong positiveIntValue_; public ulong PositiveIntValue { get { return positiveIntValue_; } - set { positiveIntValue_ = value; } + set { + pb::Freezable.CheckMutable(this); + positiveIntValue_ = value; + } } - public const int NegativeIntValueFieldNumber = 5; private long negativeIntValue_; public long NegativeIntValue { get { return negativeIntValue_; } - set { negativeIntValue_ = value; } + set { + pb::Freezable.CheckMutable(this); + negativeIntValue_ = value; + } } - public const int DoubleValueFieldNumber = 6; private double doubleValue_; public double DoubleValue { get { return doubleValue_; } - set { doubleValue_ = value; } + set { + pb::Freezable.CheckMutable(this); + doubleValue_ = value; + } } - public const int StringValueFieldNumber = 7; private pb::ByteString stringValue_ = pb::ByteString.Empty; public pb::ByteString StringValue { get { return stringValue_; } - set { stringValue_ = value ?? pb::ByteString.Empty; } + set { + pb::Freezable.CheckMutable(this); + stringValue_ = value ?? pb::ByteString.Empty; + } } - public const int AggregateValueFieldNumber = 8; private string aggregateValue_ = ""; public string AggregateValue { get { return aggregateValue_; } - set { aggregateValue_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + aggregateValue_ = value ?? ""; + } } - public override bool Equals(object other) { return Equals(other as UninterpretedOption); } @@ -4114,6 +4492,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_UninterpretedOption_NamePart__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public NamePart() { } public NamePart(NamePart other) { @@ -4125,22 +4506,33 @@ namespace Google.Protobuf.DescriptorProtos { return new NamePart(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + } + public const int NamePart_FieldNumber = 1; private string namePart_ = ""; public string NamePart_ { get { return namePart_; } - set { namePart_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + namePart_ = value ?? ""; + } } - public const int IsExtensionFieldNumber = 2; private bool isExtension_; public bool IsExtension { get { return isExtension_; } - set { isExtension_ = value; } + set { + pb::Freezable.CheckMutable(this); + isExtension_ = value; + } } - public override bool Equals(object other) { return Equals(other as NamePart); } @@ -4242,6 +4634,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_SourceCodeInfo__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public SourceCodeInfo() { } public SourceCodeInfo(SourceCodeInfo other) { @@ -4252,6 +4647,14 @@ namespace Google.Protobuf.DescriptorProtos { return new SourceCodeInfo(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + location_.Freeze(); + } + public const int LocationFieldNumber = 1; private readonly pbc::RepeatedField location_ = new pbc::RepeatedField(); public pbc::RepeatedField Location { @@ -4339,6 +4742,9 @@ namespace Google.Protobuf.DescriptorProtos { get { return global::Google.Protobuf.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_SourceCodeInfo_Location__FieldAccessorTable; } } + private bool _frozen = false; + public bool IsFrozen { get { return _frozen; } } + public Location() { } public Location(Location other) { @@ -4353,6 +4759,16 @@ namespace Google.Protobuf.DescriptorProtos { return new Location(this); } + public void Freeze() { + if (IsFrozen) { + return; + } + _frozen = true; + path_.Freeze(); + span_.Freeze(); + leadingDetachedComments_.Freeze(); + } + public const int PathFieldNumber = 1; private readonly pbc::RepeatedField path_ = new pbc::RepeatedField(); public pbc::RepeatedField Path { @@ -4369,18 +4785,22 @@ namespace Google.Protobuf.DescriptorProtos { private string leadingComments_ = ""; public string LeadingComments { get { return leadingComments_; } - set { leadingComments_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + leadingComments_ = value ?? ""; + } } - public const int TrailingCommentsFieldNumber = 4; private string trailingComments_ = ""; public string TrailingComments { get { return trailingComments_; } - set { trailingComments_ = value ?? ""; } + set { + pb::Freezable.CheckMutable(this); + trailingComments_ = value ?? ""; + } } - public const int LeadingDetachedCommentsFieldNumber = 6; private readonly pbc::RepeatedField leadingDetachedComments_ = new pbc::RepeatedField(); public pbc::RepeatedField LeadingDetachedComments { diff --git a/csharp/src/ProtocolBuffers/Freezable.cs b/csharp/src/ProtocolBuffers/Freezable.cs new file mode 100644 index 0000000000..40b4398ae8 --- /dev/null +++ b/csharp/src/ProtocolBuffers/Freezable.cs @@ -0,0 +1,60 @@ +#region Copyright notice and license + +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// http://github.com/google/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System; + +namespace Google.Protobuf +{ + /// + /// Extension methods for types. + /// + public static class Freezable + { + /// + /// Throws an if + /// is frozen. + /// + /// + /// This is a convenience methods that freezable types can call before all + /// mutations, to protect frozen objects. + /// + public static void CheckMutable(this IFreezable target) + { + if (target.IsFrozen) + { + throw new InvalidOperationException("Attempt to mutate frozen object"); + } + } + } +} diff --git a/csharp/src/ProtocolBuffers/IMessage.cs b/csharp/src/ProtocolBuffers/IMessage.cs index 5d662cfd17..d606aee1c3 100644 --- a/csharp/src/ProtocolBuffers/IMessage.cs +++ b/csharp/src/ProtocolBuffers/IMessage.cs @@ -41,6 +41,7 @@ namespace Google.Protobuf { // TODO(jonskeet): Do we want a "weak" (non-generic) version of IReflectedMessage? + // TODO(jonskeet): Split these interfaces into separate files when we're happy with them. /// /// Reflection support for a specific message type. message @@ -85,7 +86,7 @@ namespace Google.Protobuf /// the implementation class. /// /// The message type. - public interface IMessage : IMessage, IEquatable, IDeepCloneable where T : IMessage + public interface IMessage : IMessage, IEquatable, IDeepCloneable, IFreezable where T : IMessage { /// /// Merges the given message into this one. @@ -102,6 +103,11 @@ namespace Google.Protobuf /// All generated messages implement this interface, but so do some non-message types. /// Additionally, due to the type constraint on T in , /// it is simpler to keep this as a separate interface. + /// + /// + /// Freezable types which implement this interface should always return a mutable clone, + /// even if the original object is frozen. + /// /// /// The type itself, returned by the method. public interface IDeepCloneable @@ -112,4 +118,32 @@ namespace Google.Protobuf /// A deep clone of this object. T Clone(); } + + /// + /// Provides a mechanism for freezing a message (or repeated field collection) + /// to make it immutable. + /// + /// + /// Implementations are under no obligation to make this thread-safe: if a freezable + /// type instance is shared between threads before being frozen, and one thread then + /// freezes it, it is possible for other threads to make changes during the freezing + /// operation and also to observe stale values for mutated fields. Objects should be + /// frozen before being made available to other threads. + /// + public interface IFreezable + { + /// + /// Freezes this object. + /// + /// + /// If the object is already frozen, this method has no effect. + /// + void Freeze(); + + /// + /// Returns whether or not this object is frozen (and therefore immutable). + /// + /// true if this object is frozen; false otherwise. + bool IsFrozen { get; } + } } diff --git a/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj b/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj index 33a32ff228..d1551148ae 100644 --- a/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj +++ b/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj @@ -85,6 +85,7 @@ + diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc index 54f281eea7..0bfbc70ec2 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -107,6 +107,11 @@ FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor, FieldGeneratorBase::~FieldGeneratorBase() { } +void FieldGeneratorBase::GenerateFreezingCode(io::Printer* printer) { + // No-op: only message fields and repeated fields need + // special handling for freezing, so default to not generating any code. +} + void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) { if (descriptor_->options().deprecated()) { diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h index 91ae3ba1af..abf9254b69 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.h +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h @@ -48,6 +48,7 @@ class FieldGeneratorBase : public SourceGeneratorBase { ~FieldGeneratorBase(); virtual void GenerateCloningCode(io::Printer* printer) = 0; + virtual void GenerateFreezingCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer) = 0; virtual void GenerateMergingCode(io::Printer* printer) = 0; virtual void GenerateParsingCode(io::Printer* printer) = 0; diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 39938fa397..9580c1677a 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -211,7 +211,9 @@ void MessageGenerator::Generate(io::Printer* printer) { "public pb::FieldAccess.FieldAccessorTable<$class_name$> Fields {\n" " get { return $umbrella_class_name$.internal__$identifier$__FieldAccessorTable; }\n" "}\n" - "\n"); + "\n" + "private bool _frozen = false;\n" + "public bool IsFrozen { get { return _frozen; } }\n\n"); // Parameterless constructor printer->Print( @@ -219,6 +221,7 @@ void MessageGenerator::Generate(io::Printer* printer) { "public $class_name$() { }\n\n"); GenerateCloningCode(printer); + GenerateFreezingCode(printer); // Fields/properties for (int i = 0; i < descriptor_->field_count(); i++) { @@ -260,6 +263,7 @@ void MessageGenerator::Generate(io::Printer* printer) { " get { return $name$Case_; }\n" "}\n\n" "public void Clear$property_name$() {\n" + " pb::Freezable.CheckMutable(this);\n" " $name$Case_ = $property_name$OneofCase.None;\n" " $name$_ = null;\n" "}\n\n"); @@ -346,6 +350,36 @@ void MessageGenerator::GenerateCloningCode(io::Printer* printer) { "}\n\n"); } +void MessageGenerator::GenerateFreezingCode(io::Printer* printer) { + map vars; + vars["class_name"] = class_name(); + printer->Print( + "public void Freeze() {\n" + " if (IsFrozen) {\n" + " return;\n" + " }\n" + " _frozen = true;\n"); + printer->Indent(); + // Freeze non-oneof fields first (only messages and repeated fields will actually generate any code) + for (int i = 0; i < descriptor_->field_count(); i++) { + if (!descriptor_->field(i)->containing_oneof()) { + scoped_ptr generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->GenerateFreezingCode(printer); + } + } + + // For each oneof, if the value is freezable, freeze it. We don't actually need to know which type it was. + for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { + vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); + printer->Print(vars, + "if ($name$_ is IFreezable) ((IFreezable) $name$_).Freeze();\n"); + } + + printer->Outdent(); + printer->Print("}\n\n"); +} + void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) { map vars; vars["class_name"] = class_name(); diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h index c3a37a0efb..6c7153aa6b 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.h +++ b/src/google/protobuf/compiler/csharp/csharp_message.h @@ -51,6 +51,7 @@ class MessageGenerator : public SourceGeneratorBase { ~MessageGenerator(); void GenerateCloningCode(io::Printer* printer); + void GenerateFreezingCode(io::Printer* printer); void GenerateFrameworkMethods(io::Printer* printer); void GenerateStaticVariables(io::Printer* printer); void GenerateStaticVariableInitializers(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc index 82deef54bd..cbf182d27e 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc @@ -66,7 +66,10 @@ void MessageFieldGenerator::GenerateMembers(io::Printer* printer) { variables_, "public $type_name$ $property_name$ {\n" " get { return $name$_; }\n" - " set { $name$_ = value; }\n" + " set {\n" + " pb::Freezable.CheckMutable(this);\n" + " $name$_ = value;\n" + " }\n" "}\n"); } @@ -116,7 +119,7 @@ void MessageFieldGenerator::WriteHash(io::Printer* printer) { void MessageFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( variables_, - "if (!object.Equals($property_name$, other.$property_name$)) return false;"); + "if (!object.Equals($property_name$, other.$property_name$)) return false;\n"); } void MessageFieldGenerator::WriteToString(io::Printer* printer) { variables_["field_name"] = GetFieldName(descriptor_); @@ -130,6 +133,11 @@ void MessageFieldGenerator::GenerateCloningCode(io::Printer* printer) { "$property_name$ = other.$has_property_check$ ? other.$property_name$.Clone() : null;\n"); } +void MessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) { + printer->Print(variables_, + "if ($has_property_check$) $property_name$.Freeze();\n"); +} + MessageOneofFieldGenerator::MessageOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal) : MessageFieldGenerator(descriptor, fieldOrdinal) { @@ -147,6 +155,7 @@ void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) { "public $type_name$ $property_name$ {\n" " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : null; }\n" " set {\n" + " pb::Freezable.CheckMutable(this);\n" " $oneof_name$_ = value;\n" " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n" " }\n" diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.h b/src/google/protobuf/compiler/csharp/csharp_message_field.h index f15e8e7e8a..3e17f92a82 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.h @@ -47,6 +47,7 @@ class MessageFieldGenerator : public FieldGeneratorBase { ~MessageFieldGenerator(); virtual void GenerateCloningCode(io::Printer* printer); + virtual void GenerateFreezingCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc index c426c37ae0..d5542f57ea 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -72,17 +72,21 @@ void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) { printer->Print( variables_, "public $type_name$ $property_name$ {\n" - " get { return $name$_; }\n"); + " get { return $name$_; }\n" + " set {\n" + " pb::Freezable.CheckMutable(this);\n"); if (is_value_type) { printer->Print( variables_, - " set { $name$_ = value; }\n"); + " $name$_ = value;\n"); } else { printer->Print( variables_, - " set { $name$_ = value ?? $default_value$; }\n"); + " $name$_ = value ?? $default_value$;\n"); } - printer->Print("}\n\n"); + printer->Print( + " }\n" + "}\n"); } void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) { @@ -166,7 +170,8 @@ void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) { variables_, "public $type_name$ $property_name$ {\n" " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n" - " set {\n"); + " set {\n" + " pb::Freezable.CheckMutable(this);\n"); if (is_value_type) { printer->Print( variables_, diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc index ce526b3784..d223273c20 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc @@ -147,6 +147,11 @@ void RepeatedEnumFieldGenerator::GenerateCloningCode(io::Printer* printer) { "$name$_ = other.$name$_.Clone();\n"); } +void RepeatedEnumFieldGenerator::GenerateFreezingCode(io::Printer* printer) { + printer->Print(variables_, + "$name$_.Freeze();\n"); +} + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h index c7846a6199..ee50eef015 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h @@ -49,6 +49,7 @@ class RepeatedEnumFieldGenerator : public FieldGeneratorBase { ~RepeatedEnumFieldGenerator(); virtual void GenerateCloningCode(io::Printer* printer); + virtual void GenerateFreezingCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc index edfb98b44e..400f0e4f8e 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc @@ -123,6 +123,11 @@ void RepeatedMessageFieldGenerator::GenerateCloningCode(io::Printer* printer) { "$name$_ = other.$name$_.Clone();\n"); } +void RepeatedMessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) { + printer->Print(variables_, + "$name$_.Freeze();\n"); +} + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h index 38006731fd..cf601c7e01 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h @@ -47,6 +47,7 @@ class RepeatedMessageFieldGenerator : public FieldGeneratorBase { ~RepeatedMessageFieldGenerator(); virtual void GenerateCloningCode(io::Printer* printer); + virtual void GenerateFreezingCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc index 49a29c5558..a78a74c0ab 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc @@ -153,6 +153,11 @@ void RepeatedPrimitiveFieldGenerator::GenerateCloningCode(io::Printer* printer) "$name$_ = other.$name$_.Clone();\n"); } +void RepeatedPrimitiveFieldGenerator::GenerateFreezingCode(io::Printer* printer) { + printer->Print(variables_, + "$name$_.Freeze();\n"); +} + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h index 7f8f17a84e..f1ceeb507b 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h @@ -47,6 +47,7 @@ class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase { ~RepeatedPrimitiveFieldGenerator(); virtual void GenerateCloningCode(io::Printer* printer); + virtual void GenerateFreezingCode(io::Printer* printer); virtual void GenerateMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); From 322ec531615b3f1aa7b25902ecb10e8673408cac Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 24 Jun 2015 17:55:02 +0100 Subject: [PATCH 2/4] Revert the change to wire_format.h. It seems too much code relies on the broken behaviour. See issue #493. Instead, we reimplement MakeTag just for C#, temporarily. --- .../protobuf/compiler/csharp/csharp_field_base.cc | 2 +- src/google/protobuf/compiler/csharp/csharp_helpers.cc | 11 +++++++++++ src/google/protobuf/compiler/csharp/csharp_helpers.h | 2 ++ src/google/protobuf/compiler/csharp/csharp_message.cc | 3 +-- src/google/protobuf/wire_format.h | 2 +- 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc index 0bfbc70ec2..c716e1bf73 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -57,7 +57,7 @@ void FieldGeneratorBase::SetCommonFieldVariables( // repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which // never effects the tag size. int tag_size = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); - uint tag = internal::WireFormat::MakeTag(descriptor_); + uint tag = FixedMakeTag(descriptor_); uint8 tag_array[5]; io::CodedOutputStream::WriteTagToArray(tag, tag_array); string tag_bytes = SimpleItoa(tag_array[0]); diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc index 76e2c8508b..39a53268f4 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -338,6 +338,17 @@ std::string FileDescriptorToBase64(const FileDescriptor* descriptor) { return StringToBase64(fdp_bytes); } +// TODO(jonskeet): Remove this when internal::WireFormat::MakeTag works +// properly... +// Workaround for issue #493 +uint FixedMakeTag(const FieldDescriptor* field) { + internal::WireFormatLite::WireType field_type = field->is_packed() + ? internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED + : internal::WireFormat::WireTypeForFieldType(field->type()); + + return internal::WireFormatLite::MakeTag(field->number(), field_type); +} + FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal) { switch (descriptor->type()) { diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h index bc77f43ae7..d2ee8fbeed 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.h +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h @@ -97,6 +97,8 @@ std::string StringToBase64(const std::string& input); std::string FileDescriptorToBase64(const FileDescriptor* descriptor); +uint FixedMakeTag(const FieldDescriptor* descriptor); + FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); bool HasRequiredFields(const Descriptor* descriptor); diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 9580c1677a..a6c8e32b00 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -194,8 +194,7 @@ void MessageGenerator::Generate(io::Printer* printer) { "slash", field_names().size() > 0 ? "\"" : ""); std::vector tags; for (int i = 0; i < field_names().size(); i++) { - uint32 tag = internal::WireFormat::MakeTag( - descriptor_->FindFieldByName(field_names()[i])); + uint32 tag = FixedMakeTag(descriptor_->FindFieldByName(field_names()[i])); tags.push_back(SimpleItoa(tag)); } printer->Print( diff --git a/src/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h index 84270fee7e..8de491a633 100644 --- a/src/google/protobuf/wire_format.h +++ b/src/google/protobuf/wire_format.h @@ -290,7 +290,7 @@ class LIBPROTOBUF_EXPORT UnknownFieldSetFieldSkipper : public FieldSkipper { inline WireFormatLite::WireType WireFormat::WireTypeForField( const FieldDescriptor* field) { - if (field->is_packed()) { + if (field->options().packed()) { return WireFormatLite::WIRETYPE_LENGTH_DELIMITED; } else { return WireTypeForFieldType(field->type()); From d487c322defd80f3dba1d1dfc1546e451c7b1c1d Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Thu, 25 Jun 2015 08:22:56 +0100 Subject: [PATCH 3/4] Regenerated descriptor C++ code --- src/google/protobuf/descriptor.pb.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index 30b3a3a7b2..1f49cd6d82 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -753,10 +753,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "ion\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004sp" "an\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(\t\022\031" "\n\021trailing_comments\030\004 \001(\t\022!\n\031leading_det" - "ached_comments\030\006 \003(\tBe\n\023com.google.proto" + "ached_comments\030\006 \003(\tB^\n\023com.google.proto" "bufB\020DescriptorProtosH\001Z\ndescriptor\242\002\003GP" - "B\252\002\'Google.ProtocolBuffers.DescriptorPro" - "tos", 4963); + "B\252\002 Google.Protobuf.DescriptorProtos", 4956); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/descriptor.proto", &protobuf_RegisterTypes); FileDescriptorSet::default_instance_ = new FileDescriptorSet(); From 0698aa973740d2a666fed8281c84a884a4227aa4 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Thu, 25 Jun 2015 08:59:35 +0100 Subject: [PATCH 4/4] Get the Mono build script working again. The solution as a whole doesn't build yet - we probably want to remove ProtoDump and ProtoMunge entirely, and ProtoBench should use Jan's new benchmarks for parity with Java. The version of NUnit on my machine, packaged with Mono 3.12.1, is only NUnit 2.4.2, which is extremely old - it still requires an explicit [TestFixture] attribute on test fixtures. I've added one just for ByteStringTest for the moment so that we can see some tests passing in Travis, but as part of a separate PR we should work on making sure we're using a recent NUnit version. (It may already be doing so, but we can check that once it's working and merged.) --- csharp/buildall.sh | 15 ++++++++------- csharp/src/ProtocolBuffers.Test/ByteStringTest.cs | 1 + csharp/src/ProtocolBuffers.sln | 6 ------ 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/csharp/buildall.sh b/csharp/buildall.sh index 164707cbc0..e19cea0a54 100755 --- a/csharp/buildall.sh +++ b/csharp/buildall.sh @@ -11,12 +11,13 @@ SRC=$(dirname $0)/src set -ex -echo Building the solution. -xbuild /p:Configuration=$CONFIG $SRC/ProtocolBuffers.sln +# echo Building the solution. +# TODO(jonskeet): Re-enable building the whole solution when we have ProtoBench et al +# working again. +# xbuild /p:Configuration=$CONFIG $SRC/ProtocolBuffers.sln -echo Running tests. -$NUNIT_CONSOLE $SRC/ProtocolBuffers.Test/bin/$CONFIG/Google.ProtocolBuffers.Test.dll - -$NUNIT_CONSOLE $SRC/ProtocolBuffersLite.Test/bin/$CONFIG/Google.ProtocolBuffersLite.Test.dll +xbuild /p:Configuration=$CONFIG $SRC/ProtocolBuffers/ProtocolBuffers.csproj +xbuild /p:Configuration=$CONFIG $SRC/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj -$NUNIT_CONSOLE $SRC/ProtocolBuffersLite.Test/bin/$CONFIG/Google.ProtocolBuffersMixedLite.Test.dll +echo Running tests. +$NUNIT_CONSOLE $SRC/ProtocolBuffers.Test/bin/$CONFIG/Google.Protobuf.Test.dll diff --git a/csharp/src/ProtocolBuffers.Test/ByteStringTest.cs b/csharp/src/ProtocolBuffers.Test/ByteStringTest.cs index 0edd149bd3..f7ddb23fbd 100644 --- a/csharp/src/ProtocolBuffers.Test/ByteStringTest.cs +++ b/csharp/src/ProtocolBuffers.Test/ByteStringTest.cs @@ -40,6 +40,7 @@ using NUnit.Framework; namespace Google.Protobuf { + [TestFixture] public class ByteStringTest { [Test] diff --git a/csharp/src/ProtocolBuffers.sln b/csharp/src/ProtocolBuffers.sln index 0889c50e34..7413122f4a 100644 --- a/csharp/src/ProtocolBuffers.sln +++ b/csharp/src/ProtocolBuffers.sln @@ -4,8 +4,6 @@ VisualStudioVersion = 14.0.22823.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProtocolBuffers", "ProtocolBuffers\ProtocolBuffers.csproj", "{6908BDCE-D925-43F3-94AC-A531E6DF2591}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProtocolBuffers.Serialization", "ProtocolBuffers.Serialization\ProtocolBuffers.Serialization.csproj", "{231391AF-449C-4A39-986C-AD7F270F4750}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProtocolBuffers.Test", "ProtocolBuffers.Test\ProtocolBuffers.Test.csproj", "{DD01ED24-3750-4567-9A23-1DB676A15610}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddressBook", "AddressBook\AddressBook.csproj", "{A31F5FB2-4FF3-432A-B35B-5CD203606311}" @@ -26,10 +24,6 @@ Global {6908BDCE-D925-43F3-94AC-A531E6DF2591}.Debug|Any CPU.Build.0 = Debug|Any CPU {6908BDCE-D925-43F3-94AC-A531E6DF2591}.Release|Any CPU.ActiveCfg = Release|Any CPU {6908BDCE-D925-43F3-94AC-A531E6DF2591}.Release|Any CPU.Build.0 = Release|Any CPU - {231391AF-449C-4A39-986C-AD7F270F4750}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {231391AF-449C-4A39-986C-AD7F270F4750}.Debug|Any CPU.Build.0 = Debug|Any CPU - {231391AF-449C-4A39-986C-AD7F270F4750}.Release|Any CPU.ActiveCfg = Release|Any CPU - {231391AF-449C-4A39-986C-AD7F270F4750}.Release|Any CPU.Build.0 = Release|Any CPU {DD01ED24-3750-4567-9A23-1DB676A15610}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DD01ED24-3750-4567-9A23-1DB676A15610}.Debug|Any CPU.Build.0 = Debug|Any CPU {DD01ED24-3750-4567-9A23-1DB676A15610}.Release|Any CPU.ActiveCfg = Release|Any CPU