فهرست منبع

Use a switch instead of a map for WireFormat.

Jon Skeet 17 سال پیش
والد
کامیت
6d0cbe7200
3فایلهای تغییر یافته به همراه48 افزوده شده و 17 حذف شده
  1. 9 5
      csharp/ProtocolBuffers.Test/WireFormatTest.cs
  2. 1 1
      csharp/ProtocolBuffers/UnknownFieldSet.cs
  3. 38 11
      csharp/ProtocolBuffers/WireFormat.cs

+ 9 - 5
csharp/ProtocolBuffers.Test/WireFormatTest.cs

@@ -13,6 +13,7 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+using System.Reflection;
 using Google.ProtocolBuffers.Descriptors;
 using Google.ProtocolBuffers.TestProtos;
 using NUnit.Framework;
@@ -21,13 +22,16 @@ namespace Google.ProtocolBuffers {
   [TestFixture]
   public class WireFormatTest {
 
+    /// <summary>
+    /// Keeps the attributes on FieldType and the switch statement in WireFormat in sync.
+    /// </summary>
     [Test]
     public void FieldTypeToWireTypeMapping() {
-
-      // Just test a few values
-      Assert.AreEqual(WireFormat.WireType.Fixed64, WireFormat.FieldTypeToWireFormatMap[FieldType.SFixed64]);
-      Assert.AreEqual(WireFormat.WireType.LengthDelimited, WireFormat.FieldTypeToWireFormatMap[FieldType.String]);
-      Assert.AreEqual(WireFormat.WireType.LengthDelimited, WireFormat.FieldTypeToWireFormatMap[FieldType.Message]);
+      foreach (FieldInfo field in typeof(FieldType).GetFields(BindingFlags.Static | BindingFlags.Public)) {
+        FieldType fieldType = (FieldType)field.GetValue(null);
+        FieldMappingAttribute mapping = (FieldMappingAttribute)field.GetCustomAttributes(typeof(FieldMappingAttribute), false)[0];
+        Assert.AreEqual(mapping.WireType, WireFormat.GetWireType(fieldType));
+      }
     }
 
     [Test]

+ 1 - 1
csharp/ProtocolBuffers/UnknownFieldSet.cs

@@ -480,7 +480,7 @@ namespace Google.ProtocolBuffers {
         }
 
         // Unknown field or wrong wire type. Skip.
-        if (field == null || wireType != WireFormat.FieldTypeToWireFormatMap[field.FieldType]) {
+        if (field == null || wireType != WireFormat.GetWireType(field.FieldType)) {
           return MergeFieldFrom(tag, input);
         }
 

+ 38 - 11
csharp/ProtocolBuffers/WireFormat.cs

@@ -13,6 +13,7 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+using System;
 using System.Reflection;
 using Google.ProtocolBuffers.Descriptors;
 using System.Collections.Generic;
@@ -77,19 +78,45 @@ namespace Google.ProtocolBuffers {
     }
 
     /// <summary>
-    /// Immutable mapping from field type to wire type. Built using the attributes on
-    /// FieldType values.
+    /// Converts a field type to its wire type. Done with a switch for the sake
+    /// of speed - this is significantly faster than a dictionary lookup.
     /// </summary>
-    public static readonly IDictionary<FieldType, WireType> FieldTypeToWireFormatMap = MapFieldTypes();
-
-    private static IDictionary<FieldType, WireType> MapFieldTypes() {
-      var map = new Dictionary<FieldType, WireType>();
-      foreach (FieldInfo field in typeof(FieldType).GetFields(BindingFlags.Static | BindingFlags.Public)) {
-        FieldType fieldType = (FieldType) field.GetValue(null);
-        FieldMappingAttribute mapping = (FieldMappingAttribute)field.GetCustomAttributes(typeof(FieldMappingAttribute), false)[0];
-        map[fieldType] = mapping.WireType;
+    public static WireType GetWireType(FieldType fieldType) {
+      switch (fieldType) {
+        case FieldType.Double:
+          return WireType.Fixed64;
+        case FieldType.Float:
+          return WireType.Fixed32;
+        case FieldType.Int64:
+        case FieldType.UInt64:
+        case FieldType.Int32:
+          return WireType.Varint;
+        case FieldType.Fixed64:
+          return WireType.Fixed64;
+        case FieldType.Fixed32:
+          return WireType.Fixed32;
+        case FieldType.Bool:
+          return WireType.Varint;
+        case FieldType.String:
+          return WireType.LengthDelimited;
+        case FieldType.Group:
+          return WireType.StartGroup;
+        case FieldType.Message:
+        case FieldType.Bytes:
+          return WireType.LengthDelimited;
+        case FieldType.UInt32:
+          return WireType.Varint;
+        case FieldType.SFixed32:
+          return WireType.Fixed32;
+        case FieldType.SFixed64:
+          return WireType.Fixed64;
+        case FieldType.SInt32:
+        case FieldType.SInt64:
+        case FieldType.Enum:
+          return WireType.Varint;
+        default:
+          throw new ArgumentOutOfRangeException("No such field type");
       }
-      return Dictionaries.AsReadOnly(map);
     }
   }
 }