aboutsummaryrefslogtreecommitdiff
path: root/csharp/src/ProtocolBuffers
diff options
context:
space:
mode:
authorJon Skeet <jonskeet@google.com>2015-06-23 16:09:27 +0100
committerJon Skeet <jonskeet@google.com>2015-06-24 17:56:22 +0100
commitbfee2dfe137b07e64ebd46baf71d932d58d01b1f (patch)
tree4bf6258a990369335cc82c8a8059eaaf1dc2dd06 /csharp/src/ProtocolBuffers
parent94071b54d24d2f2f1cb5933a692b5397a047057c (diff)
downloadprotobuf-bfee2dfe137b07e64ebd46baf71d932d58d01b1f.tar.gz
protobuf-bfee2dfe137b07e64ebd46baf71d932d58d01b1f.tar.bz2
protobuf-bfee2dfe137b07e64ebd46baf71d932d58d01b1f.zip
Implement freezing for messages and repeated fields.
Fixes issue #523.
Diffstat (limited to 'csharp/src/ProtocolBuffers')
-rw-r--r--csharp/src/ProtocolBuffers/Collections/RepeatedField.cs35
-rw-r--r--csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs710
-rw-r--r--csharp/src/ProtocolBuffers/Freezable.cs60
-rw-r--r--csharp/src/ProtocolBuffers/IMessage.cs36
-rw-r--r--csharp/src/ProtocolBuffers/ProtocolBuffers.csproj1
5 files changed, 694 insertions, 148 deletions
diff --git a/csharp/src/ProtocolBuffers/Collections/RepeatedField.cs b/csharp/src/ProtocolBuffers/Collections/RepeatedField.cs
index 5100e4db..ebfc522f 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<T> : IList<T>, IEquatable<RepeatedField<T>>
+ /// <summary>
+ /// The contents of a repeated field: essentially, a collection with some extra
+ /// restrictions (no null values) and capabilities (deep cloning and freezing).
+ /// </summary>
+ /// <typeparam name="T">The element type of the repeated field.</typeparam>
+ public sealed class RepeatedField<T> : IList<T>, IDeepCloneable<RepeatedField<T>>, IEquatable<RepeatedField<T>>, 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<T> Clone()
{
RepeatedField<T> clone = new RepeatedField<T>();
+ // 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
/// <param name="readEnum"></param>
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<T> 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 23d5e964..eedb21fe 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<global::Google.Protobuf.DescriptorProtos.FileDescriptorProto> file_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FileDescriptorProto>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FileDescriptorProto> 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<string> dependency_ = new pbc::RepeatedField<string>();
public pbc::RepeatedField<string> 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<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> field_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto> 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<global::Google.Protobuf.DescriptorProtos.EnumValueDescriptorProto> value_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumValueDescriptorProto>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.EnumValueDescriptorProto> 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<global::Google.Protobuf.DescriptorProtos.MethodDescriptorProto> method_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.MethodDescriptorProto>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.MethodDescriptorProto> 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<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> 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<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> 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<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> 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<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> 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<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> 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<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> 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<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption> 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<global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart> name_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart> 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<global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location> location_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location>();
public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location> 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<int> path_ = new pbc::RepeatedField<int>();
public pbc::RepeatedField<int> 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<string> leadingDetachedComments_ = new pbc::RepeatedField<string>();
public pbc::RepeatedField<string> LeadingDetachedComments {
diff --git a/csharp/src/ProtocolBuffers/Freezable.cs b/csharp/src/ProtocolBuffers/Freezable.cs
new file mode 100644
index 00000000..40b4398a
--- /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
+{
+ /// <summary>
+ /// Extension methods for <see cref="IFreezable"/> types.
+ /// </summary>
+ public static class Freezable
+ {
+ /// <summary>
+ /// Throws an <see cref="InvalidOperationException"/> if <paramref name="target"/>
+ /// is frozen.
+ /// </summary>
+ /// <remarks>
+ /// This is a convenience methods that freezable types can call before all
+ /// mutations, to protect frozen objects.
+ /// </remarks>
+ 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 5d662cfd..d606aee1 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.
/// <summary>
/// Reflection support for a specific message type. message
@@ -85,7 +86,7 @@ namespace Google.Protobuf
/// the implementation class.
/// </summary>
/// <typeparam name="T">The message type.</typeparam>
- public interface IMessage<T> : IMessage, IEquatable<T>, IDeepCloneable<T> where T : IMessage<T>
+ public interface IMessage<T> : IMessage, IEquatable<T>, IDeepCloneable<T>, IFreezable where T : IMessage<T>
{
/// <summary>
/// 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 <c>T</c> in <see cref="IMessage{T}"/>,
/// it is simpler to keep this as a separate interface.
+ /// </para>
+ /// <para>
+ /// Freezable types which implement this interface should always return a mutable clone,
+ /// even if the original object is frozen.
+ /// </para>
/// </remarks>
/// <typeparam name="T">The type itself, returned by the <see cref="Clone"/> method.</typeparam>
public interface IDeepCloneable<T>
@@ -112,4 +118,32 @@ namespace Google.Protobuf
/// <returns>A deep clone of this object.</returns>
T Clone();
}
+
+ /// <summary>
+ /// Provides a mechanism for freezing a message (or repeated field collection)
+ /// to make it immutable.
+ /// </summary>
+ /// <remarks>
+ /// 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.
+ /// </remarks>
+ public interface IFreezable
+ {
+ /// <summary>
+ /// Freezes this object.
+ /// </summary>
+ /// <remarks>
+ /// If the object is already frozen, this method has no effect.
+ /// </remarks>
+ void Freeze();
+
+ /// <summary>
+ /// Returns whether or not this object is frozen (and therefore immutable).
+ /// </summary>
+ /// <value><c>true</c> if this object is frozen; <c>false</c> otherwise.</value>
+ bool IsFrozen { get; }
+ }
}
diff --git a/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj b/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj
index 33a32ff2..d1551148 100644
--- a/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj
+++ b/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj
@@ -85,6 +85,7 @@
<Compile Include="Descriptors\PackageDescriptor.cs" />
<Compile Include="Descriptors\ServiceDescriptor.cs" />
<Compile Include="FrameworkPortability.cs" />
+ <Compile Include="Freezable.cs" />
<Compile Include="MessageExtensions.cs" />
<Compile Include="FieldAccess\FieldAccessorBase.cs" />
<Compile Include="FieldAccess\ReflectionUtil.cs" />