diff --git a/csharp/src/ProtocolBuffers.Test/CodedInputStreamTest.cs b/csharp/src/ProtocolBuffers.Test/CodedInputStreamTest.cs index 576500497..aa2da330e 100644 --- a/csharp/src/ProtocolBuffers.Test/CodedInputStreamTest.cs +++ b/csharp/src/ProtocolBuffers.Test/CodedInputStreamTest.cs @@ -466,18 +466,18 @@ namespace Google.Protobuf } } - enum TestNegEnum : long { None = 0, Value = -2 } + enum TestNegEnum { None = 0, Value = -2 } [Test] public void TestNegativeEnum() { byte[] bytes = new byte[10] { 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01 }; CodedInputStream input = CodedInputStream.CreateInstance(bytes); - TestNegEnum val = TestNegEnum.None; + int val = 0; Assert.IsTrue(input.ReadEnum(ref val)); Assert.IsTrue(input.IsAtEnd); - Assert.AreEqual(TestNegEnum.Value, val); + Assert.AreEqual((int) TestNegEnum.Value, val); } [Test] diff --git a/csharp/src/ProtocolBuffers.Test/CodedOutputStreamTest.cs b/csharp/src/ProtocolBuffers.Test/CodedOutputStreamTest.cs index df80b3af5..fcbb7f8dc 100644 --- a/csharp/src/ProtocolBuffers.Test/CodedOutputStreamTest.cs +++ b/csharp/src/ProtocolBuffers.Test/CodedOutputStreamTest.cs @@ -296,27 +296,27 @@ namespace Google.Protobuf public void TestNegativeEnumNoTag() { Assert.AreEqual(10, CodedOutputStream.ComputeInt32SizeNoTag(-2)); - Assert.AreEqual(10, CodedOutputStream.ComputeEnumSizeNoTag(TestNegEnum.Value)); + Assert.AreEqual(10, CodedOutputStream.ComputeEnumSizeNoTag((int) TestNegEnum.Value)); byte[] bytes = new byte[10]; CodedOutputStream output = CodedOutputStream.CreateInstance(bytes); - output.WriteEnumNoTag(TestNegEnum.Value); + output.WriteEnumNoTag((int) TestNegEnum.Value); Assert.AreEqual(0, output.SpaceLeft); Assert.AreEqual("FE-FF-FF-FF-FF-FF-FF-FF-FF-01", BitConverter.ToString(bytes)); } - enum TestNegEnum : long { None = 0, Value = -2 } + enum TestNegEnum { None = 0, Value = -2 } [Test] public void TestNegativeEnumWithTag() { Assert.AreEqual(11, CodedOutputStream.ComputeInt32Size(8, -2)); - Assert.AreEqual(11, CodedOutputStream.ComputeEnumSize(8, TestNegEnum.Value)); + Assert.AreEqual(11, CodedOutputStream.ComputeEnumSize(8, (int) TestNegEnum.Value)); byte[] bytes = new byte[11]; CodedOutputStream output = CodedOutputStream.CreateInstance(bytes); - output.WriteEnum(8, "", TestNegEnum.Value); + output.WriteEnum(8, "", (int) TestNegEnum.Value); Assert.AreEqual(0, output.SpaceLeft); //fyi, 0x40 == 0x08 << 3 + 0, field num + wire format shift diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs index 1eb87f05c..4b62794a1 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs @@ -49,7 +49,7 @@ namespace Google.Protobuf.TestProtos { } #region Enums - public enum ImportEnum : long { + public enum ImportEnum { IMPORT_ENUM_UNSPECIFIED = 0, IMPORT_FOO = 7, IMPORT_BAR = 8, diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs index fc696cf02..14ca78a41 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs @@ -75,13 +75,13 @@ namespace UnitTest.Issues.TestProtos { } #region Enums - public enum NegativeEnum : long { + public enum NegativeEnum { NEGATIVE_ENUM_ZERO = 0, FiveBelow = -5, MinusOne = -1, } - public enum DeprecatedEnum : long { + public enum DeprecatedEnum { DEPRECATED_ZERO = 0, one = 1, } @@ -156,7 +156,7 @@ namespace UnitTest.Issues.TestProtos { public void WriteTo(pb::ICodedOutputStream output) { string[] fieldNames = _fieldNames; if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) { - output.WriteEnum(1, fieldNames[1], Value); + output.WriteEnum(1, fieldNames[1], (int) Value); } output.WriteEnumArray(2, fieldNames[2], values_); output.WritePackedEnumArray(3, fieldNames[0], packedValues_); @@ -165,13 +165,13 @@ namespace UnitTest.Issues.TestProtos { public int CalculateSize() { int size = 0; if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) { - size += pb::CodedOutputStream.ComputeEnumSize(1, Value); + size += pb::CodedOutputStream.ComputeEnumSize(1, (int) Value); } { int dataSize = 0; if (values_.Count > 0) { foreach (global::UnitTest.Issues.TestProtos.NegativeEnum element in values_) { - dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element); + dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); } size += dataSize; size += 1 * values_.Count; @@ -181,7 +181,7 @@ namespace UnitTest.Issues.TestProtos { int dataSize = 0; if (packedValues_.Count > 0) { foreach (global::UnitTest.Issues.TestProtos.NegativeEnum element in packedValues_) { - dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element); + dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); } size += dataSize; size += 1; @@ -220,8 +220,9 @@ namespace UnitTest.Issues.TestProtos { } break; case 8: { - input.ReadEnum(ref value_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + value_ = (global::UnitTest.Issues.TestProtos.NegativeEnum) tmp;break; } case 18: case 16: { @@ -422,7 +423,7 @@ namespace UnitTest.Issues.TestProtos { } output.WriteMessageArray(4, fieldNames[2], messageArray_); if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) { - output.WriteEnum(5, fieldNames[1], EnumValue); + output.WriteEnum(5, fieldNames[1], (int) EnumValue); } output.WritePackedEnumArray(6, fieldNames[0], enumArray_); } @@ -449,13 +450,13 @@ namespace UnitTest.Issues.TestProtos { size += pb::CodedOutputStream.ComputeMessageSize(4, element); } if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) { - size += pb::CodedOutputStream.ComputeEnumSize(5, EnumValue); + size += pb::CodedOutputStream.ComputeEnumSize(5, (int) EnumValue); } { int dataSize = 0; if (enumArray_.Count > 0) { foreach (global::UnitTest.Issues.TestProtos.DeprecatedEnum element in enumArray_) { - dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element); + dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); } size += dataSize; size += 1; @@ -524,8 +525,9 @@ namespace UnitTest.Issues.TestProtos { break; } case 40: { - input.ReadEnum(ref enumValue_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + enumValue_ = (global::UnitTest.Issues.TestProtos.DeprecatedEnum) tmp;break; } case 50: case 48: { diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs index e231bb953..3e5bb8b69 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs @@ -372,14 +372,14 @@ namespace Google.Protobuf.TestProtos { } #region Enums - public enum ForeignEnum : long { + public enum ForeignEnum { FOREIGN_UNSPECIFIED = 0, FOREIGN_FOO = 4, FOREIGN_BAR = 5, FOREIGN_BAZ = 6, } - public enum TestEnumWithDupValue : long { + public enum TestEnumWithDupValue { TEST_ENUM_WITH_DUP_VALUE_UNSPECIFIED = 0, FOO1 = 1, BAR1 = 2, @@ -388,7 +388,7 @@ namespace Google.Protobuf.TestProtos { BAR2 = 2, } - public enum TestSparseEnum : long { + public enum TestSparseEnum { TEST_SPARSE_ENUM_UNSPECIFIED = 0, SPARSE_A = 123, SPARSE_B = 62374, @@ -945,13 +945,13 @@ namespace Google.Protobuf.TestProtos { output.WriteMessage(20, fieldNames[35], SingleImportMessage); } if (SingleNestedEnum != global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.NESTED_ENUM_UNSPECIFIED) { - output.WriteEnum(21, fieldNames[38], SingleNestedEnum); + output.WriteEnum(21, fieldNames[38], (int) SingleNestedEnum); } if (SingleForeignEnum != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) { - output.WriteEnum(22, fieldNames[32], SingleForeignEnum); + output.WriteEnum(22, fieldNames[32], (int) SingleForeignEnum); } if (SingleImportEnum != global::Google.Protobuf.TestProtos.ImportEnum.IMPORT_ENUM_UNSPECIFIED) { - output.WriteEnum(23, fieldNames[34], SingleImportEnum); + output.WriteEnum(23, fieldNames[34], (int) SingleImportEnum); } if (singlePublicImportMessage_ != null) { output.WriteMessage(26, fieldNames[40], SinglePublicImportMessage); @@ -1049,13 +1049,13 @@ namespace Google.Protobuf.TestProtos { size += pb::CodedOutputStream.ComputeMessageSize(20, SingleImportMessage); } if (SingleNestedEnum != global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.NESTED_ENUM_UNSPECIFIED) { - size += pb::CodedOutputStream.ComputeEnumSize(21, SingleNestedEnum); + size += pb::CodedOutputStream.ComputeEnumSize(21, (int) SingleNestedEnum); } if (SingleForeignEnum != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) { - size += pb::CodedOutputStream.ComputeEnumSize(22, SingleForeignEnum); + size += pb::CodedOutputStream.ComputeEnumSize(22, (int) SingleForeignEnum); } if (SingleImportEnum != global::Google.Protobuf.TestProtos.ImportEnum.IMPORT_ENUM_UNSPECIFIED) { - size += pb::CodedOutputStream.ComputeEnumSize(23, SingleImportEnum); + size += pb::CodedOutputStream.ComputeEnumSize(23, (int) SingleImportEnum); } if (singlePublicImportMessage_ != null) { size += pb::CodedOutputStream.ComputeMessageSize(26, SinglePublicImportMessage); @@ -1205,7 +1205,7 @@ namespace Google.Protobuf.TestProtos { int dataSize = 0; if (repeatedNestedEnum_.Count > 0) { foreach (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum element in repeatedNestedEnum_) { - dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element); + dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); } size += dataSize; size += 2; @@ -1216,7 +1216,7 @@ namespace Google.Protobuf.TestProtos { int dataSize = 0; if (repeatedForeignEnum_.Count > 0) { foreach (global::Google.Protobuf.TestProtos.ForeignEnum element in repeatedForeignEnum_) { - dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element); + dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); } size += dataSize; size += 2; @@ -1227,7 +1227,7 @@ namespace Google.Protobuf.TestProtos { int dataSize = 0; if (repeatedImportEnum_.Count > 0) { foreach (global::Google.Protobuf.TestProtos.ImportEnum element in repeatedImportEnum_) { - dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element); + dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); } size += dataSize; size += 2; @@ -1472,16 +1472,19 @@ namespace Google.Protobuf.TestProtos { break; } case 168: { - input.ReadEnum(ref singleNestedEnum_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + singleNestedEnum_ = (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) tmp;break; } case 176: { - input.ReadEnum(ref singleForeignEnum_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + singleForeignEnum_ = (global::Google.Protobuf.TestProtos.ForeignEnum) tmp;break; } case 184: { - input.ReadEnum(ref singleImportEnum_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + singleImportEnum_ = (global::Google.Protobuf.TestProtos.ImportEnum) tmp;break; } case 210: { if (singlePublicImportMessage_ == null) { @@ -1634,7 +1637,7 @@ namespace Google.Protobuf.TestProtos { #region Nested types [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public static partial class Types { - public enum NestedEnum : long { + public enum NestedEnum { NESTED_ENUM_UNSPECIFIED = 0, FOO = 1, BAR = 2, @@ -2865,7 +2868,7 @@ namespace Google.Protobuf.TestProtos { output.WriteString(2, fieldNames[7], StringField); } if (EnumField != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) { - output.WriteEnum(3, fieldNames[0], EnumField); + output.WriteEnum(3, fieldNames[0], (int) EnumField); } if (messageField_ != null) { output.WriteMessage(4, fieldNames[1], MessageField); @@ -2885,7 +2888,7 @@ namespace Google.Protobuf.TestProtos { size += pb::CodedOutputStream.ComputeStringSize(2, StringField); } if (EnumField != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) { - size += pb::CodedOutputStream.ComputeEnumSize(3, EnumField); + size += pb::CodedOutputStream.ComputeEnumSize(3, (int) EnumField); } if (messageField_ != null) { size += pb::CodedOutputStream.ComputeMessageSize(4, MessageField); @@ -2912,7 +2915,7 @@ namespace Google.Protobuf.TestProtos { int dataSize = 0; if (repeatedEnumField_.Count > 0) { foreach (global::Google.Protobuf.TestProtos.ForeignEnum element in repeatedEnumField_) { - dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element); + dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); } size += dataSize; size += 1; @@ -2976,8 +2979,9 @@ namespace Google.Protobuf.TestProtos { break; } case 24: { - input.ReadEnum(ref enumField_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + enumField_ = (global::Google.Protobuf.TestProtos.ForeignEnum) tmp;break; } case 34: { if (messageField_ == null) { @@ -3361,14 +3365,14 @@ namespace Google.Protobuf.TestProtos { public void WriteTo(pb::ICodedOutputStream output) { string[] fieldNames = _fieldNames; if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.TEST_SPARSE_ENUM_UNSPECIFIED) { - output.WriteEnum(1, fieldNames[0], SparseEnum); + output.WriteEnum(1, fieldNames[0], (int) SparseEnum); } } public int CalculateSize() { int size = 0; if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.TEST_SPARSE_ENUM_UNSPECIFIED) { - size += pb::CodedOutputStream.ComputeEnumSize(1, SparseEnum); + size += pb::CodedOutputStream.ComputeEnumSize(1, (int) SparseEnum); } return size; } @@ -3400,8 +3404,9 @@ namespace Google.Protobuf.TestProtos { } break; case 8: { - input.ReadEnum(ref sparseEnum_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + sparseEnum_ = (global::Google.Protobuf.TestProtos.TestSparseEnum) tmp;break; } } } @@ -4769,7 +4774,7 @@ namespace Google.Protobuf.TestProtos { int dataSize = 0; if (packedEnum_.Count > 0) { foreach (global::Google.Protobuf.TestProtos.ForeignEnum element in packedEnum_) { - dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element); + dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); } size += dataSize; size += 2; @@ -5156,7 +5161,7 @@ namespace Google.Protobuf.TestProtos { int dataSize = 0; if (unpackedEnum_.Count > 0) { foreach (global::Google.Protobuf.TestProtos.ForeignEnum element in unpackedEnum_) { - dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element); + dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); } size += dataSize; size += 2 * unpackedEnum_.Count; diff --git a/csharp/src/ProtocolBuffers/CodedInputStream.cs b/csharp/src/ProtocolBuffers/CodedInputStream.cs index 685d77026..d5cab6fd7 100644 --- a/csharp/src/ProtocolBuffers/CodedInputStream.cs +++ b/csharp/src/ProtocolBuffers/CodedInputStream.cs @@ -434,11 +434,10 @@ namespace Google.Protobuf /// then the ref value is set and it returns true. Otherwise the unknown output /// value is set and this method returns false. /// - public bool ReadEnum(ref T value) - where T : struct, IComparable, IFormattable + public bool ReadEnum(ref int value) { - int number = (int) ReadRawVarint32(); - value = EnumHelper.FromInt32(number); + // Currently just a pass-through, but it's nice to separate it logically from WriteInt32. + value = (int) ReadRawVarint32(); return true; } @@ -796,7 +795,7 @@ namespace Google.Protobuf public void ReadEnumArray(uint fieldTag, string fieldName, ICollection list) where T : struct, IComparable, IFormattable { - T value = default(T); + int value = 0; WireFormat.WireType wformat = WireFormat.GetTagWireType(fieldTag); // 2.3 allows packed form even if the field is not declared packed. @@ -806,8 +805,9 @@ namespace Google.Protobuf int limit = PushLimit(length); while (!ReachedLimit) { - ReadEnum(ref value); - list.Add(value); + ReadEnum(ref value); + // TODO(jonskeet): Avoid this horrible boxing! + list.Add((T)(object)value); } PopLimit(limit); } @@ -816,7 +816,8 @@ namespace Google.Protobuf do { ReadEnum(ref value); - list.Add(value); + // TODO(jonskeet): Avoid this horrible boxing! + list.Add((T)(object) value); } while (ContinueArray(fieldTag)); } } diff --git a/csharp/src/ProtocolBuffers/CodedOutputStream.ComputeSize.cs b/csharp/src/ProtocolBuffers/CodedOutputStream.ComputeSize.cs index 58475ff7b..96be9db56 100644 --- a/csharp/src/ProtocolBuffers/CodedOutputStream.ComputeSize.cs +++ b/csharp/src/ProtocolBuffers/CodedOutputStream.ComputeSize.cs @@ -196,7 +196,7 @@ namespace Google.Protobuf /// enum field, including the tag. The caller is responsible for /// converting the enum value to its numeric value. /// - public static int ComputeEnumSize(int fieldNumber, T value) where T : struct, IComparable, IFormattable + public static int ComputeEnumSize(int fieldNumber, int value) { return ComputeTagSize(fieldNumber) + ComputeEnumSizeNoTag(value); } @@ -371,10 +371,10 @@ namespace Google.Protobuf /// enum field, including the tag. The caller is responsible for /// converting the enum value to its numeric value. /// - public static int ComputeEnumSizeNoTag(T value) where T : struct, IComparable, IFormattable + public static int ComputeEnumSizeNoTag(int value) { - int serializedValue = EnumHelper.ToInt32(value); - return ComputeInt32SizeNoTag(serializedValue); + // Currently just a pass-through, but it's nice to separate it logically. + return ComputeInt32SizeNoTag(value); } /// @@ -555,7 +555,7 @@ namespace Google.Protobuf case FieldType.SInt64: return ComputeSInt64Size(fieldNumber, (long) value); case FieldType.Enum: - return ComputeEnumSize(fieldNumber, Convert.ToInt64(value)); + return ComputeEnumSize(fieldNumber, (int) value); default: throw new ArgumentOutOfRangeException("Invalid field type " + fieldType); } @@ -605,7 +605,7 @@ namespace Google.Protobuf case FieldType.SInt64: return ComputeSInt64SizeNoTag((long) value); case FieldType.Enum: - return ComputeEnumSizeNoTag(Convert.ToInt64(value)); + return ComputeEnumSizeNoTag((int) value); default: throw new ArgumentOutOfRangeException("Invalid field type " + fieldType); } diff --git a/csharp/src/ProtocolBuffers/CodedOutputStream.cs b/csharp/src/ProtocolBuffers/CodedOutputStream.cs index f55f8ca2f..e3f0c7007 100644 --- a/csharp/src/ProtocolBuffers/CodedOutputStream.cs +++ b/csharp/src/ProtocolBuffers/CodedOutputStream.cs @@ -37,6 +37,7 @@ using System; using System.Collections; using System.IO; +using System.Linq; using System.Text; using Google.Protobuf.Collections; using Google.Protobuf.Descriptors; @@ -350,10 +351,11 @@ namespace Google.Protobuf WriteRawVarint32(value); } - public void WriteEnum(int fieldNumber, string fieldName, T value) where T : struct, IComparable, IFormattable + public void WriteEnum(int fieldNumber, string fieldName, int value) { + // Currently just a pass-through, but it's nice to separate it logically from WriteInt32. WriteTag(fieldNumber, WireFormat.WireType.Varint); - WriteInt32NoTag(EnumHelper.ToInt32(value)); + WriteInt32NoTag(value); } public void WriteSFixed32(int fieldNumber, string fieldName, int value) @@ -595,9 +597,9 @@ namespace Google.Protobuf WriteRawVarint32(value); } - public void WriteEnumNoTag(T value) where T : struct, IComparable, IFormattable + public void WriteEnumNoTag(int value) { - WriteInt32NoTag(EnumHelper.ToInt32(value)); + WriteInt32NoTag(value); } public void WriteSFixed32NoTag(int value) @@ -774,7 +776,12 @@ namespace Google.Protobuf public void WriteEnumArray(int fieldNumber, string fieldName, RepeatedField list) where T : struct, IComparable, IFormattable { - foreach (T value in list) + if (list.Count == 0) + { + return; + } + // TODO(jonskeet): Avoid the Cast call here. Work out a better mass "T to int" conversion. + foreach (int value in list.Cast()) { WriteEnum(fieldNumber, fieldName, value); } @@ -1005,10 +1012,13 @@ namespace Google.Protobuf { return; } - uint size = list.CalculateSize(ComputeEnumSizeNoTag); + // Obviously, we'll want to get rid of this hack... + var temporaryHack = new RepeatedField(); + temporaryHack.Add(list.Cast()); + uint size = temporaryHack.CalculateSize(ComputeEnumSizeNoTag); WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited); WriteRawVarint32(size); - foreach (T value in list) + foreach (int value in temporaryHack) { WriteEnumNoTag(value); } diff --git a/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs b/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs index b18b63bf7..eb96dfcf5 100644 --- a/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs +++ b/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs @@ -1360,10 +1360,10 @@ namespace Google.Protobuf.DescriptorProtos { output.WriteInt32(3, fieldNames[4], Number); } if (Label != global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Label.LABEL_OPTIONAL) { - output.WriteEnum(4, fieldNames[2], Label); + output.WriteEnum(4, fieldNames[2], (int) Label); } if (Type != global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Type.TYPE_DOUBLE) { - output.WriteEnum(5, fieldNames[7], Type); + output.WriteEnum(5, fieldNames[7], (int) Type); } if (TypeName != "") { output.WriteString(6, fieldNames[8], TypeName); @@ -1388,10 +1388,10 @@ namespace Google.Protobuf.DescriptorProtos { size += pb::CodedOutputStream.ComputeInt32Size(3, Number); } if (Label != global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Label.LABEL_OPTIONAL) { - size += pb::CodedOutputStream.ComputeEnumSize(4, Label); + size += pb::CodedOutputStream.ComputeEnumSize(4, (int) Label); } if (Type != global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Type.TYPE_DOUBLE) { - size += pb::CodedOutputStream.ComputeEnumSize(5, Type); + size += pb::CodedOutputStream.ComputeEnumSize(5, (int) Type); } if (TypeName != "") { size += pb::CodedOutputStream.ComputeStringSize(6, TypeName); @@ -1477,12 +1477,14 @@ namespace Google.Protobuf.DescriptorProtos { break; } case 32: { - input.ReadEnum(ref label_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + label_ = (global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Label) tmp;break; } case 40: { - input.ReadEnum(ref type_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + type_ = (global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Type) tmp;break; } case 50: { input.ReadString(ref typeName_); @@ -1510,7 +1512,7 @@ namespace Google.Protobuf.DescriptorProtos { #region Nested types [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public static partial class Types { - public enum Type : long { + public enum Type { TYPE_DOUBLE = 1, TYPE_FLOAT = 2, TYPE_INT64 = 3, @@ -1531,7 +1533,7 @@ namespace Google.Protobuf.DescriptorProtos { TYPE_SINT64 = 18, } - public enum Label : long { + public enum Label { LABEL_OPTIONAL = 1, LABEL_REQUIRED = 2, LABEL_REPEATED = 3, @@ -2489,7 +2491,7 @@ namespace Google.Protobuf.DescriptorProtos { output.WriteString(8, fieldNames[8], JavaOuterClassname); } if (OptimizeFor != global::Google.Protobuf.DescriptorProtos.FileOptions.Types.OptimizeMode.SPEED) { - output.WriteEnum(9, fieldNames[12], OptimizeFor); + output.WriteEnum(9, fieldNames[12], (int) OptimizeFor); } if (JavaMultipleFiles != false) { output.WriteBool(10, fieldNames[7], JavaMultipleFiles); @@ -2545,7 +2547,7 @@ namespace Google.Protobuf.DescriptorProtos { size += pb::CodedOutputStream.ComputeBoolSize(27, JavaStringCheckUtf8); } if (OptimizeFor != global::Google.Protobuf.DescriptorProtos.FileOptions.Types.OptimizeMode.SPEED) { - size += pb::CodedOutputStream.ComputeEnumSize(9, OptimizeFor); + size += pb::CodedOutputStream.ComputeEnumSize(9, (int) OptimizeFor); } if (GoPackage != "") { size += pb::CodedOutputStream.ComputeStringSize(11, GoPackage); @@ -2652,8 +2654,9 @@ namespace Google.Protobuf.DescriptorProtos { break; } case 72: { - input.ReadEnum(ref optimizeFor_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + optimizeFor_ = (global::Google.Protobuf.DescriptorProtos.FileOptions.Types.OptimizeMode) tmp;break; } case 80: { input.ReadBool(ref javaMultipleFiles_); @@ -2710,7 +2713,7 @@ namespace Google.Protobuf.DescriptorProtos { #region Nested types [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public static partial class Types { - public enum OptimizeMode : long { + public enum OptimizeMode { SPEED = 1, CODE_SIZE = 2, LITE_RUNTIME = 3, @@ -3015,7 +3018,7 @@ namespace Google.Protobuf.DescriptorProtos { public void WriteTo(pb::ICodedOutputStream output) { string[] fieldNames = _fieldNames; if (Ctype != global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.CType.STRING) { - output.WriteEnum(1, fieldNames[0], Ctype); + output.WriteEnum(1, fieldNames[0], (int) Ctype); } if (Packed != false) { output.WriteBool(2, fieldNames[4], Packed); @@ -3027,7 +3030,7 @@ namespace Google.Protobuf.DescriptorProtos { output.WriteBool(5, fieldNames[3], Lazy); } if (Jstype != global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.JSType.JS_NORMAL) { - output.WriteEnum(6, fieldNames[2], Jstype); + output.WriteEnum(6, fieldNames[2], (int) Jstype); } if (Weak != false) { output.WriteBool(10, fieldNames[6], Weak); @@ -3038,13 +3041,13 @@ namespace Google.Protobuf.DescriptorProtos { public int CalculateSize() { int size = 0; if (Ctype != global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.CType.STRING) { - size += pb::CodedOutputStream.ComputeEnumSize(1, Ctype); + size += pb::CodedOutputStream.ComputeEnumSize(1, (int) Ctype); } if (Packed != false) { size += pb::CodedOutputStream.ComputeBoolSize(2, Packed); } if (Jstype != global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.JSType.JS_NORMAL) { - size += pb::CodedOutputStream.ComputeEnumSize(6, Jstype); + size += pb::CodedOutputStream.ComputeEnumSize(6, (int) Jstype); } if (Lazy != false) { size += pb::CodedOutputStream.ComputeBoolSize(5, Lazy); @@ -3104,8 +3107,9 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 8: { - input.ReadEnum(ref ctype_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + ctype_ = (global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.CType) tmp;break; } case 16: { input.ReadBool(ref packed_); @@ -3120,8 +3124,9 @@ namespace Google.Protobuf.DescriptorProtos { break; } case 48: { - input.ReadEnum(ref jstype_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + jstype_ = (global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.JSType) tmp;break; } case 80: { input.ReadBool(ref weak_); @@ -3138,13 +3143,13 @@ namespace Google.Protobuf.DescriptorProtos { #region Nested types [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public static partial class Types { - public enum CType : long { + public enum CType { STRING = 0, CORD = 1, STRING_PIECE = 2, } - public enum JSType : long { + public enum JSType { JS_NORMAL = 0, JS_STRING = 1, JS_NUMBER = 2, diff --git a/csharp/src/ProtocolBuffers/EnumHelper.cs b/csharp/src/ProtocolBuffers/EnumHelper.cs deleted file mode 100644 index 1cf189858..000000000 --- a/csharp/src/ProtocolBuffers/EnumHelper.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Text; - -namespace Google.Protobuf -{ - public class EnumHelper where T : struct, IComparable, IFormattable - { - // TODO(jonskeet): For snmall enums, use something lighter-weight than a dictionary? - private static readonly Dictionary _byNumber; - private static readonly Dictionary _byName; - private static readonly Func toRawValue; - private static readonly Func fromRawValue; - - private const long UnknownValueBase = 0x100000000L; - - static EnumHelper() - { - if (!typeof(T).IsEnum) - { - throw new InvalidOperationException(string.Format("{0} is not an enum type", typeof(T).FullName)); - } - if (Enum.GetUnderlyingType(typeof(T)) != typeof(long)) - { - throw new InvalidOperationException(string.Format("{0} does not have long as an underlying type", typeof(T).FullName)); - } - // It will actually be a T[], but the CLR will let us convert. - long[] array = (long[])Enum.GetValues(typeof(T)); - _byNumber = new Dictionary(array.Length); - foreach (long i in array) - { - _byNumber[(int) i] = (T)(object)i; - } - string[] names = (string[])Enum.GetNames(typeof(T)); - _byName = new Dictionary(); - foreach (var name in names) - { - _byName[name] = (T) Enum.Parse(typeof(T), name, false); - } - - ParameterExpression param1 = Expression.Parameter(typeof(T), "x"); - ParameterExpression param2 = Expression.Parameter(typeof(long), "x"); - Expression convertedParam1 = Expression.Convert(param1, typeof(long)); - Expression convertedParam2 = Expression.Convert(param2, typeof(T)); - toRawValue = Expression.Lambda>(convertedParam1, param1).Compile(); - fromRawValue = Expression.Lambda>(convertedParam2, param2).Compile(); - } - - /// - /// Converts the given 32-bit integer into a value of the enum type. - /// If the integer is a known, named value, that is returned; otherwise, - /// a value which is outside the range of 32-bit integers but which preserves - /// the original integer is returned. - /// - public static T FromInt32(int value) - { - T validValue; - return _byNumber.TryGetValue(value, out validValue) ? validValue : FromRawValue((long) value | UnknownValueBase); - } - - /// - /// Converts a value of the enum type to a 32-bit integer. This reverses - /// . - /// - public static int ToInt32(T value) - { - return (int)GetRawValue(value); - } - - public static bool IsKnownValue(T value) - { - long raw = GetRawValue(value); - if (raw >= int.MinValue && raw <= int.MaxValue) - { - return _byNumber.ContainsKey((int)raw); - } - return false; - } - - private static long GetRawValue(T value) - { - return toRawValue(value); - } - - private static T FromRawValue(long value) - { - return fromRawValue(value); - } - - } -} diff --git a/csharp/src/ProtocolBuffers/ICodedInputStream.cs b/csharp/src/ProtocolBuffers/ICodedInputStream.cs index 748589a00..d962e62bf 100644 --- a/csharp/src/ProtocolBuffers/ICodedInputStream.cs +++ b/csharp/src/ProtocolBuffers/ICodedInputStream.cs @@ -146,14 +146,11 @@ namespace Google.Protobuf bool ReadUInt32(ref uint value); /// - /// Reads an enum field value from the stream. If the enum is valid for type T, - /// then the ref value is set and it returns true. Otherwise, if a value is present - /// but invalid for the proto enum, it is still set in the field as a "preserved - /// but invalid" value, and the method returns true. If no value can be read, the - /// method does not affect the parameter and returns false. + /// Reads an enum field value from the stream. This performs no checking + /// as to whether the enum value is known to the enum type as it was present + /// when the code was generated. /// - bool ReadEnum(ref T value) - where T : struct, IComparable, IFormattable; + bool ReadEnum(ref int value); /// /// Reads an sfixed32 field value from the stream. diff --git a/csharp/src/ProtocolBuffers/ICodedOutputStream.cs b/csharp/src/ProtocolBuffers/ICodedOutputStream.cs index e51c10a49..921400aca 100644 --- a/csharp/src/ProtocolBuffers/ICodedOutputStream.cs +++ b/csharp/src/ProtocolBuffers/ICodedOutputStream.cs @@ -148,7 +148,7 @@ namespace Google.Protobuf /// /// Writes an enum field value, including tag, to the stream. /// - void WriteEnum(int fieldNumber, string fieldName, T value) where T : struct, IComparable, IFormattable; + void WriteEnum(int fieldNumber, string fieldName, int value); /// /// Writes a fixed 32-bit field value, including tag, to the stream. diff --git a/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj b/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj index d15f13069..efd387a27 100644 --- a/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj +++ b/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj @@ -84,7 +84,6 @@ - diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.cc b/src/google/protobuf/compiler/csharp/csharp_enum.cc index d511bba3b..0e8f98369 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum.cc @@ -58,7 +58,7 @@ EnumGenerator::~EnumGenerator() { void EnumGenerator::Generate(io::Printer* printer) { WriteGeneratedCodeAttributes(printer); - printer->Print("$access_level$ enum $name$ : long {\n", + printer->Print("$access_level$ enum $name$ {\n", "access_level", class_access_level(), "name", descriptor_->name()); printer->Indent(); diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc index ee9d6a1d2..3494b2280 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc @@ -54,14 +54,17 @@ EnumFieldGenerator::~EnumFieldGenerator() { } void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { + // TODO(jonskeet): Get rid of the temporary variable when we sanitize CodedInputStream not to use ref. printer->Print(variables_, - "input.ReadEnum(ref $name$_);\n"); + "int tmp = 0;\n" + "input.ReadEnum(ref tmp);\n" + "$name$_ = ($type_name$) tmp;"); } void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print(variables_, "if ($has_property_check$) {\n" - " output.WriteEnum($number$, fieldNames[$field_ordinal$], $property_name$);\n" + " output.WriteEnum($number$, fieldNames[$field_ordinal$], (int) $property_name$);\n" "}\n"); } @@ -69,7 +72,7 @@ void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " size += pb::CodedOutputStream.ComputeEnumSize($number$, $property_name$);\n" + " size += pb::CodedOutputStream.ComputeEnumSize($number$, (int) $property_name$);\n" "}\n"); } @@ -85,7 +88,7 @@ void EnumOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { // TODO(jonskeet): What about if we read the default value? printer->Print( variables_, - "$type_name$ enumValue = $default_value$;\n" + "int enumValue = 0;\n" "if(input.ReadEnum(ref enumValue)) {\n" " $oneof_name$_ = enumValue;\n" " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" @@ -96,7 +99,7 @@ void EnumOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " output.WriteEnum($number$, fieldNames[$field_ordinal$], (long) $property_name$, $property_name$);\n" + " output.WriteEnum($number$, fieldNames[$field_ordinal$], (int) $property_name$);\n" "}\n"); } @@ -104,7 +107,7 @@ void EnumOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " size += pb::CodedOutputStream.ComputeEnumSize($number$, (long) $property_name$);\n" + " size += pb::CodedOutputStream.ComputeEnumSize($number$, (int) $property_name$);\n" "}\n"); } 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 ebbbf3bee..937d675a5 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc @@ -99,7 +99,7 @@ void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer printer->Print( variables_, "foreach ($type_name$ element in $name$_) {\n" - " dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element);\n" + " dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);\n" "}\n" "size += dataSize;\n"); int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());