Browse Source

Refactoring of CodedInputStream.Read??? to use boolean return with out param.

csharptest 14 years ago
parent
commit
d2af9e923f
35 changed files with 1496 additions and 1372 deletions
  1. 14 18
      src/AddressBook/AddressBookProtos.cs
  2. 19 6
      src/ProtoGen/EnumFieldGenerator.cs
  3. 1 1
      src/ProtoGen/MessageGenerator.cs
  4. 1 1
      src/ProtoGen/PrimitiveFieldGenerator.cs
  5. 38 24
      src/ProtoGen/RepeatedEnumFieldGenerator.cs
  6. 13 10
      src/ProtoGen/RepeatedMessageFieldGenerator.cs
  7. 14 13
      src/ProtoGen/RepeatedPrimitiveFieldGenerator.cs
  8. 4 2
      src/ProtocolBuffers.Test/CodedInputStreamTest.cs
  9. 4 4
      src/ProtocolBuffers.Test/TestProtos/UnitTestCSharpOptionsProtoFile.cs
  10. 26 26
      src/ProtocolBuffers.Test/TestProtos/UnitTestCustomOptionsProtoFile.cs
  11. 2 4
      src/ProtocolBuffers.Test/TestProtos/UnitTestEmbedOptimizeForProtoFile.cs
  12. 121 123
      src/ProtocolBuffers.Test/TestProtos/UnitTestGoogleSpeedProtoFile.cs
  13. 2 2
      src/ProtocolBuffers.Test/TestProtos/UnitTestImportLiteProtoFile.cs
  14. 2 2
      src/ProtocolBuffers.Test/TestProtos/UnitTestImportProtoFile.cs
  15. 11 13
      src/ProtocolBuffers.Test/TestProtos/UnitTestMessageSetProtoFile.cs
  16. 2 2
      src/ProtocolBuffers.Test/TestProtos/UnitTestNoGenericServicesProtoFile.cs
  17. 200 210
      src/ProtocolBuffers.Test/TestProtos/UnitTestProtoFile.cs
  18. 9 11
      src/ProtocolBuffers.Test/TestProtos/UnitTestRpcInterop.cs
  19. 26 26
      src/ProtocolBuffers.Test/TestProtos/UnitTestXmlSerializerTestProtoFile.cs
  20. 341 57
      src/ProtocolBuffers/CodedInputStream.cs
  21. 24 24
      src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs
  22. 94 134
      src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
  23. 4 0
      src/ProtocolBuffers/Descriptors/EnumDescriptor.cs
  24. 9 0
      src/ProtocolBuffers/EnumLite.cs
  25. 2 2
      src/ProtocolBuffers/ExtendableBuilder.cs
  26. 60 98
      src/ProtocolBuffers/ExtendableBuilderLite.cs
  27. 1 1
      src/ProtocolBuffers/GeneratedBuilder.cs
  28. 1 1
      src/ProtocolBuffers/GeneratedBuilderLite.cs
  29. 100 97
      src/ProtocolBuffers/UnknownFieldSet.cs
  30. 27 36
      src/ProtocolBuffersLite.Test/TestProtos/UnitTestExtrasLiteProtoFile.cs
  31. 2 2
      src/ProtocolBuffersLite.Test/TestProtos/UnitTestImportLiteProtoFile.cs
  32. 2 2
      src/ProtocolBuffersLite.Test/TestProtos/UnitTestImportProtoFile.cs
  33. 1 1
      src/ProtocolBuffersLite.Test/TestProtos/UnitTestLiteImportNonLiteProtoFile.cs
  34. 119 209
      src/ProtocolBuffersLite.Test/TestProtos/UnitTestLiteProtoFile.cs
  35. 200 210
      src/ProtocolBuffersLite.Test/TestProtos/UnitTestProtoFile.cs

+ 14 - 18
src/AddressBook/AddressBookProtos.cs

@@ -304,22 +304,22 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
                   if (unknownFields == null) {
                     unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                   }
-                  ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+                  ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
                   break;
                 }
                 case 10: {
-                  Number = input.ReadString();
+                  result.hasNumber |= input.ReadString(ref result.number_);
                   break;
                 }
                 case 16: {
-                  int rawValue = input.ReadEnum();
-                  if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneType), rawValue)) {
+                  object unknown;
+                  if(input.ReadEnum(ref result.type_, out unknown)) {
+                    result.hasType = true;
+                  } else if(unknown is int) {
                     if (unknownFields == null) {
                       unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                     }
-                    unknownFields.MergeVarintField(2, (ulong) rawValue);
-                  } else {
-                    Type = (global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneType) rawValue;
+                    unknownFields.MergeVarintField(2, (ulong)(int)unknown);
                   }
                   break;
                 }
@@ -602,25 +602,23 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              Name = input.ReadString();
+              result.hasName |= input.ReadString(ref result.name_);
               break;
             }
             case 16: {
-              Id = input.ReadInt32();
+              result.hasId |= input.ReadInt32(ref result.id_);
               break;
             }
             case 26: {
-              Email = input.ReadString();
+              result.hasEmail |= input.ReadString(ref result.email_);
               break;
             }
             case 34: {
-              global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber.Builder subBuilder = global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddPhone(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.phone_, global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber.DefaultInstance, extensionRegistry);
               break;
             }
           }
@@ -922,13 +920,11 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              global::Google.ProtocolBuffers.Examples.AddressBook.Person.Builder subBuilder = global::Google.ProtocolBuffers.Examples.AddressBook.Person.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddPerson(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.person_, global::Google.ProtocolBuffers.Examples.AddressBook.Person.DefaultInstance, extensionRegistry);
               break;
             }
           }

+ 19 - 6
src/ProtoGen/EnumFieldGenerator.cs

@@ -95,19 +95,32 @@ namespace Google.ProtocolBuffers.ProtoGen
 
         public void GenerateParsingCode(TextGenerator writer)
         {
-            // TODO(jonskeet): Make a more efficient way of doing this
-            writer.WriteLine("int rawValue = input.ReadEnum();");
-            writer.WriteLine("if (!global::System.Enum.IsDefined(typeof({0}), rawValue)) {{", TypeName);
+            writer.WriteLine("object unknown;");
+            writer.WriteLine("if(input.ReadEnum(ref result.{0}_, out unknown)) {{", Name);
+            writer.WriteLine("  result.has{0} = true;", PropertyName);
+            writer.WriteLine("} else if(unknown is int) {");
             if (!UseLiteRuntime)
             {
                 writer.WriteLine("  if (unknownFields == null) {"); // First unknown field - create builder now
                 writer.WriteLine("    unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);");
                 writer.WriteLine("  }");
-                writer.WriteLine("  unknownFields.MergeVarintField({0}, (ulong) rawValue);", Number);
+                writer.WriteLine("  unknownFields.MergeVarintField({0}, (ulong)(int)unknown);", Number);
             }
-            writer.WriteLine("} else {");
-            writer.WriteLine("  {0} = ({1}) rawValue;", PropertyName, TypeName);
             writer.WriteLine("}");
+
+            // TO DO(jonskeet): Make a more efficient way of doing this
+            //writer.WriteLine("int rawValue = input.ReadEnum();");
+            //writer.WriteLine("if (!global::System.Enum.IsDefined(typeof({0}), rawValue)) {{", TypeName);
+            //if (!UseLiteRuntime)
+            //{
+            //    writer.WriteLine("  if (unknownFields == null) {"); // First unknown field - create builder now
+            //    writer.WriteLine("    unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);");
+            //    writer.WriteLine("  }");
+            //    writer.WriteLine("  unknownFields.MergeVarintField({0}, (ulong) rawValue);", Number);
+            //}
+            //writer.WriteLine("} else {");
+            //writer.WriteLine("  {0} = ({1}) rawValue;", PropertyName, TypeName);
+            //writer.WriteLine("}");
         }
 
         public void GenerateSerializationCode(TextGenerator writer)

+ 1 - 1
src/ProtoGen/MessageGenerator.cs

@@ -647,7 +647,7 @@ namespace Google.ProtocolBuffers.ProtoGen
                 writer.WriteLine("    unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);");
                 writer.WriteLine("  }");
             }
-            writer.WriteLine("  ParseUnknownField(input, {0}extensionRegistry, tag);",
+            writer.WriteLine("  ParseUnknownField(input, {0}extensionRegistry, tag, field_name);",
                              UseLiteRuntime ? "" : "unknownFields, ");
             writer.WriteLine("  break;");
             writer.WriteLine("}");

+ 1 - 1
src/ProtoGen/PrimitiveFieldGenerator.cs

@@ -97,7 +97,7 @@ namespace Google.ProtocolBuffers.ProtoGen
 
         public void GenerateParsingCode(TextGenerator writer)
         {
-            writer.WriteLine("{0} = input.Read{1}();", PropertyName, CapitalizedTypeName);
+            writer.WriteLine("result.has{0} |= input.Read{1}(ref result.{2}_);", PropertyName, CapitalizedTypeName, Name);
         }
 
         public void GenerateSerializationCode(TextGenerator writer)

+ 38 - 24
src/ProtoGen/RepeatedEnumFieldGenerator.cs

@@ -112,36 +112,50 @@ namespace Google.ProtocolBuffers.ProtoGen
 
         public void GenerateParsingCode(TextGenerator writer)
         {
-            // If packed, set up the while loop
-            if (Descriptor.IsPacked)
-            {
-                writer.WriteLine("int length = input.ReadInt32();");
-                writer.WriteLine("int oldLimit = input.PushLimit(length);");
-                writer.WriteLine("while (!input.ReachedLimit) {");
-                writer.Indent();
-            }
-
-            // Read and store the enum
-            // TODO(jonskeet): Make a more efficient way of doing this
-            writer.WriteLine("int rawValue = input.ReadEnum();");
-            writer.WriteLine("if (!global::System.Enum.IsDefined(typeof({0}), rawValue)) {{", TypeName);
+            writer.WriteLine("scg::ICollection<object> unknownItems;");
+            writer.WriteLine("input.ReadEnumArray<{0}>(tag, field_name, result.{1}_, out unknownItems);", TypeName, Name);
             if (!UseLiteRuntime)
             {
-                writer.WriteLine("  if (unknownFields == null) {"); // First unknown field - create builder now
+                writer.WriteLine("if (unknownItems != null) {");
+                writer.WriteLine("  if (unknownFields == null) {");
                 writer.WriteLine("    unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);");
                 writer.WriteLine("  }");
-                writer.WriteLine("  unknownFields.MergeVarintField({0}, (ulong) rawValue);", Number);
-            }
-            writer.WriteLine("} else {");
-            writer.WriteLine("  Add{0}(({1}) rawValue);", PropertyName, TypeName);
-            writer.WriteLine("}");
-
-            if (Descriptor.IsPacked)
-            {
-                writer.Outdent();
+                writer.WriteLine("  foreach (object rawValue in unknownItems)");
+                writer.WriteLine("    if (rawValue is int)");
+                writer.WriteLine("      unknownFields.MergeVarintField({0}, (ulong)(int)rawValue);", Number);
                 writer.WriteLine("}");
-                writer.WriteLine("input.PopLimit(oldLimit);");
             }
+
+            //// If packed, set up the while loop
+            //if (Descriptor.IsPacked)
+            //{
+            //    writer.WriteLine("int length = input.ReadInt32();");
+            //    writer.WriteLine("int oldLimit = input.PushLimit(length);");
+            //    writer.WriteLine("while (!input.ReachedLimit) {");
+            //    writer.Indent();
+            //}
+
+            //// Read and store the enum
+            //// TO DO(jonskeet): Make a more efficient way of doing this
+            //writer.WriteLine("int rawValue = input.ReadEnum();");
+            //writer.WriteLine("if (!global::System.Enum.IsDefined(typeof({0}), rawValue)) {{", TypeName);
+            //if (!UseLiteRuntime)
+            //{
+            //    writer.WriteLine("  if (unknownFields == null) {"); // First unknown field - create builder now
+            //    writer.WriteLine("    unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);");
+            //    writer.WriteLine("  }");
+            //    writer.WriteLine("  unknownFields.MergeVarintField({0}, (ulong) rawValue);", Number);
+            //}
+            //writer.WriteLine("} else {");
+            //writer.WriteLine("  Add{0}(({1}) rawValue);", PropertyName, TypeName);
+            //writer.WriteLine("}");
+
+            //if (Descriptor.IsPacked)
+            //{
+            //    writer.Outdent();
+            //    writer.WriteLine("}");
+            //    writer.WriteLine("input.PopLimit(oldLimit);");
+            //}
         }
 
         public void GenerateSerializationCode(TextGenerator writer)

+ 13 - 10
src/ProtoGen/RepeatedMessageFieldGenerator.cs

@@ -34,6 +34,7 @@
 
 #endregion
 
+using System;
 using Google.ProtocolBuffers.Descriptors;
 
 namespace Google.ProtocolBuffers.ProtoGen
@@ -121,16 +122,18 @@ namespace Google.ProtocolBuffers.ProtoGen
 
         public void GenerateParsingCode(TextGenerator writer)
         {
-            writer.WriteLine("{0}.Builder subBuilder = {0}.CreateBuilder();", TypeName);
-            if (Descriptor.FieldType == FieldType.Group)
-            {
-                writer.WriteLine("input.ReadGroup({0}, subBuilder, extensionRegistry);", Number);
-            }
-            else
-            {
-                writer.WriteLine("input.ReadMessage(subBuilder, extensionRegistry);");
-            }
-            writer.WriteLine("Add{0}(subBuilder.BuildPartial());", PropertyName);
+            writer.WriteLine("input.Read{0}Array(tag, field_name, result.{1}_, {2}.DefaultInstance, extensionRegistry);", MessageOrGroup, Name, TypeName);
+      
+            //writer.WriteLine("{0}.Builder subBuilder = {0}.CreateBuilder();", TypeName);
+            //if (Descriptor.FieldType == FieldType.Group)
+            //{
+            //    writer.WriteLine("input.ReadGroup({0}, subBuilder, extensionRegistry);", Number);
+            //}
+            //else
+            //{
+            //    writer.WriteLine("input.ReadMessage(subBuilder, extensionRegistry);");
+            //}
+            //writer.WriteLine("Add{0}(subBuilder.BuildPartial());", PropertyName);
         }
 
         public void GenerateSerializationCode(TextGenerator writer)

+ 14 - 13
src/ProtoGen/RepeatedPrimitiveFieldGenerator.cs

@@ -121,19 +121,20 @@ namespace Google.ProtocolBuffers.ProtoGen
 
         public void GenerateParsingCode(TextGenerator writer)
         {
-            if (Descriptor.IsPacked)
-            {
-                writer.WriteLine("int length = input.ReadInt32();");
-                writer.WriteLine("int limit = input.PushLimit(length);");
-                writer.WriteLine("while (!input.ReachedLimit) {");
-                writer.WriteLine("  Add{0}(input.Read{1}());", PropertyName, CapitalizedTypeName);
-                writer.WriteLine("}");
-                writer.WriteLine("input.PopLimit(limit);");
-            }
-            else
-            {
-                writer.WriteLine("Add{0}(input.Read{1}());", PropertyName, CapitalizedTypeName);
-            }
+            writer.WriteLine("input.ReadPrimitiveArray(pbd::FieldType.{1}, tag, field_name, result.{0}_);", Name, Descriptor.FieldType);
+            //if (Descriptor.IsPacked)
+            //{
+            //    writer.WriteLine("int length = input.ReadInt32();");
+            //    writer.WriteLine("int limit = input.PushLimit(length);");
+            //    writer.WriteLine("while (!input.ReachedLimit) {");
+            //    writer.WriteLine("  Add{0}(input.Read{1}());", PropertyName, CapitalizedTypeName);
+            //    writer.WriteLine("}");
+            //    writer.WriteLine("input.PopLimit(limit);");
+            //}
+            //else
+            //{
+            //    writer.WriteLine("Add{0}(input.Read{1}());", PropertyName, CapitalizedTypeName);
+            //}
         }
 
         public void GenerateSerializationCode(TextGenerator writer)

+ 4 - 2
src/ProtocolBuffers.Test/CodedInputStreamTest.cs

@@ -362,7 +362,8 @@ namespace Google.ProtocolBuffers
 
             try
             {
-                input.ReadBytes();
+                ByteString bytes = null;
+                input.ReadBytes(ref bytes);
                 Assert.Fail("Should have thrown an exception!");
             }
             catch (InvalidProtocolBufferException)
@@ -506,7 +507,8 @@ namespace Google.ProtocolBuffers
 
             Assert.IsTrue(input.ReadTag(out testtag, out ignored));
             Assert.AreEqual(tag, testtag);
-            string text = input.ReadString();
+            string text = null;
+            input.ReadString(ref text);
             Assert.AreEqual('\ufffd', text[0]);
         }
 

+ 4 - 4
src/ProtocolBuffers.Test/TestProtos/UnitTestCSharpOptionsProtoFile.cs

@@ -276,19 +276,19 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              Normal = input.ReadString();
+              result.hasNormal |= input.ReadString(ref result.normal_);
               break;
             }
             case 18: {
-              OptionsMessage_ = input.ReadString();
+              result.hasOptionsMessage_ |= input.ReadString(ref result.optionsMessage_);
               break;
             }
             case 26: {
-              CustomName = input.ReadString();
+              result.hasCustomName |= input.ReadString(ref result.customized_);
               break;
             }
           }

+ 26 - 26
src/ProtocolBuffers.Test/TestProtos/UnitTestCustomOptionsProtoFile.cs

@@ -593,11 +593,11 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              Field1 = input.ReadString();
+              result.hasField1 |= input.ReadString(ref result.field1_);
               break;
             }
           }
@@ -799,7 +799,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
           }
@@ -982,7 +982,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
           }
@@ -1180,7 +1180,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
           }
@@ -1363,7 +1363,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
           }
@@ -1546,7 +1546,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
           }
@@ -1729,7 +1729,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
           }
@@ -1912,7 +1912,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
           }
@@ -2095,7 +2095,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
           }
@@ -2278,7 +2278,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
           }
@@ -2523,19 +2523,19 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 8: {
-              Foo = input.ReadInt32();
+              result.hasFoo |= input.ReadInt32(ref result.foo_);
               break;
             }
             case 16: {
-              Foo2 = input.ReadInt32();
+              result.hasFoo2 |= input.ReadInt32(ref result.foo2_);
               break;
             }
             case 24: {
-              Foo3 = input.ReadInt32();
+              result.hasFoo3 |= input.ReadInt32(ref result.foo3_);
               break;
             }
           }
@@ -2823,11 +2823,11 @@ namespace Google.ProtocolBuffers.TestProtos {
                   if (unknownFields == null) {
                     unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                   }
-                  ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+                  ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
                   break;
                 }
                 case 8: {
-                  Waldo = input.ReadInt32();
+                  result.hasWaldo |= input.ReadInt32(ref result.waldo_);
                   break;
                 }
               }
@@ -3071,7 +3071,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
@@ -3084,7 +3084,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               break;
             }
             case 16: {
-              Baz = input.ReadInt32();
+              result.hasBaz |= input.ReadInt32(ref result.baz_);
               break;
             }
             case 26: {
@@ -3415,11 +3415,11 @@ namespace Google.ProtocolBuffers.TestProtos {
                   if (unknownFields == null) {
                     unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                   }
-                  ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+                  ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
                   break;
                 }
                 case 24: {
-                  Plugh = input.ReadInt32();
+                  result.hasPlugh |= input.ReadInt32(ref result.plugh_);
                   break;
                 }
               }
@@ -3636,11 +3636,11 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 8: {
-              Qux = input.ReadInt32();
+              result.hasQux |= input.ReadInt32(ref result.qux_);
               break;
             }
             case 19: {
@@ -3905,11 +3905,11 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 60751608: {
-              Xyzzy = input.ReadInt32();
+              result.hasXyzzy |= input.ReadInt32(ref result.xyzzy_);
               break;
             }
           }
@@ -4110,7 +4110,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
           }

+ 2 - 4
src/ProtocolBuffers.Test/TestProtos/UnitTestEmbedOptimizeForProtoFile.cs

@@ -270,7 +270,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
@@ -283,9 +283,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               break;
             }
             case 18: {
-              global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddRepeatedMessage(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.repeatedMessage_, global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.DefaultInstance, extensionRegistry);
               break;
             }
           }

+ 121 - 123
src/ProtocolBuffers.Test/TestProtos/UnitTestGoogleSpeedProtoFile.cs

@@ -1086,51 +1086,51 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              Field1 = input.ReadString();
+              result.hasField1 |= input.ReadString(ref result.field1_);
               break;
             }
             case 16: {
-              Field2 = input.ReadInt32();
+              result.hasField2 |= input.ReadInt32(ref result.field2_);
               break;
             }
             case 24: {
-              Field3 = input.ReadInt32();
+              result.hasField3 |= input.ReadInt32(ref result.field3_);
               break;
             }
             case 34: {
-              Field4 = input.ReadString();
+              result.hasField4 |= input.ReadString(ref result.field4_);
               break;
             }
             case 41: {
-              AddField5(input.ReadFixed64());
+              input.ReadPrimitiveArray(pbd::FieldType.Fixed64, tag, field_name, result.field5_);
               break;
             }
             case 48: {
-              Field6 = input.ReadInt32();
+              result.hasField6 |= input.ReadInt32(ref result.field6_);
               break;
             }
             case 58: {
-              Field7 = input.ReadString();
+              result.hasField7 |= input.ReadString(ref result.field7_);
               break;
             }
             case 74: {
-              Field9 = input.ReadString();
+              result.hasField9 |= input.ReadString(ref result.field9_);
               break;
             }
             case 96: {
-              Field12 = input.ReadBool();
+              result.hasField12 |= input.ReadBool(ref result.field12_);
               break;
             }
             case 104: {
-              Field13 = input.ReadBool();
+              result.hasField13 |= input.ReadBool(ref result.field13_);
               break;
             }
             case 112: {
-              Field14 = input.ReadBool();
+              result.hasField14 |= input.ReadBool(ref result.field14_);
               break;
             }
             case 122: {
@@ -1143,119 +1143,119 @@ namespace Google.ProtocolBuffers.TestProtos {
               break;
             }
             case 128: {
-              Field16 = input.ReadInt32();
+              result.hasField16 |= input.ReadInt32(ref result.field16_);
               break;
             }
             case 136: {
-              Field17 = input.ReadBool();
+              result.hasField17 |= input.ReadBool(ref result.field17_);
               break;
             }
             case 146: {
-              Field18 = input.ReadString();
+              result.hasField18 |= input.ReadString(ref result.field18_);
               break;
             }
             case 176: {
-              Field22 = input.ReadInt64();
+              result.hasField22 |= input.ReadInt64(ref result.field22_);
               break;
             }
             case 184: {
-              Field23 = input.ReadInt32();
+              result.hasField23 |= input.ReadInt32(ref result.field23_);
               break;
             }
             case 192: {
-              Field24 = input.ReadBool();
+              result.hasField24 |= input.ReadBool(ref result.field24_);
               break;
             }
             case 200: {
-              Field25 = input.ReadInt32();
+              result.hasField25 |= input.ReadInt32(ref result.field25_);
               break;
             }
             case 232: {
-              Field29 = input.ReadInt32();
+              result.hasField29 |= input.ReadInt32(ref result.field29_);
               break;
             }
             case 240: {
-              Field30 = input.ReadBool();
+              result.hasField30 |= input.ReadBool(ref result.field30_);
               break;
             }
             case 472: {
-              Field59 = input.ReadBool();
+              result.hasField59 |= input.ReadBool(ref result.field59_);
               break;
             }
             case 480: {
-              Field60 = input.ReadInt32();
+              result.hasField60 |= input.ReadInt32(ref result.field60_);
               break;
             }
             case 536: {
-              Field67 = input.ReadInt32();
+              result.hasField67 |= input.ReadInt32(ref result.field67_);
               break;
             }
             case 544: {
-              Field68 = input.ReadInt32();
+              result.hasField68 |= input.ReadInt32(ref result.field68_);
               break;
             }
             case 624: {
-              Field78 = input.ReadBool();
+              result.hasField78 |= input.ReadBool(ref result.field78_);
               break;
             }
             case 640: {
-              Field80 = input.ReadBool();
+              result.hasField80 |= input.ReadBool(ref result.field80_);
               break;
             }
             case 648: {
-              Field81 = input.ReadBool();
+              result.hasField81 |= input.ReadBool(ref result.field81_);
               break;
             }
             case 800: {
-              Field100 = input.ReadInt32();
+              result.hasField100 |= input.ReadInt32(ref result.field100_);
               break;
             }
             case 808: {
-              Field101 = input.ReadInt32();
+              result.hasField101 |= input.ReadInt32(ref result.field101_);
               break;
             }
             case 818: {
-              Field102 = input.ReadString();
+              result.hasField102 |= input.ReadString(ref result.field102_);
               break;
             }
             case 826: {
-              Field103 = input.ReadString();
+              result.hasField103 |= input.ReadString(ref result.field103_);
               break;
             }
             case 832: {
-              Field104 = input.ReadInt32();
+              result.hasField104 |= input.ReadInt32(ref result.field104_);
               break;
             }
             case 1024: {
-              Field128 = input.ReadInt32();
+              result.hasField128 |= input.ReadInt32(ref result.field128_);
               break;
             }
             case 1034: {
-              Field129 = input.ReadString();
+              result.hasField129 |= input.ReadString(ref result.field129_);
               break;
             }
             case 1040: {
-              Field130 = input.ReadInt32();
+              result.hasField130 |= input.ReadInt32(ref result.field130_);
               break;
             }
             case 1048: {
-              Field131 = input.ReadInt32();
+              result.hasField131 |= input.ReadInt32(ref result.field131_);
               break;
             }
             case 1200: {
-              Field150 = input.ReadInt32();
+              result.hasField150 |= input.ReadInt32(ref result.field150_);
               break;
             }
             case 2168: {
-              Field271 = input.ReadInt32();
+              result.hasField271 |= input.ReadInt32(ref result.field271_);
               break;
             }
             case 2176: {
-              Field272 = input.ReadInt32();
+              result.hasField272 |= input.ReadInt32(ref result.field272_);
               break;
             }
             case 2240: {
-              Field280 = input.ReadInt32();
+              result.hasField280 |= input.ReadInt32(ref result.field280_);
               break;
             }
           }
@@ -2599,87 +2599,87 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 8: {
-              Field1 = input.ReadInt32();
+              result.hasField1 |= input.ReadInt32(ref result.field1_);
               break;
             }
             case 16: {
-              Field2 = input.ReadInt32();
+              result.hasField2 |= input.ReadInt32(ref result.field2_);
               break;
             }
             case 24: {
-              Field3 = input.ReadInt32();
+              result.hasField3 |= input.ReadInt32(ref result.field3_);
               break;
             }
             case 96: {
-              Field12 = input.ReadBool();
+              result.hasField12 |= input.ReadBool(ref result.field12_);
               break;
             }
             case 104: {
-              Field13 = input.ReadInt64();
+              result.hasField13 |= input.ReadInt64(ref result.field13_);
               break;
             }
             case 112: {
-              Field14 = input.ReadInt64();
+              result.hasField14 |= input.ReadInt64(ref result.field14_);
               break;
             }
             case 122: {
-              Field15 = input.ReadString();
+              result.hasField15 |= input.ReadString(ref result.field15_);
               break;
             }
             case 128: {
-              Field16 = input.ReadInt32();
+              result.hasField16 |= input.ReadInt32(ref result.field16_);
               break;
             }
             case 152: {
-              Field19 = input.ReadInt32();
+              result.hasField19 |= input.ReadInt32(ref result.field19_);
               break;
             }
             case 160: {
-              Field20 = input.ReadBool();
+              result.hasField20 |= input.ReadBool(ref result.field20_);
               break;
             }
             case 169: {
-              Field21 = input.ReadFixed64();
+              result.hasField21 |= input.ReadFixed64(ref result.field21_);
               break;
             }
             case 176: {
-              Field22 = input.ReadInt32();
+              result.hasField22 |= input.ReadInt32(ref result.field22_);
               break;
             }
             case 184: {
-              Field23 = input.ReadBool();
+              result.hasField23 |= input.ReadBool(ref result.field23_);
               break;
             }
             case 224: {
-              Field28 = input.ReadBool();
+              result.hasField28 |= input.ReadBool(ref result.field28_);
               break;
             }
             case 1629: {
-              Field203 = input.ReadFixed32();
+              result.hasField203 |= input.ReadFixed32(ref result.field203_);
               break;
             }
             case 1632: {
-              Field204 = input.ReadInt32();
+              result.hasField204 |= input.ReadInt32(ref result.field204_);
               break;
             }
             case 1642: {
-              Field205 = input.ReadString();
+              result.hasField205 |= input.ReadString(ref result.field205_);
               break;
             }
             case 1648: {
-              Field206 = input.ReadBool();
+              result.hasField206 |= input.ReadBool(ref result.field206_);
               break;
             }
             case 1656: {
-              Field207 = input.ReadUInt64();
+              result.hasField207 |= input.ReadUInt64(ref result.field207_);
               break;
             }
             case 2400: {
-              Field300 = input.ReadUInt64();
+              result.hasField300 |= input.ReadUInt64(ref result.field300_);
               break;
             }
           }
@@ -3593,63 +3593,63 @@ namespace Google.ProtocolBuffers.TestProtos {
                   if (unknownFields == null) {
                     unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                   }
-                  ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+                  ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
                   break;
                 }
                 case 40: {
-                  Field5 = input.ReadInt32();
+                  result.hasField5 |= input.ReadInt32(ref result.field5_);
                   break;
                 }
                 case 93: {
-                  Field11 = input.ReadFloat();
+                  result.hasField11 |= input.ReadFloat(ref result.field11_);
                   break;
                 }
                 case 98: {
-                  Field12 = input.ReadString();
+                  result.hasField12 |= input.ReadString(ref result.field12_);
                   break;
                 }
                 case 106: {
-                  Field13 = input.ReadString();
+                  result.hasField13 |= input.ReadString(ref result.field13_);
                   break;
                 }
                 case 114: {
-                  AddField14(input.ReadString());
+                  input.ReadPrimitiveArray(pbd::FieldType.String, tag, field_name, result.field14_);
                   break;
                 }
                 case 120: {
-                  Field15 = input.ReadUInt64();
+                  result.hasField15 |= input.ReadUInt64(ref result.field15_);
                   break;
                 }
                 case 130: {
-                  Field16 = input.ReadString();
+                  result.hasField16 |= input.ReadString(ref result.field16_);
                   break;
                 }
                 case 160: {
-                  Field20 = input.ReadInt32();
+                  result.hasField20 |= input.ReadInt32(ref result.field20_);
                   break;
                 }
                 case 178: {
-                  AddField22(input.ReadString());
+                  input.ReadPrimitiveArray(pbd::FieldType.String, tag, field_name, result.field22_);
                   break;
                 }
                 case 194: {
-                  Field24 = input.ReadString();
+                  result.hasField24 |= input.ReadString(ref result.field24_);
                   break;
                 }
                 case 213: {
-                  Field26 = input.ReadFloat();
+                  result.hasField26 |= input.ReadFloat(ref result.field26_);
                   break;
                 }
                 case 218: {
-                  Field27 = input.ReadString();
+                  result.hasField27 |= input.ReadString(ref result.field27_);
                   break;
                 }
                 case 224: {
-                  Field28 = input.ReadInt32();
+                  result.hasField28 |= input.ReadInt32(ref result.field28_);
                   break;
                 }
                 case 234: {
-                  Field29 = input.ReadString();
+                  result.hasField29 |= input.ReadString(ref result.field29_);
                   break;
                 }
                 case 250: {
@@ -3662,7 +3662,7 @@ namespace Google.ProtocolBuffers.TestProtos {
                   break;
                 }
                 case 584: {
-                  AddField73(input.ReadInt32());
+                  input.ReadPrimitiveArray(pbd::FieldType.Int32, tag, field_name, result.field73_);
                   break;
                 }
               }
@@ -4762,129 +4762,127 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              Field1 = input.ReadString();
+              result.hasField1 |= input.ReadString(ref result.field1_);
               break;
             }
             case 18: {
-              Field2 = input.ReadBytes();
+              result.hasField2 |= input.ReadBytes(ref result.field2_);
               break;
             }
             case 24: {
-              Field3 = input.ReadInt64();
+              result.hasField3 |= input.ReadInt64(ref result.field3_);
               break;
             }
             case 32: {
-              Field4 = input.ReadInt64();
+              result.hasField4 |= input.ReadInt64(ref result.field4_);
               break;
             }
             case 50: {
-              Field6 = input.ReadString();
+              result.hasField6 |= input.ReadString(ref result.field6_);
               break;
             }
             case 83: {
-              global::Google.ProtocolBuffers.TestProtos.SpeedMessage2.Types.Group1.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.SpeedMessage2.Types.Group1.CreateBuilder();
-              input.ReadGroup(10, subBuilder, extensionRegistry);
-              AddGroup1(subBuilder.BuildPartial());
+              input.ReadGroupArray(tag, field_name, result.group1_, global::Google.ProtocolBuffers.TestProtos.SpeedMessage2.Types.Group1.DefaultInstance, extensionRegistry);
               break;
             }
             case 168: {
-              Field21 = input.ReadInt32();
+              result.hasField21 |= input.ReadInt32(ref result.field21_);
               break;
             }
             case 205: {
-              Field25 = input.ReadFloat();
+              result.hasField25 |= input.ReadFloat(ref result.field25_);
               break;
             }
             case 240: {
-              Field30 = input.ReadInt64();
+              result.hasField30 |= input.ReadInt64(ref result.field30_);
               break;
             }
             case 504: {
-              Field63 = input.ReadInt32();
+              result.hasField63 |= input.ReadInt32(ref result.field63_);
               break;
             }
             case 568: {
-              Field71 = input.ReadInt32();
+              result.hasField71 |= input.ReadInt32(ref result.field71_);
               break;
             }
             case 600: {
-              Field75 = input.ReadBool();
+              result.hasField75 |= input.ReadBool(ref result.field75_);
               break;
             }
             case 872: {
-              Field109 = input.ReadInt32();
+              result.hasField109 |= input.ReadInt32(ref result.field109_);
               break;
             }
             case 1018: {
-              AddField127(input.ReadString());
+              input.ReadPrimitiveArray(pbd::FieldType.String, tag, field_name, result.field127_);
               break;
             }
             case 1026: {
-              AddField128(input.ReadString());
+              input.ReadPrimitiveArray(pbd::FieldType.String, tag, field_name, result.field128_);
               break;
             }
             case 1032: {
-              Field129 = input.ReadInt32();
+              result.hasField129 |= input.ReadInt32(ref result.field129_);
               break;
             }
             case 1040: {
-              AddField130(input.ReadInt64());
+              input.ReadPrimitiveArray(pbd::FieldType.Int64, tag, field_name, result.field130_);
               break;
             }
             case 1048: {
-              Field131 = input.ReadInt64();
+              result.hasField131 |= input.ReadInt64(ref result.field131_);
               break;
             }
             case 1640: {
-              Field205 = input.ReadBool();
+              result.hasField205 |= input.ReadBool(ref result.field205_);
               break;
             }
             case 1648: {
-              Field206 = input.ReadBool();
+              result.hasField206 |= input.ReadBool(ref result.field206_);
               break;
             }
             case 1680: {
-              Field210 = input.ReadInt32();
+              result.hasField210 |= input.ReadInt32(ref result.field210_);
               break;
             }
             case 1688: {
-              Field211 = input.ReadInt32();
+              result.hasField211 |= input.ReadInt32(ref result.field211_);
               break;
             }
             case 1696: {
-              Field212 = input.ReadInt32();
+              result.hasField212 |= input.ReadInt32(ref result.field212_);
               break;
             }
             case 1704: {
-              Field213 = input.ReadInt32();
+              result.hasField213 |= input.ReadInt32(ref result.field213_);
               break;
             }
             case 1728: {
-              Field216 = input.ReadInt32();
+              result.hasField216 |= input.ReadInt32(ref result.field216_);
               break;
             }
             case 1736: {
-              Field217 = input.ReadInt32();
+              result.hasField217 |= input.ReadInt32(ref result.field217_);
               break;
             }
             case 1744: {
-              Field218 = input.ReadInt32();
+              result.hasField218 |= input.ReadInt32(ref result.field218_);
               break;
             }
             case 1760: {
-              Field220 = input.ReadInt32();
+              result.hasField220 |= input.ReadInt32(ref result.field220_);
               break;
             }
             case 1768: {
-              Field221 = input.ReadInt32();
+              result.hasField221 |= input.ReadInt32(ref result.field221_);
               break;
             }
             case 1781: {
-              Field222 = input.ReadFloat();
+              result.hasField222 |= input.ReadFloat(ref result.field222_);
               break;
             }
           }
@@ -5867,51 +5865,51 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 13: {
-              Field1 = input.ReadFloat();
+              result.hasField1 |= input.ReadFloat(ref result.field1_);
               break;
             }
             case 21: {
-              Field2 = input.ReadFloat();
+              result.hasField2 |= input.ReadFloat(ref result.field2_);
               break;
             }
             case 29: {
-              Field3 = input.ReadFloat();
+              result.hasField3 |= input.ReadFloat(ref result.field3_);
               break;
             }
             case 32: {
-              Field4 = input.ReadBool();
+              result.hasField4 |= input.ReadBool(ref result.field4_);
               break;
             }
             case 40: {
-              Field5 = input.ReadBool();
+              result.hasField5 |= input.ReadBool(ref result.field5_);
               break;
             }
             case 48: {
-              Field6 = input.ReadBool();
+              result.hasField6 |= input.ReadBool(ref result.field6_);
               break;
             }
             case 56: {
-              Field7 = input.ReadBool();
+              result.hasField7 |= input.ReadBool(ref result.field7_);
               break;
             }
             case 69: {
-              Field8 = input.ReadFloat();
+              result.hasField8 |= input.ReadFloat(ref result.field8_);
               break;
             }
             case 72: {
-              Field9 = input.ReadBool();
+              result.hasField9 |= input.ReadBool(ref result.field9_);
               break;
             }
             case 85: {
-              Field10 = input.ReadFloat();
+              result.hasField10 |= input.ReadFloat(ref result.field10_);
               break;
             }
             case 88: {
-              Field11 = input.ReadInt64();
+              result.hasField11 |= input.ReadInt64(ref result.field11_);
               break;
             }
           }

+ 2 - 2
src/ProtocolBuffers.Test/TestProtos/UnitTestImportLiteProtoFile.cs

@@ -218,11 +218,11 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (pb::WireFormat.IsEndGroupTag(tag)) {
                 return this;
               }
-              ParseUnknownField(input, extensionRegistry, tag);
+              ParseUnknownField(input, extensionRegistry, tag, field_name);
               break;
             }
             case 8: {
-              D = input.ReadInt32();
+              result.hasD |= input.ReadInt32(ref result.d_);
               break;
             }
           }

+ 2 - 2
src/ProtocolBuffers.Test/TestProtos/UnitTestImportProtoFile.cs

@@ -249,11 +249,11 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 8: {
-              D = input.ReadInt32();
+              result.hasD |= input.ReadInt32(ref result.d_);
               break;
             }
           }

+ 11 - 13
src/ProtocolBuffers.Test/TestProtos/UnitTestMessageSetProtoFile.cs

@@ -267,7 +267,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
           }
@@ -469,7 +469,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
@@ -718,11 +718,11 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 120: {
-              I = input.ReadInt32();
+              result.hasI |= input.ReadInt32(ref result.i_);
               break;
             }
           }
@@ -944,11 +944,11 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 202: {
-              Str = input.ReadString();
+              result.hasStr |= input.ReadString(ref result.str_);
               break;
             }
           }
@@ -1220,15 +1220,15 @@ namespace Google.ProtocolBuffers.TestProtos {
                   if (unknownFields == null) {
                     unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                   }
-                  ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+                  ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
                   break;
                 }
                 case 16: {
-                  TypeId = input.ReadInt32();
+                  result.hasTypeId |= input.ReadInt32(ref result.typeId_);
                   break;
                 }
                 case 26: {
-                  Message = input.ReadBytes();
+                  result.hasMessage |= input.ReadBytes(ref result.message_);
                   break;
                 }
               }
@@ -1448,13 +1448,11 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 11: {
-              global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item.CreateBuilder();
-              input.ReadGroup(1, subBuilder, extensionRegistry);
-              AddItem(subBuilder.BuildPartial());
+              input.ReadGroupArray(tag, field_name, result.item_, global::Google.ProtocolBuffers.TestProtos.RawMessageSet.Types.Item.DefaultInstance, extensionRegistry);
               break;
             }
           }

+ 2 - 2
src/ProtocolBuffers.Test/TestProtos/UnitTestNoGenericServicesProtoFile.cs

@@ -264,11 +264,11 @@ namespace Google.ProtocolBuffers.TestProtos.NoGenericService {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 8: {
-              A = input.ReadInt32();
+              result.hasA |= input.ReadInt32(ref result.a_);
               break;
             }
           }

File diff suppressed because it is too large
+ 200 - 210
src/ProtocolBuffers.Test/TestProtos/UnitTestProtoFile.cs


+ 9 - 11
src/ProtocolBuffers.Test/TestProtos/UnitTestRpcInterop.cs

@@ -269,11 +269,11 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              AddCriteria(input.ReadString());
+              input.ReadPrimitiveArray(pbd::FieldType.String, tag, field_name, result.criteria_);
               break;
             }
           }
@@ -553,15 +553,15 @@ namespace Google.ProtocolBuffers.TestProtos {
                   if (unknownFields == null) {
                     unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                   }
-                  ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+                  ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
                   break;
                 }
                 case 10: {
-                  Url = input.ReadString();
+                  result.hasUrl |= input.ReadString(ref result.url_);
                   break;
                 }
                 case 18: {
-                  Name = input.ReadString();
+                  result.hasName |= input.ReadString(ref result.name_);
                   break;
                 }
               }
@@ -785,13 +785,11 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddResults(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.results_, global::Google.ProtocolBuffers.TestProtos.SearchResponse.Types.ResultItem.DefaultInstance, extensionRegistry);
               break;
             }
           }
@@ -1060,11 +1058,11 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              AddCriteria(input.ReadString());
+              input.ReadPrimitiveArray(pbd::FieldType.String, tag, field_name, result.criteria_);
               break;
             }
             case 18: {

+ 26 - 26
src/ProtocolBuffers.Test/TestProtos/UnitTestXmlSerializerTestProtoFile.cs

@@ -337,23 +337,24 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 24: {
-              int rawValue = input.ReadEnum();
-              if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.TestProtos.EnumOptions), rawValue)) {
+              scg::ICollection<object> unknownItems;
+              input.ReadEnumArray<global::Google.ProtocolBuffers.TestProtos.EnumOptions>(tag, field_name, result.options_, out unknownItems);
+              if (unknownItems != null) {
                 if (unknownFields == null) {
                   unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                 }
-                unknownFields.MergeVarintField(3, (ulong) rawValue);
-              } else {
-                AddOptions((global::Google.ProtocolBuffers.TestProtos.EnumOptions) rawValue);
+                foreach (object rawValue in unknownItems)
+                  if (rawValue is int)
+                    unknownFields.MergeVarintField(3, (ulong)(int)rawValue);
               }
               break;
             }
             case 34: {
-              Binary = input.ReadBytes();
+              result.hasBinary |= input.ReadBytes(ref result.binary_);
               break;
             }
           }
@@ -581,7 +582,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
           }
@@ -842,23 +843,24 @@ namespace Google.ProtocolBuffers.TestProtos {
                   if (unknownFields == null) {
                     unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                   }
-                  ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+                  ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
                   break;
                 }
                 case 24: {
-                  int rawValue = input.ReadEnum();
-                  if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.TestProtos.EnumOptions), rawValue)) {
+                  scg::ICollection<object> unknownItems;
+                  input.ReadEnumArray<global::Google.ProtocolBuffers.TestProtos.EnumOptions>(tag, field_name, result.options_, out unknownItems);
+                  if (unknownItems != null) {
                     if (unknownFields == null) {
                       unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                     }
-                    unknownFields.MergeVarintField(3, (ulong) rawValue);
-                  } else {
-                    AddOptions((global::Google.ProtocolBuffers.TestProtos.EnumOptions) rawValue);
+                    foreach (object rawValue in unknownItems)
+                      if (rawValue is int)
+                        unknownFields.MergeVarintField(3, (ulong)(int)rawValue);
                   }
                   break;
                 }
                 case 34: {
-                  Binary = input.ReadBytes();
+                  result.hasBinary |= input.ReadBytes(ref result.binary_);
                   break;
                 }
               }
@@ -1221,7 +1223,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
@@ -1234,29 +1236,27 @@ namespace Google.ProtocolBuffers.TestProtos {
               break;
             }
             case 16: {
-              AddNumbers(input.ReadInt32());
+              input.ReadPrimitiveArray(pbd::FieldType.Int32, tag, field_name, result.numbers_);
               break;
             }
             case 26: {
-              Text = input.ReadString();
+              result.hasText |= input.ReadString(ref result.text_);
               break;
             }
             case 40: {
-              Valid = input.ReadBool();
+              result.hasValid |= input.ReadBool(ref result.valid_);
               break;
             }
             case 48: {
-              Number = input.ReadInt64();
+              result.hasNumber |= input.ReadInt64(ref result.number_);
               break;
             }
             case 3211: {
-              global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children.CreateBuilder();
-              input.ReadGroup(401, subBuilder, extensionRegistry);
-              AddChildren(subBuilder.BuildPartial());
+              input.ReadGroupArray(tag, field_name, result.children_, global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children.DefaultInstance, extensionRegistry);
               break;
             }
             case 5602: {
-              AddTextlines(input.ReadString());
+              input.ReadPrimitiveArray(pbd::FieldType.String, tag, field_name, result.textlines_);
               break;
             }
           }
@@ -1642,11 +1642,11 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 8: {
-              Number = input.ReadInt32();
+              result.hasNumber |= input.ReadInt32(ref result.number_);
               break;
             }
           }

+ 341 - 57
src/ProtocolBuffers/CodedInputStream.cs

@@ -201,88 +201,100 @@ namespace Google.ProtocolBuffers
         /// <summary>
         /// Read a double field from the stream.
         /// </summary>
-        public double ReadDouble()
+        public bool ReadDouble(ref double value)
         {
 #if SILVERLIGHT2 || COMPACT_FRAMEWORK_35
-            byte[] bytes = ReadRawBytes(8);
-            return BitConverter.ToDouble(bytes, 0);
+            byte[] rawBytes = ReadRawBytes(8);
+            if (!BitConverter.IsLittleEndian) 
+                Array.Reverse(rawBytes);
+            value = BitConverter.ToDouble(rawBytes, 0);
+            return true;
 #else
-      return BitConverter.Int64BitsToDouble((long) ReadRawLittleEndian64());
+            value = BitConverter.Int64BitsToDouble((long) ReadRawLittleEndian64());
+            return true;
 #endif
         }
 
         /// <summary>
         /// Read a float field from the stream.
         /// </summary>
-        public float ReadFloat()
+        public bool ReadFloat(ref float value)
         {
-            // TODO(jonskeet): Test this on different endiannesses
-            uint raw = ReadRawLittleEndian32();
-            byte[] rawBytes = BitConverter.GetBytes(raw);
-            return BitConverter.ToSingle(rawBytes, 0);
+            byte[] rawBytes = ReadRawBytes(4);
+            if (!BitConverter.IsLittleEndian)
+                Array.Reverse(rawBytes);
+            value = BitConverter.ToSingle(rawBytes, 0);
+            return true;
         }
 
         /// <summary>
         /// Read a uint64 field from the stream.
         /// </summary>
         [CLSCompliant(false)]
-        public ulong ReadUInt64()
+        public bool ReadUInt64(ref ulong value)
         {
-            return ReadRawVarint64();
+            value = ReadRawVarint64();
+            return true;
         }
 
         /// <summary>
         /// Read an int64 field from the stream.
         /// </summary>
-        public long ReadInt64()
+        public bool ReadInt64(ref long value)
         {
-            return (long) ReadRawVarint64();
+            value = (long) ReadRawVarint64();
+            return true;
         }
 
         /// <summary>
         /// Read an int32 field from the stream.
         /// </summary>
-        public int ReadInt32()
+        public bool ReadInt32(ref int value)
         {
-            return (int) ReadRawVarint32();
+            value = (int)ReadRawVarint32();
+            return true;
         }
 
         /// <summary>
         /// Read a fixed64 field from the stream.
         /// </summary>
         [CLSCompliant(false)]
-        public ulong ReadFixed64()
+        public bool ReadFixed64(ref ulong value)
         {
-            return ReadRawLittleEndian64();
+            value = ReadRawLittleEndian64();
+            return true;
         }
 
         /// <summary>
         /// Read a fixed32 field from the stream.
         /// </summary>
         [CLSCompliant(false)]
-        public uint ReadFixed32()
+        public bool ReadFixed32(ref uint value)
         {
-            return ReadRawLittleEndian32();
+            value = ReadRawLittleEndian32();
+            return true;
         }
 
         /// <summary>
         /// Read a bool field from the stream.
         /// </summary>
-        public bool ReadBool()
+        public bool ReadBool(ref bool value)
         {
-            return ReadRawVarint32() != 0;
+            value = ReadRawVarint32() != 0;
+            return true;
         }
 
         /// <summary>
         /// Reads a string field from the stream.
         /// </summary>
-        public String ReadString()
+        public bool ReadString(ref string value)
         {
             int size = (int) ReadRawVarint32();
             // No need to read any data for an empty string.
             if (size == 0)
             {
-                return "";
+                value = "";
+                return true;
             }
             if (size <= bufferSize - bufferPos)
             {
@@ -290,10 +302,12 @@ namespace Google.ProtocolBuffers
                 //   just copy directly from it.
                 String result = Encoding.UTF8.GetString(buffer, bufferPos, size);
                 bufferPos += size;
-                return result;
+                value = result;
+                return true;
             }
             // Slow path: Build a byte array first then copy it.
-            return Encoding.UTF8.GetString(ReadRawBytes(size), 0, size);
+            value = Encoding.UTF8.GetString(ReadRawBytes(size), 0, size);
+            return true;
         }
 
         /// <summary>
@@ -350,7 +364,7 @@ namespace Google.ProtocolBuffers
         /// <summary>
         /// Reads a bytes field value from the stream.
         /// </summary>   
-        public ByteString ReadBytes()
+        public bool ReadBytes(ref ByteString value)
         {
             int size = (int) ReadRawVarint32();
             if (size < bufferSize - bufferPos && size > 0)
@@ -359,12 +373,14 @@ namespace Google.ProtocolBuffers
                 //   just copy directly from it.
                 ByteString result = ByteString.CopyFrom(buffer, bufferPos, size);
                 bufferPos += size;
-                return result;
+                value = result;
+                return true;
             }
             else
             {
                 // Slow path:  Build a byte array first then copy it.
-                return ByteString.AttachBytes(ReadRawBytes(size));
+                value = ByteString.AttachBytes(ReadRawBytes(size));
+                return true;
             }
         }
 
@@ -372,90 +388,358 @@ namespace Google.ProtocolBuffers
         /// Reads a uint32 field value from the stream.
         /// </summary>   
         [CLSCompliant(false)]
-        public uint ReadUInt32()
+        public bool ReadUInt32(ref uint value)
         {
-            return ReadRawVarint32();
+            value = ReadRawVarint32();
+            return true;
         }
 
         /// <summary>
         /// Reads an enum field value from the stream. The caller is responsible
         /// for converting the numeric value to an actual enum.
         /// </summary>   
-        public int ReadEnum()
+        public bool ReadEnum(ref IEnumLite value, out object unknown, IEnumLiteMap mapping)
+        {
+            int rawValue = (int)ReadRawVarint32();
+            
+            value = mapping.FindValueByNumber(rawValue);
+            if (value != null)
+            {
+                unknown = null;
+                return true;
+            }
+            unknown = rawValue;
+            return false;
+        }
+
+        /// <summary>
+        /// 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 the unkown output
+        /// value is set and this method returns false.
+        /// </summary>   
+        [CLSCompliant(false)]
+        public bool ReadEnum<T>(ref T value, out object unknown)
+            where T : struct, IComparable, IFormattable, IConvertible
         {
-            return (int) ReadRawVarint32();
+            int number = (int)ReadRawVarint32();
+            if (Enum.IsDefined(typeof(T), number))
+            {
+                unknown = null;
+                value = (T)(object)number;
+                return true;
+            }
+            unknown = number;
+            return false;
         }
 
         /// <summary>
         /// Reads an sfixed32 field value from the stream.
         /// </summary>   
-        public int ReadSFixed32()
+        public bool ReadSFixed32(ref int value)
         {
-            return (int) ReadRawLittleEndian32();
+            value = (int)ReadRawLittleEndian32();
+            return true;
         }
 
         /// <summary>
         /// Reads an sfixed64 field value from the stream.
         /// </summary>   
-        public long ReadSFixed64()
+        public bool ReadSFixed64(ref long value)
         {
-            return (long) ReadRawLittleEndian64();
+            value = (long)ReadRawLittleEndian64();
+            return true;
         }
 
         /// <summary>
         /// Reads an sint32 field value from the stream.
         /// </summary>   
-        public int ReadSInt32()
+        public bool ReadSInt32(ref int value)
         {
-            return DecodeZigZag32(ReadRawVarint32());
+            value = DecodeZigZag32(ReadRawVarint32());
+            return true;
         }
 
         /// <summary>
         /// Reads an sint64 field value from the stream.
         /// </summary>   
-        public long ReadSInt64()
+        public bool ReadSInt64(ref long value)
+        {
+            value = DecodeZigZag64(ReadRawVarint64());
+            return true;
+        }
+
+        [CLSCompliant(false)]
+        public void ReadPrimitiveArray<T>(FieldType fieldType, uint fieldTag, string fieldName, ICollection<T> list)
+        {
+            WireFormat.WireType normal = WireFormat.GetWireType(fieldType);
+            WireFormat.WireType wformat = WireFormat.GetTagWireType(fieldTag);
+            
+            // 2.3 allows packed form even if the field is not declared packed.
+            if(normal != wformat && wformat == WireFormat.WireType.LengthDelimited)
+            {
+                int length = (int)(ReadRawVarint32() & int.MaxValue);
+                int limit = PushLimit(length);
+                while (!ReachedLimit)
+                {
+                    Object value = null;
+                    if(ReadPrimitiveField(fieldType, ref value))
+                        list.Add((T)value);
+                }
+                PopLimit(limit);
+            }
+            else
+            {
+                Object value = null;
+                if (ReadPrimitiveField(fieldType, ref value))
+                    list.Add((T)value);
+            }
+        }
+
+        [CLSCompliant(false)]
+        public void ReadEnumArray(uint fieldTag, string fieldName, ICollection<IEnumLite> list, out ICollection<object> unknown, IEnumLiteMap mapping)
+        {
+            unknown = null;
+            object unkval;
+            IEnumLite value = null;
+            WireFormat.WireType wformat = WireFormat.GetTagWireType(fieldTag);
+
+            // 2.3 allows packed form even if the field is not declared packed.
+            if (wformat == WireFormat.WireType.LengthDelimited)
+            {
+                int length = (int)(ReadRawVarint32() & int.MaxValue);
+                int limit = PushLimit(length);
+                while (!ReachedLimit)
+                {
+                    if (ReadEnum(ref value, out unkval, mapping))
+                        list.Add(value);
+                    else
+                    {
+                        if (unknown == null)
+                            unknown = new List<object>();
+                        unknown.Add(unkval);
+                    }
+                }
+                PopLimit(limit);
+            }
+            else
+            {
+                if (ReadEnum(ref value, out unkval, mapping))
+                    list.Add(value);
+                else
+                    unknown = new object[] { unkval };
+            }
+        }
+
+        [CLSCompliant(false)]
+        public void ReadEnumArray<T>(uint fieldTag, string fieldName, ICollection<T> list, out ICollection<object> unknown)
+            where T : struct, IComparable, IFormattable, IConvertible
+        {
+            unknown = null;
+            object unkval;
+            T value = default(T);
+            WireFormat.WireType wformat = WireFormat.GetTagWireType(fieldTag);
+
+            // 2.3 allows packed form even if the field is not declared packed.
+            if (wformat == WireFormat.WireType.LengthDelimited)
+            {
+                int length = (int)(ReadRawVarint32() & int.MaxValue);
+                int limit = PushLimit(length);
+                while (!ReachedLimit)
+                {
+                    if (ReadEnum<T>(ref value, out unkval))
+                        list.Add(value);
+                    else
+                    {
+                        if (unknown == null)
+                            unknown = new List<object>();
+                        unknown.Add(unkval);
+                    }
+                }
+                PopLimit(limit);
+            }
+            else
+            {
+                if (ReadEnum(ref value, out unkval))
+                    list.Add(value);
+                else
+                    unknown = new object[] { unkval };
+            }
+        }
+
+        [CLSCompliant(false)]
+        public void ReadMessageArray<T>(uint fieldTag, string fieldName, ICollection<T> list, T messageType, ExtensionRegistry registry) where T : IMessageLite
+        {
+            IBuilderLite builder = messageType.WeakCreateBuilderForType();
+            ReadMessage(builder, registry);
+            list.Add((T)builder.WeakBuildPartial());
+        }
+
+        [CLSCompliant(false)]
+        public void ReadGroupArray<T>(uint fieldTag, string fieldName, ICollection<T> list, T messageType, ExtensionRegistry registry) where T : IMessageLite
         {
-            return DecodeZigZag64(ReadRawVarint64());
+            IBuilderLite builder = messageType.WeakCreateBuilderForType();
+            ReadGroup(WireFormat.GetTagFieldNumber(fieldTag), builder, registry);
+            list.Add((T)builder.WeakBuildPartial());
         }
 
         /// <summary>
         /// Reads a field of any primitive type. Enums, groups and embedded
         /// messages are not handled by this method.
         /// </summary>
-        public object ReadPrimitiveField(FieldType fieldType)
+        public bool ReadPrimitiveField(FieldType fieldType, ref object value)
         {
             switch (fieldType)
             {
                 case FieldType.Double:
-                    return ReadDouble();
+                    {
+                        double tmp = 0;
+                        if (ReadDouble(ref tmp))
+                        {
+                            value = tmp;
+                            return true;
+                        }
+                        return false;
+                    }
                 case FieldType.Float:
-                    return ReadFloat();
+                    {
+                        float tmp = 0;
+                        if (ReadFloat(ref tmp))
+                        {
+                            value = tmp;
+                            return true;
+                        }
+                        return false;
+                    }
                 case FieldType.Int64:
-                    return ReadInt64();
+                    {
+                        long tmp = 0;
+                        if (ReadInt64(ref tmp))
+                        {
+                            value = tmp;
+                            return true;
+                        }
+                        return false;
+                    }
                 case FieldType.UInt64:
-                    return ReadUInt64();
+                    {
+                        ulong tmp = 0;
+                        if (ReadUInt64(ref tmp))
+                        {
+                            value = tmp;
+                            return true;
+                        }
+                        return false;
+                    }
                 case FieldType.Int32:
-                    return ReadInt32();
+                    {
+                        int tmp = 0;
+                        if (ReadInt32(ref tmp))
+                        {
+                            value = tmp;
+                            return true;
+                        }
+                        return false;
+                    }
                 case FieldType.Fixed64:
-                    return ReadFixed64();
+                    {
+                        ulong tmp = 0;
+                        if (ReadFixed64(ref tmp))
+                        {
+                            value = tmp;
+                            return true;
+                        }
+                        return false;
+                    }
                 case FieldType.Fixed32:
-                    return ReadFixed32();
+                    {
+                        uint tmp = 0;
+                        if (ReadFixed32(ref tmp))
+                        {
+                            value = tmp;
+                            return true;
+                        }
+                        return false;
+                    }
                 case FieldType.Bool:
-                    return ReadBool();
+                    {
+                        bool tmp = false;
+                        if (ReadBool(ref tmp))
+                        {
+                            value = tmp;
+                            return true;
+                        }
+                        return false;
+                    }
                 case FieldType.String:
-                    return ReadString();
+                    {
+                        string tmp = null;
+                        if (ReadString(ref tmp))
+                        {
+                            value = tmp;
+                            return true;
+                        }
+                        return false;
+                    }
                 case FieldType.Bytes:
-                    return ReadBytes();
+                    {
+                        ByteString tmp = null;
+                        if (ReadBytes(ref tmp))
+                        {
+                            value = tmp;
+                            return true;
+                        }
+                        return false;
+                    }
                 case FieldType.UInt32:
-                    return ReadUInt32();
+                    {
+                        uint tmp = 0;
+                        if (ReadUInt32(ref tmp))
+                        {
+                            value = tmp;
+                            return true;
+                        }
+                        return false;
+                    }
                 case FieldType.SFixed32:
-                    return ReadSFixed32();
+                    {
+                        int tmp = 0;
+                        if (ReadSFixed32(ref tmp))
+                        {
+                            value = tmp;
+                            return true;
+                        }
+                        return false;
+                    }
                 case FieldType.SFixed64:
-                    return ReadSFixed64();
+                    {
+                        long tmp = 0;
+                        if (ReadSFixed64(ref tmp))
+                        {
+                            value = tmp;
+                            return true;
+                        }
+                        return false;
+                    }
                 case FieldType.SInt32:
-                    return ReadSInt32();
+                    {
+                        int tmp = 0;
+                        if (ReadSInt32(ref tmp))
+                        {
+                            value = tmp;
+                            return true;
+                        }
+                        return false;
+                    }
                 case FieldType.SInt64:
-                    return ReadSInt64();
+                    {
+                        long tmp = 0;
+                        if (ReadSInt64(ref tmp))
+                        {
+                            value = tmp;
+                            return true;
+                        }
+                        return false;
+                    }
                 case FieldType.Group:
                     throw new ArgumentException("ReadPrimitiveField() cannot handle nested groups.");
                 case FieldType.Message:
@@ -1047,7 +1331,7 @@ namespace Google.ProtocolBuffers
             switch (WireFormat.GetTagWireType(tag))
             {
                 case WireFormat.WireType.Varint:
-                    ReadInt32();
+                    ReadRawVarint64();
                     return true;
                 case WireFormat.WireType.Fixed64:
                     ReadRawLittleEndian64();

+ 24 - 24
src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs

@@ -531,66 +531,66 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              Namespace = input.ReadString();
+              result.hasNamespace |= input.ReadString(ref result.namespace_);
               break;
             }
             case 18: {
-              UmbrellaClassname = input.ReadString();
+              result.hasUmbrellaClassname |= input.ReadString(ref result.umbrellaClassname_);
               break;
             }
             case 24: {
-              PublicClasses = input.ReadBool();
+              result.hasPublicClasses |= input.ReadBool(ref result.publicClasses_);
               break;
             }
             case 32: {
-              MultipleFiles = input.ReadBool();
+              result.hasMultipleFiles |= input.ReadBool(ref result.multipleFiles_);
               break;
             }
             case 40: {
-              NestClasses = input.ReadBool();
+              result.hasNestClasses |= input.ReadBool(ref result.nestClasses_);
               break;
             }
             case 48: {
-              CodeContracts = input.ReadBool();
+              result.hasCodeContracts |= input.ReadBool(ref result.codeContracts_);
               break;
             }
             case 56: {
-              ExpandNamespaceDirectories = input.ReadBool();
+              result.hasExpandNamespaceDirectories |= input.ReadBool(ref result.expandNamespaceDirectories_);
               break;
             }
             case 64: {
-              ClsCompliance = input.ReadBool();
+              result.hasClsCompliance |= input.ReadBool(ref result.clsCompliance_);
               break;
             }
             case 1770: {
-              FileExtension = input.ReadString();
+              result.hasFileExtension |= input.ReadString(ref result.fileExtension_);
               break;
             }
             case 1778: {
-              UmbrellaNamespace = input.ReadString();
+              result.hasUmbrellaNamespace |= input.ReadString(ref result.umbrellaNamespace_);
               break;
             }
             case 1786: {
-              OutputDirectory = input.ReadString();
+              result.hasOutputDirectory |= input.ReadString(ref result.outputDirectory_);
               break;
             }
             case 1792: {
-              IgnoreGoogleProtobuf = input.ReadBool();
+              result.hasIgnoreGoogleProtobuf |= input.ReadBool(ref result.ignoreGoogleProtobuf_);
               break;
             }
             case 1800: {
-              int rawValue = input.ReadEnum();
-              if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.DescriptorProtos.CSharpServiceType), rawValue)) {
+              object unknown;
+              if(input.ReadEnum(ref result.serviceGeneratorType_, out unknown)) {
+                result.hasServiceGeneratorType = true;
+              } else if(unknown is int) {
                 if (unknownFields == null) {
                   unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                 }
-                unknownFields.MergeVarintField(225, (ulong) rawValue);
-              } else {
-                ServiceGeneratorType = (global::Google.ProtocolBuffers.DescriptorProtos.CSharpServiceType) rawValue;
+                unknownFields.MergeVarintField(225, (ulong)(int)unknown);
               }
               break;
             }
@@ -1032,11 +1032,11 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              PropertyName = input.ReadString();
+              result.hasPropertyName |= input.ReadString(ref result.propertyName_);
               break;
             }
           }
@@ -1257,11 +1257,11 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              InterfaceId = input.ReadString();
+              result.hasInterfaceId |= input.ReadString(ref result.interfaceId_);
               break;
             }
           }
@@ -1482,11 +1482,11 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 8: {
-              DispatchId = input.ReadInt32();
+              result.hasDispatchId |= input.ReadInt32(ref result.dispatchId_);
               break;
             }
           }

+ 94 - 134
src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs

@@ -417,13 +417,11 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddFile(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.file_, global::Google.ProtocolBuffers.DescriptorProtos.FileDescriptorProto.DefaultInstance, extensionRegistry);
               break;
             }
           }
@@ -831,43 +829,35 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              Name = input.ReadString();
+              result.hasName |= input.ReadString(ref result.name_);
               break;
             }
             case 18: {
-              Package = input.ReadString();
+              result.hasPackage |= input.ReadString(ref result.package_);
               break;
             }
             case 26: {
-              AddDependency(input.ReadString());
+              input.ReadPrimitiveArray(pbd::FieldType.String, tag, field_name, result.dependency_);
               break;
             }
             case 34: {
-              global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddMessageType(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.messageType_, global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.DefaultInstance, extensionRegistry);
               break;
             }
             case 42: {
-              global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddEnumType(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.enumType_, global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto.DefaultInstance, extensionRegistry);
               break;
             }
             case 50: {
-              global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddService(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.service_, global::Google.ProtocolBuffers.DescriptorProtos.ServiceDescriptorProto.DefaultInstance, extensionRegistry);
               break;
             }
             case 58: {
-              global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddExtension(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.extension_, global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.DefaultInstance, extensionRegistry);
               break;
             }
             case 66: {
@@ -1381,15 +1371,15 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
                   if (unknownFields == null) {
                     unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                   }
-                  ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+                  ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
                   break;
                 }
                 case 8: {
-                  Start = input.ReadInt32();
+                  result.hasStart |= input.ReadInt32(ref result.start_);
                   break;
                 }
                 case 16: {
-                  End = input.ReadInt32();
+                  result.hasEnd |= input.ReadInt32(ref result.end_);
                   break;
                 }
               }
@@ -1749,41 +1739,31 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              Name = input.ReadString();
+              result.hasName |= input.ReadString(ref result.name_);
               break;
             }
             case 18: {
-              global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddField(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.field_, global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.DefaultInstance, extensionRegistry);
               break;
             }
             case 26: {
-              global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddNestedType(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.nestedType_, global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.DefaultInstance, extensionRegistry);
               break;
             }
             case 34: {
-              global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddEnumType(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.enumType_, global::Google.ProtocolBuffers.DescriptorProtos.EnumDescriptorProto.DefaultInstance, extensionRegistry);
               break;
             }
             case 42: {
-              global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddExtensionRange(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.extensionRange_, global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ExtensionRange.DefaultInstance, extensionRegistry);
               break;
             }
             case 50: {
-              global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddExtension(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.extension_, global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.DefaultInstance, extensionRegistry);
               break;
             }
             case 58: {
@@ -2414,51 +2394,51 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              Name = input.ReadString();
+              result.hasName |= input.ReadString(ref result.name_);
               break;
             }
             case 18: {
-              Extendee = input.ReadString();
+              result.hasExtendee |= input.ReadString(ref result.extendee_);
               break;
             }
             case 24: {
-              Number = input.ReadInt32();
+              result.hasNumber |= input.ReadInt32(ref result.number_);
               break;
             }
             case 32: {
-              int rawValue = input.ReadEnum();
-              if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Label), rawValue)) {
+              object unknown;
+              if(input.ReadEnum(ref result.label_, out unknown)) {
+                result.hasLabel = true;
+              } else if(unknown is int) {
                 if (unknownFields == null) {
                   unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                 }
-                unknownFields.MergeVarintField(4, (ulong) rawValue);
-              } else {
-                Label = (global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Label) rawValue;
+                unknownFields.MergeVarintField(4, (ulong)(int)unknown);
               }
               break;
             }
             case 40: {
-              int rawValue = input.ReadEnum();
-              if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Type), rawValue)) {
+              object unknown;
+              if(input.ReadEnum(ref result.type_, out unknown)) {
+                result.hasType = true;
+              } else if(unknown is int) {
                 if (unknownFields == null) {
                   unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                 }
-                unknownFields.MergeVarintField(5, (ulong) rawValue);
-              } else {
-                Type = (global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Type) rawValue;
+                unknownFields.MergeVarintField(5, (ulong)(int)unknown);
               }
               break;
             }
             case 50: {
-              TypeName = input.ReadString();
+              result.hasTypeName |= input.ReadString(ref result.typeName_);
               break;
             }
             case 58: {
-              DefaultValue = input.ReadString();
+              result.hasDefaultValue |= input.ReadString(ref result.defaultValue_);
               break;
             }
             case 66: {
@@ -2882,17 +2862,15 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              Name = input.ReadString();
+              result.hasName |= input.ReadString(ref result.name_);
               break;
             }
             case 18: {
-              global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddValue(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.value_, global::Google.ProtocolBuffers.DescriptorProtos.EnumValueDescriptorProto.DefaultInstance, extensionRegistry);
               break;
             }
             case 26: {
@@ -3237,15 +3215,15 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              Name = input.ReadString();
+              result.hasName |= input.ReadString(ref result.name_);
               break;
             }
             case 16: {
-              Number = input.ReadInt32();
+              result.hasNumber |= input.ReadInt32(ref result.number_);
               break;
             }
             case 26: {
@@ -3576,17 +3554,15 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              Name = input.ReadString();
+              result.hasName |= input.ReadString(ref result.name_);
               break;
             }
             case 18: {
-              global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddMethod(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.method_, global::Google.ProtocolBuffers.DescriptorProtos.MethodDescriptorProto.DefaultInstance, extensionRegistry);
               break;
             }
             case 26: {
@@ -3950,19 +3926,19 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              Name = input.ReadString();
+              result.hasName |= input.ReadString(ref result.name_);
               break;
             }
             case 18: {
-              InputType = input.ReadString();
+              result.hasInputType |= input.ReadString(ref result.inputType_);
               break;
             }
             case 26: {
-              OutputType = input.ReadString();
+              result.hasOutputType |= input.ReadString(ref result.outputType_);
               break;
             }
             case 34: {
@@ -4426,49 +4402,47 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              JavaPackage = input.ReadString();
+              result.hasJavaPackage |= input.ReadString(ref result.javaPackage_);
               break;
             }
             case 66: {
-              JavaOuterClassname = input.ReadString();
+              result.hasJavaOuterClassname |= input.ReadString(ref result.javaOuterClassname_);
               break;
             }
             case 72: {
-              int rawValue = input.ReadEnum();
-              if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.Types.OptimizeMode), rawValue)) {
+              object unknown;
+              if(input.ReadEnum(ref result.optimizeFor_, out unknown)) {
+                result.hasOptimizeFor = true;
+              } else if(unknown is int) {
                 if (unknownFields == null) {
                   unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                 }
-                unknownFields.MergeVarintField(9, (ulong) rawValue);
-              } else {
-                OptimizeFor = (global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.Types.OptimizeMode) rawValue;
+                unknownFields.MergeVarintField(9, (ulong)(int)unknown);
               }
               break;
             }
             case 80: {
-              JavaMultipleFiles = input.ReadBool();
+              result.hasJavaMultipleFiles |= input.ReadBool(ref result.javaMultipleFiles_);
               break;
             }
             case 128: {
-              CcGenericServices = input.ReadBool();
+              result.hasCcGenericServices |= input.ReadBool(ref result.ccGenericServices_);
               break;
             }
             case 136: {
-              JavaGenericServices = input.ReadBool();
+              result.hasJavaGenericServices |= input.ReadBool(ref result.javaGenericServices_);
               break;
             }
             case 144: {
-              PyGenericServices = input.ReadBool();
+              result.hasPyGenericServices |= input.ReadBool(ref result.pyGenericServices_);
               break;
             }
             case 7994: {
-              global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddUninterpretedOption(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.uninterpretedOption_, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.DefaultInstance, extensionRegistry);
               break;
             }
           }
@@ -4885,21 +4859,19 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 8: {
-              MessageSetWireFormat = input.ReadBool();
+              result.hasMessageSetWireFormat |= input.ReadBool(ref result.messageSetWireFormat_);
               break;
             }
             case 16: {
-              NoStandardDescriptorAccessor = input.ReadBool();
+              result.hasNoStandardDescriptorAccessor |= input.ReadBool(ref result.noStandardDescriptorAccessor_);
               break;
             }
             case 7994: {
-              global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddUninterpretedOption(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.uninterpretedOption_, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.DefaultInstance, extensionRegistry);
               break;
             }
           }
@@ -5278,37 +5250,35 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 8: {
-              int rawValue = input.ReadEnum();
-              if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.CType), rawValue)) {
+              object unknown;
+              if(input.ReadEnum(ref result.ctype_, out unknown)) {
+                result.hasCtype = true;
+              } else if(unknown is int) {
                 if (unknownFields == null) {
                   unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                 }
-                unknownFields.MergeVarintField(1, (ulong) rawValue);
-              } else {
-                Ctype = (global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.CType) rawValue;
+                unknownFields.MergeVarintField(1, (ulong)(int)unknown);
               }
               break;
             }
             case 16: {
-              Packed = input.ReadBool();
+              result.hasPacked |= input.ReadBool(ref result.packed_);
               break;
             }
             case 24: {
-              Deprecated = input.ReadBool();
+              result.hasDeprecated |= input.ReadBool(ref result.deprecated_);
               break;
             }
             case 74: {
-              ExperimentalMapKey = input.ReadString();
+              result.hasExperimentalMapKey |= input.ReadString(ref result.experimentalMapKey_);
               break;
             }
             case 7994: {
-              global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddUninterpretedOption(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.uninterpretedOption_, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.DefaultInstance, extensionRegistry);
               break;
             }
           }
@@ -5632,13 +5602,11 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 7994: {
-              global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddUninterpretedOption(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.uninterpretedOption_, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.DefaultInstance, extensionRegistry);
               break;
             }
           }
@@ -5889,13 +5857,11 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 7994: {
-              global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddUninterpretedOption(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.uninterpretedOption_, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.DefaultInstance, extensionRegistry);
               break;
             }
           }
@@ -6146,13 +6112,11 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 7994: {
-              global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddUninterpretedOption(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.uninterpretedOption_, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.DefaultInstance, extensionRegistry);
               break;
             }
           }
@@ -6403,13 +6367,11 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 7994: {
-              global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddUninterpretedOption(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.uninterpretedOption_, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.DefaultInstance, extensionRegistry);
               break;
             }
           }
@@ -6700,15 +6662,15 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
                   if (unknownFields == null) {
                     unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                   }
-                  ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+                  ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
                   break;
                 }
                 case 10: {
-                  NamePart_ = input.ReadString();
+                  result.hasNamePart_ |= input.ReadString(ref result.namePart_);
                   break;
                 }
                 case 16: {
-                  IsExtension = input.ReadBool();
+                  result.hasIsExtension |= input.ReadBool(ref result.isExtension_);
                   break;
                 }
               }
@@ -7027,33 +6989,31 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 18: {
-              global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddName(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.name_, global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Types.NamePart.DefaultInstance, extensionRegistry);
               break;
             }
             case 26: {
-              IdentifierValue = input.ReadString();
+              result.hasIdentifierValue |= input.ReadString(ref result.identifierValue_);
               break;
             }
             case 32: {
-              PositiveIntValue = input.ReadUInt64();
+              result.hasPositiveIntValue |= input.ReadUInt64(ref result.positiveIntValue_);
               break;
             }
             case 40: {
-              NegativeIntValue = input.ReadInt64();
+              result.hasNegativeIntValue |= input.ReadInt64(ref result.negativeIntValue_);
               break;
             }
             case 49: {
-              DoubleValue = input.ReadDouble();
+              result.hasDoubleValue |= input.ReadDouble(ref result.doubleValue_);
               break;
             }
             case 58: {
-              StringValue = input.ReadBytes();
+              result.hasStringValue |= input.ReadBytes(ref result.stringValue_);
               break;
             }
           }

+ 4 - 0
src/ProtocolBuffers/Descriptors/EnumDescriptor.cs

@@ -98,6 +98,10 @@ namespace Google.ProtocolBuffers.Descriptors
         {
             return FindValueByNumber(number);
         }
+        IEnumLite IEnumLiteMap.FindValueByName(string name)
+        {
+            return FindValueByName(name);
+        }
 
         /// <summary>
         /// Finds an enum value by name.

+ 9 - 0
src/ProtocolBuffers/EnumLite.cs

@@ -70,6 +70,7 @@ namespace Google.ProtocolBuffers
     {
         bool IsValidValue(IEnumLite value);
         IEnumLite FindValueByNumber(int number);
+        IEnumLite FindValueByName(string name);
     }
 
     public class EnumLiteMap<TEnum> : IEnumLiteMap<IEnumLite>
@@ -125,6 +126,14 @@ namespace Google.ProtocolBuffers
             return items.TryGetValue(number, out val) ? val : null;
         }
 
+        public IEnumLite FindValueByName(string name)
+        {
+            IEnumLite val;
+            if(Enum.IsDefined(typeof(TEnum), name))
+                return items.TryGetValue((int)Enum.Parse(typeof(TEnum), name, false), out val) ? val : null;
+            return null;
+        }
+
         public bool IsValidValue(IEnumLite value)
         {
             return items.ContainsKey(value.Number);

+ 2 - 2
src/ProtocolBuffers/ExtendableBuilder.cs

@@ -131,9 +131,9 @@ namespace Google.ProtocolBuffers
         /// <returns>true unless the tag is an end-group tag</returns>
         [CLSCompliant(false)]
         protected override bool ParseUnknownField(CodedInputStream input, UnknownFieldSet.Builder unknownFields,
-                                                  ExtensionRegistry extensionRegistry, uint tag)
+                                                  ExtensionRegistry extensionRegistry, uint tag, string fieldName)
         {
-            return unknownFields.MergeFieldFrom(input, extensionRegistry, this, tag);
+            return unknownFields.MergeFieldFrom(input, extensionRegistry, this, tag, fieldName);
         }
 
         // ---------------------------------------------------------------

+ 60 - 98
src/ProtocolBuffers/ExtendableBuilderLite.cs

@@ -134,7 +134,7 @@ namespace Google.ProtocolBuffers
         /// <returns>true unless the tag is an end-group tag</returns>
         [CLSCompliant(false)]
         protected override bool ParseUnknownField(CodedInputStream input,
-                                                  ExtensionRegistry extensionRegistry, uint tag)
+                                                  ExtensionRegistry extensionRegistry, uint tag, string fieldName)
         {
             FieldSet extensions = MessageBeingBuilt.Extensions;
 
@@ -142,119 +142,81 @@ namespace Google.ProtocolBuffers
             int fieldNumber = WireFormat.GetTagFieldNumber(tag);
             IGeneratedExtensionLite extension = extensionRegistry[DefaultInstanceForType, fieldNumber];
 
-            bool unknown = false;
-            bool packed = false;
-            if (extension == null)
-            {
-                unknown = true; // Unknown field.
-            }
-            else if (wireType ==
-                     FieldMappingAttribute.WireTypeFromFieldType(extension.Descriptor.FieldType, false /* isPacked */))
-            {
-                packed = false; // Normal, unpacked value.
-            }
-            else if (extension.Descriptor.IsRepeated &&
-                     //?? just returns true ?? extension.Descriptor.type.isPackable() &&
-                     wireType ==
-                     FieldMappingAttribute.WireTypeFromFieldType(extension.Descriptor.FieldType, true /* isPacked */))
-            {
-                packed = true; // Packed value.
-            }
-            else
-            {
-                unknown = true; // Wrong wire type.
-            }
+            if (extension == null)//unknown field
+                return input.SkipField();
 
-            if (unknown)
-            {
-                // Unknown field or wrong wire type.  Skip.
+            IFieldDescriptorLite field = extension.Descriptor;
+            if (!field.IsRepeated && wireType != WireFormat.GetWireType(field.FieldType)) //invalid wire type
                 return input.SkipField();
-            }
 
-            if (packed)
+            switch (field.FieldType)
             {
-                int length = (int) Math.Min(int.MaxValue, input.ReadRawVarint32());
-                int limit = input.PushLimit(length);
-                if (extension.Descriptor.FieldType == FieldType.Enum)
-                {
-                    while (!input.ReachedLimit)
+                case FieldType.Group:
+                case FieldType.Message:
                     {
-                        int rawValue = input.ReadEnum();
-                        Object value =
-                            extension.Descriptor.EnumType.FindValueByNumber(rawValue);
-                        if (value == null)
+                        if (!field.IsRepeated)
+                        {
+                            IMessageLite message = extensions[extension.Descriptor] as IMessageLite;
+                            IBuilderLite subBuilder = (message ?? extension.MessageDefaultInstance).WeakToBuilder();
+
+                            if (field.FieldType == FieldType.Group)
+                                input.ReadGroup(field.FieldNumber, subBuilder, extensionRegistry);
+                            else
+                                input.ReadMessage(subBuilder, extensionRegistry);
+                            
+                            extensions[field] = subBuilder.WeakBuild();
+                        }
+                        else
                         {
-                            // If the number isn't recognized as a valid value for this
-                            // enum, drop it (don't even add it to unknownFields).
+                            List<IMessageLite> list = new List<IMessageLite>();
+                            if (field.FieldType == FieldType.Group)
+                                input.ReadGroupArray(tag, fieldName, list, extension.MessageDefaultInstance, extensionRegistry);
+                            else
+                                input.ReadMessageArray(tag, fieldName, list, extension.MessageDefaultInstance, extensionRegistry);
+
+                            foreach (IMessageLite m in list)
+                                extensions.AddRepeatedField(field, m);
                             return true;
                         }
-                        extensions.AddRepeatedField(extension.Descriptor, value);
+                        break;
                     }
-                }
-                else
-                {
-                    while (!input.ReachedLimit)
+                case FieldType.Enum:
                     {
-                        Object value = input.ReadPrimitiveField(extension.Descriptor.FieldType);
-                        extensions.AddRepeatedField(extension.Descriptor, value);
-                    }
-                }
-                input.PopLimit(limit);
-            }
-            else
-            {
-                Object value;
-                switch (extension.Descriptor.MappedType)
-                {
-                    case MappedType.Message:
+                        if (!field.IsRepeated)
                         {
-                            IBuilderLite subBuilder = null;
-                            if (!extension.Descriptor.IsRepeated)
-                            {
-                                IMessageLite existingValue = extensions[extension.Descriptor] as IMessageLite;
-                                if (existingValue != null)
-                                {
-                                    subBuilder = existingValue.WeakToBuilder();
-                                }
-                            }
-                            if (subBuilder == null)
-                            {
-                                subBuilder = extension.MessageDefaultInstance.WeakCreateBuilderForType();
-                            }
-                            if (extension.Descriptor.FieldType == FieldType.Group)
-                            {
-                                input.ReadGroup(extension.Number, subBuilder, extensionRegistry);
-                            }
-                            else
-                            {
-                                input.ReadMessage(subBuilder, extensionRegistry);
-                            }
-                            value = subBuilder.WeakBuild();
-                            break;
+                            object unknown;
+                            IEnumLite value = null;
+                            if (input.ReadEnum(ref value, out unknown, field.EnumType))
+                                extensions[field] = value;
                         }
-                    case MappedType.Enum:
-                        int rawValue = input.ReadEnum();
-                        value = extension.Descriptor.EnumType.FindValueByNumber(rawValue);
-                        // If the number isn't recognized as a valid value for this enum,
-                        // drop it.
-                        if (value == null)
+                        else
                         {
-                            return true;
+                            ICollection<object> unknown;
+                            List<IEnumLite> list = new List<IEnumLite>();
+                            input.ReadEnumArray(tag, fieldName, list, out unknown, field.EnumType);
+
+                            foreach (IEnumLite en in list)
+                                extensions.AddRepeatedField(field, en);
                         }
                         break;
-                    default:
-                        value = input.ReadPrimitiveField(extension.Descriptor.FieldType);
+                    }
+                default:
+                    {
+                        if (!field.IsRepeated)
+                        {
+                            object value = null;
+                            if (input.ReadPrimitiveField(field.FieldType, ref value))
+                                extensions[field] = value;
+                        }
+                        else
+                        {
+                            List<object> list = new List<object>();
+                            input.ReadPrimitiveArray(field.FieldType, tag, fieldName, list);
+                            foreach (object oval in list)
+                                extensions.AddRepeatedField(field, oval);
+                        }
                         break;
-                }
-
-                if (extension.Descriptor.IsRepeated)
-                {
-                    extensions.AddRepeatedField(extension.Descriptor, value);
-                }
-                else
-                {
-                    extensions[extension.Descriptor] = value;
-                }
+                    }
             }
 
             return true;

+ 1 - 1
src/ProtocolBuffers/GeneratedBuilder.cs

@@ -116,7 +116,7 @@ namespace Google.ProtocolBuffers
         /// <returns>true unless the tag is an end-group tag</returns>
         [CLSCompliant(false)]
         protected virtual bool ParseUnknownField(CodedInputStream input, UnknownFieldSet.Builder unknownFields,
-                                                 ExtensionRegistry extensionRegistry, uint tag)
+                                                 ExtensionRegistry extensionRegistry, uint tag, string fieldName)
         {
             return unknownFields.MergeFieldFrom(tag, input);
         }

+ 1 - 1
src/ProtocolBuffers/GeneratedBuilderLite.cs

@@ -99,7 +99,7 @@ namespace Google.ProtocolBuffers
         /// <returns>true unless the tag is an end-group tag</returns>
         [CLSCompliant(false)]
         protected virtual bool ParseUnknownField(CodedInputStream input,
-                                                 ExtensionRegistry extensionRegistry, uint tag)
+                                                 ExtensionRegistry extensionRegistry, uint tag, string fieldName)
         {
             return input.SkipField();
         }

+ 100 - 97
src/ProtocolBuffers/UnknownFieldSet.cs

@@ -450,14 +450,33 @@ namespace Google.ProtocolBuffers
                 switch (WireFormat.GetTagWireType(tag))
                 {
                     case WireFormat.WireType.Varint:
-                        GetFieldBuilder(number).AddVarint(input.ReadUInt64());
-                        return true;
+                        {
+                            ulong uint64 = 0;
+                            if(input.ReadUInt64(ref uint64))
+                                GetFieldBuilder(number).AddVarint(uint64);
+                            return true;
+                        }
+                    case WireFormat.WireType.Fixed32:
+                        {
+                            uint uint32 = 0;
+                            if (input.ReadFixed32(ref uint32))
+                                GetFieldBuilder(number).AddFixed32(uint32);
+                            return true;
+                        }
                     case WireFormat.WireType.Fixed64:
-                        GetFieldBuilder(number).AddFixed64(input.ReadFixed64());
-                        return true;
+                        {
+                            ulong uint64 = 0;
+                            if (input.ReadFixed64(ref uint64))
+                                GetFieldBuilder(number).AddFixed64(uint64);
+                            return true;
+                        }
                     case WireFormat.WireType.LengthDelimited:
-                        GetFieldBuilder(number).AddLengthDelimited(input.ReadBytes());
-                        return true;
+                        {
+                            ByteString bytes = null;
+                            if (input.ReadBytes(ref bytes))
+                                GetFieldBuilder(number).AddLengthDelimited(bytes);
+                            return true;
+                        }
                     case WireFormat.WireType.StartGroup:
                         {
                             Builder subBuilder = CreateBuilder();
@@ -469,9 +488,6 @@ namespace Google.ProtocolBuffers
                         }
                     case WireFormat.WireType.EndGroup:
                         return false;
-                    case WireFormat.WireType.Fixed32:
-                        GetFieldBuilder(number).AddFixed32(input.ReadFixed32());
-                        return true;
                     default:
                         throw InvalidProtocolBufferException.InvalidWireType();
                 }
@@ -598,7 +614,7 @@ namespace Google.ProtocolBuffers
                         break;
                     }
 
-                    if (!MergeFieldFrom(input, extensionRegistry, builder, tag))
+                    if (!MergeFieldFrom(input, extensionRegistry, builder, tag, name))
                     {
                         // end group tag
                         break;
@@ -616,7 +632,7 @@ namespace Google.ProtocolBuffers
             /// <param name="tag">The tag, which should already have been read from the input</param>
             /// <returns>true unless the tag is an end-group tag</returns>
             internal bool MergeFieldFrom(CodedInputStream input,
-                                         ExtensionRegistry extensionRegistry, IBuilder builder, uint tag)
+                                         ExtensionRegistry extensionRegistry, IBuilder builder, uint tag, string fieldName)
             {
                 MessageDescriptor type = builder.DescriptorForType;
                 if (type.Options.MessageSetWireFormat && tag == WireFormat.MessageSetTag.ItemStart)
@@ -655,92 +671,81 @@ namespace Google.ProtocolBuffers
                     return MergeFieldFrom(tag, input);
                 }
 
-                if (field.IsPacked)
+                switch (field.FieldType)
                 {
-                    int length = (int) input.ReadRawVarint32();
-                    int limit = input.PushLimit(length);
-                    if (field.FieldType == FieldType.Enum)
-                    {
-                        while (!input.ReachedLimit)
+                    case FieldType.Group:
+                    case FieldType.Message:
                         {
-                            int rawValue = input.ReadEnum();
-                            object value = field.EnumType.FindValueByNumber(rawValue);
-                            if (value == null)
+                            IBuilderLite subBuilder = (defaultFieldInstance != null) ? defaultFieldInstance.WeakCreateBuilderForType() : builder.CreateBuilderForField(field);
+                            if (!field.IsRepeated)
+                            {
+                                subBuilder.WeakMergeFrom((IMessageLite)builder[field]);
+                                if (field.FieldType == FieldType.Group)
+                                    input.ReadGroup(field.FieldNumber, subBuilder, extensionRegistry);
+                                else
+                                    input.ReadMessage(subBuilder, extensionRegistry);
+                                builder[field] = subBuilder.WeakBuild();
+                            }
+                            else
                             {
-                                // If the number isn't recognized as a valid value for this
-                                // enum, drop it (don't even add it to unknownFields).
+                                List<IMessageLite> list = new List<IMessageLite>();
+                                if (field.FieldType == FieldType.Group)
+                                    input.ReadGroupArray(tag, fieldName, list, subBuilder.WeakDefaultInstanceForType, extensionRegistry);
+                                else
+                                    input.ReadMessageArray(tag, fieldName, list, subBuilder.WeakDefaultInstanceForType, extensionRegistry);
+
+                                foreach (IMessageLite m in list)
+                                    builder.WeakAddRepeatedField(field, m);
                                 return true;
                             }
-                            builder.WeakAddRepeatedField(field, value);
+                            break;
                         }
-                    }
-                    else
-                    {
-                        while (!input.ReachedLimit)
+                    case FieldType.Enum:
                         {
-                            Object value = input.ReadPrimitiveField(field.FieldType);
-                            builder.WeakAddRepeatedField(field, value);
-                        }
-                    }
-                    input.PopLimit(limit);
-                }
-                else
-                {
-                    object value;
-                    switch (field.FieldType)
-                    {
-                        case FieldType.Group:
-                        case FieldType.Message:
+                            if (!field.IsRepeated)
                             {
-                                IBuilderLite subBuilder;
-                                if (defaultFieldInstance != null)
-                                {
-                                    subBuilder = defaultFieldInstance.WeakCreateBuilderForType();
-                                }
-                                else
-                                {
-                                    subBuilder = builder.CreateBuilderForField(field);
-                                }
-                                if (!field.IsRepeated)
-                                {
-                                    subBuilder.WeakMergeFrom((IMessageLite) builder[field]);
-                                }
-                                if (field.FieldType == FieldType.Group)
-                                {
-                                    input.ReadGroup(field.FieldNumber, subBuilder, extensionRegistry);
-                                }
-                                else
-                                {
-                                    input.ReadMessage(subBuilder, extensionRegistry);
-                                }
-                                value = subBuilder.WeakBuild();
-                                break;
+                                object unknown;
+                                IEnumLite value = null;
+                                if (input.ReadEnum(ref value, out unknown, field.EnumType))
+                                    builder[field] = value;
+                                else if(unknown is int)
+                                    MergeVarintField(fieldNumber, (ulong)(int)unknown);
                             }
-                        case FieldType.Enum:
+                            else
                             {
-                                int rawValue = input.ReadEnum();
-                                value = field.EnumType.FindValueByNumber(rawValue);
-                                // If the number isn't recognized as a valid value for this enum,
-                                // drop it.
-                                if (value == null)
+                                ICollection<object> unknown;
+                                List<IEnumLite> list = new List<IEnumLite>();
+                                input.ReadEnumArray(tag, fieldName, list, out unknown, field.EnumType);
+                                
+                                foreach (IEnumLite en in list)
+                                    builder.WeakAddRepeatedField(field, en);
+
+                                if (unknown != null)
                                 {
-                                    MergeVarintField(fieldNumber, (ulong) rawValue);
-                                    return true;
+                                    foreach (object oval in unknown)
+                                        if (oval is int)
+                                            MergeVarintField(fieldNumber, (ulong)(int)oval);
                                 }
-                                break;
                             }
-                        default:
-                            value = input.ReadPrimitiveField(field.FieldType);
                             break;
-                    }
-                    if (field.IsRepeated)
-                    {
-                        builder.WeakAddRepeatedField(field, value);
-                    }
-                    else
-                    {
-                        builder[field] = value;
-                    }
+                        }
+                    default:
+                        {
+                            if (!field.IsRepeated)
+                            {
+                                object value = null;
+                                if (input.ReadPrimitiveField(field.FieldType, ref value))
+                                    builder[field] = value;
+                            }
+                            else
+                            {
+                                List<object> list = new List<object>();
+                                input.ReadPrimitiveArray(field.FieldType, tag, fieldName, list);
+                                foreach (object oval in list)
+                                    builder.WeakAddRepeatedField(field, oval);
+                            }
+                            break;
+                        }
                 }
                 return true;
             }
@@ -787,9 +792,9 @@ namespace Google.ProtocolBuffers
 
                     if (tag == WireFormat.MessageSetTag.TypeID)
                     {
-                        typeId = input.ReadInt32();
+                        typeId = 0;
                         // Zero is not a valid type ID.
-                        if (typeId != 0)
+                        if (input.ReadInt32(ref typeId) && typeId != 0)
                         {
                             ExtensionInfo extension = extensionRegistry[type, typeId];
                             if (extension != null)
@@ -824,23 +829,21 @@ namespace Google.ProtocolBuffers
                     }
                     else if (tag == WireFormat.MessageSetTag.Message)
                     {
-                        if (typeId == 0)
-                        {
-                            // We haven't seen a type ID yet, so we have to store the raw bytes for now.
-                            rawBytes = input.ReadBytes();
-                        }
-                        else if (subBuilder == null)
-                        {
-                            // We don't know how to parse this.  Ignore it.
-                            MergeField(typeId,
-                                       UnknownField.CreateBuilder().AddLengthDelimited(input.ReadBytes()).Build());
-                        }
-                        else
+                        if(subBuilder != null)
                         {
                             // We already know the type, so we can parse directly from the input
                             // with no copying.  Hooray!
                             input.ReadMessage(subBuilder, extensionRegistry);
                         }
+                        else if (input.ReadBytes(ref rawBytes))
+                        {
+                            if (typeId != 0)
+                            {
+                                // We don't know how to parse this.  Ignore it.
+                                MergeField(typeId,
+                                           UnknownField.CreateBuilder().AddLengthDelimited(rawBytes).Build());
+                            }
+                        }
                     }
                     else
                     {

+ 27 - 36
src/ProtocolBuffersLite.Test/TestProtos/UnitTestExtrasLiteProtoFile.cs

@@ -258,18 +258,18 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (pb::WireFormat.IsEndGroupTag(tag)) {
                 return this;
               }
-              ParseUnknownField(input, extensionRegistry, tag);
+              ParseUnknownField(input, extensionRegistry, tag, field_name);
               break;
             }
             case 8: {
-              D = input.ReadInt32();
+              result.hasD |= input.ReadInt32(ref result.d_);
               break;
             }
             case 16: {
-              int rawValue = input.ReadEnum();
-              if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.TestProtos.ExtraEnum), rawValue)) {
-              } else {
-                En = (global::Google.ProtocolBuffers.TestProtos.ExtraEnum) rawValue;
+              object unknown;
+              if(input.ReadEnum(ref result.en_, out unknown)) {
+                result.hasEn = true;
+              } else if(unknown is int) {
               }
               break;
             }
@@ -555,18 +555,18 @@ namespace Google.ProtocolBuffers.TestProtos {
                   if (pb::WireFormat.IsEndGroupTag(tag)) {
                     return this;
                   }
-                  ParseUnknownField(input, extensionRegistry, tag);
+                  ParseUnknownField(input, extensionRegistry, tag, field_name);
                   break;
                 }
                 case 10: {
-                  Number = input.ReadString();
+                  result.hasNumber |= input.ReadString(ref result.number_);
                   break;
                 }
                 case 16: {
-                  int rawValue = input.ReadEnum();
-                  if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneType), rawValue)) {
-                  } else {
-                    Type = (global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneType) rawValue;
+                  object unknown;
+                  if(input.ReadEnum(ref result.type_, out unknown)) {
+                    result.hasType = true;
+                  } else if(unknown is int) {
                   }
                   break;
                 }
@@ -893,27 +893,27 @@ namespace Google.ProtocolBuffers.TestProtos {
                   if (pb::WireFormat.IsEndGroupTag(tag)) {
                     return this;
                   }
-                  ParseUnknownField(input, extensionRegistry, tag);
+                  ParseUnknownField(input, extensionRegistry, tag, field_name);
                   break;
                 }
                 case 10: {
-                  Address = input.ReadString();
+                  result.hasAddress |= input.ReadString(ref result.address_);
                   break;
                 }
                 case 18: {
-                  Address2 = input.ReadString();
+                  result.hasAddress2 |= input.ReadString(ref result.address2_);
                   break;
                 }
                 case 26: {
-                  City = input.ReadString();
+                  result.hasCity |= input.ReadString(ref result.city_);
                   break;
                 }
                 case 34: {
-                  State = input.ReadString();
+                  result.hasState |= input.ReadString(ref result.state_);
                   break;
                 }
                 case 45: {
-                  Zip = input.ReadFixed32();
+                  result.hasZip |= input.ReadFixed32(ref result.zip_);
                   break;
                 }
               }
@@ -1341,40 +1341,31 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (pb::WireFormat.IsEndGroupTag(tag)) {
                 return this;
               }
-              ParseUnknownField(input, extensionRegistry, tag);
+              ParseUnknownField(input, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              Name = input.ReadString();
+              result.hasName |= input.ReadString(ref result.name_);
               break;
             }
             case 16: {
-              Id = input.ReadInt32();
+              result.hasId |= input.ReadInt32(ref result.id_);
               break;
             }
             case 26: {
-              Email = input.ReadString();
+              result.hasEmail |= input.ReadString(ref result.email_);
               break;
             }
             case 34: {
-              global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddPhone(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.phone_, global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber.DefaultInstance, extensionRegistry);
               break;
             }
             case 43: {
-              global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses.CreateBuilder();
-              input.ReadGroup(5, subBuilder, extensionRegistry);
-              AddAddresses(subBuilder.BuildPartial());
+              input.ReadGroupArray(tag, field_name, result.addresses_, global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses.DefaultInstance, extensionRegistry);
               break;
             }
             case 82: {
-              int length = input.ReadInt32();
-              int limit = input.PushLimit(length);
-              while (!input.ReachedLimit) {
-                AddCodes(input.ReadInt32());
-              }
-              input.PopLimit(limit);
+              input.ReadPrimitiveArray(pbd::FieldType.Int32, tag, field_name, result.codes_);
               break;
             }
           }
@@ -1729,11 +1720,11 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (pb::WireFormat.IsEndGroupTag(tag)) {
                 return this;
               }
-              ParseUnknownField(input, extensionRegistry, tag);
+              ParseUnknownField(input, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {
-              Number = input.ReadString();
+              result.hasNumber |= input.ReadString(ref result.number_);
               break;
             }
           }

+ 2 - 2
src/ProtocolBuffersLite.Test/TestProtos/UnitTestImportLiteProtoFile.cs

@@ -218,11 +218,11 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (pb::WireFormat.IsEndGroupTag(tag)) {
                 return this;
               }
-              ParseUnknownField(input, extensionRegistry, tag);
+              ParseUnknownField(input, extensionRegistry, tag, field_name);
               break;
             }
             case 8: {
-              D = input.ReadInt32();
+              result.hasD |= input.ReadInt32(ref result.d_);
               break;
             }
           }

+ 2 - 2
src/ProtocolBuffersLite.Test/TestProtos/UnitTestImportProtoFile.cs

@@ -249,11 +249,11 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (unknownFields == null) {
                 unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
               }
-              ParseUnknownField(input, unknownFields, extensionRegistry, tag);
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
               break;
             }
             case 8: {
-              D = input.ReadInt32();
+              result.hasD |= input.ReadInt32(ref result.d_);
               break;
             }
           }

+ 1 - 1
src/ProtocolBuffersLite.Test/TestProtos/UnitTestLiteImportNonLiteProtoFile.cs

@@ -207,7 +207,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (pb::WireFormat.IsEndGroupTag(tag)) {
                 return this;
               }
-              ParseUnknownField(input, extensionRegistry, tag);
+              ParseUnknownField(input, extensionRegistry, tag, field_name);
               break;
             }
             case 10: {

+ 119 - 209
src/ProtocolBuffersLite.Test/TestProtos/UnitTestLiteProtoFile.cs

@@ -1261,11 +1261,11 @@ namespace Google.ProtocolBuffers.TestProtos {
                   if (pb::WireFormat.IsEndGroupTag(tag)) {
                     return this;
                   }
-                  ParseUnknownField(input, extensionRegistry, tag);
+                  ParseUnknownField(input, extensionRegistry, tag, field_name);
                   break;
                 }
                 case 8: {
-                  Bb = input.ReadInt32();
+                  result.hasBb |= input.ReadInt32(ref result.bb_);
                   break;
                 }
               }
@@ -1479,11 +1479,11 @@ namespace Google.ProtocolBuffers.TestProtos {
                   if (pb::WireFormat.IsEndGroupTag(tag)) {
                     return this;
                   }
-                  ParseUnknownField(input, extensionRegistry, tag);
+                  ParseUnknownField(input, extensionRegistry, tag, field_name);
                   break;
                 }
                 case 136: {
-                  A = input.ReadInt32();
+                  result.hasA |= input.ReadInt32(ref result.a_);
                   break;
                 }
               }
@@ -1697,11 +1697,11 @@ namespace Google.ProtocolBuffers.TestProtos {
                   if (pb::WireFormat.IsEndGroupTag(tag)) {
                     return this;
                   }
-                  ParseUnknownField(input, extensionRegistry, tag);
+                  ParseUnknownField(input, extensionRegistry, tag, field_name);
                   break;
                 }
                 case 376: {
-                  A = input.ReadInt32();
+                  result.hasA |= input.ReadInt32(ref result.a_);
                   break;
                 }
               }
@@ -3627,67 +3627,67 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (pb::WireFormat.IsEndGroupTag(tag)) {
                 return this;
               }
-              ParseUnknownField(input, extensionRegistry, tag);
+              ParseUnknownField(input, extensionRegistry, tag, field_name);
               break;
             }
             case 8: {
-              OptionalInt32 = input.ReadInt32();
+              result.hasOptionalInt32 |= input.ReadInt32(ref result.optionalInt32_);
               break;
             }
             case 16: {
-              OptionalInt64 = input.ReadInt64();
+              result.hasOptionalInt64 |= input.ReadInt64(ref result.optionalInt64_);
               break;
             }
             case 24: {
-              OptionalUint32 = input.ReadUInt32();
+              result.hasOptionalUint32 |= input.ReadUInt32(ref result.optionalUint32_);
               break;
             }
             case 32: {
-              OptionalUint64 = input.ReadUInt64();
+              result.hasOptionalUint64 |= input.ReadUInt64(ref result.optionalUint64_);
               break;
             }
             case 40: {
-              OptionalSint32 = input.ReadSInt32();
+              result.hasOptionalSint32 |= input.ReadSInt32(ref result.optionalSint32_);
               break;
             }
             case 48: {
-              OptionalSint64 = input.ReadSInt64();
+              result.hasOptionalSint64 |= input.ReadSInt64(ref result.optionalSint64_);
               break;
             }
             case 61: {
-              OptionalFixed32 = input.ReadFixed32();
+              result.hasOptionalFixed32 |= input.ReadFixed32(ref result.optionalFixed32_);
               break;
             }
             case 65: {
-              OptionalFixed64 = input.ReadFixed64();
+              result.hasOptionalFixed64 |= input.ReadFixed64(ref result.optionalFixed64_);
               break;
             }
             case 77: {
-              OptionalSfixed32 = input.ReadSFixed32();
+              result.hasOptionalSfixed32 |= input.ReadSFixed32(ref result.optionalSfixed32_);
               break;
             }
             case 81: {
-              OptionalSfixed64 = input.ReadSFixed64();
+              result.hasOptionalSfixed64 |= input.ReadSFixed64(ref result.optionalSfixed64_);
               break;
             }
             case 93: {
-              OptionalFloat = input.ReadFloat();
+              result.hasOptionalFloat |= input.ReadFloat(ref result.optionalFloat_);
               break;
             }
             case 97: {
-              OptionalDouble = input.ReadDouble();
+              result.hasOptionalDouble |= input.ReadDouble(ref result.optionalDouble_);
               break;
             }
             case 104: {
-              OptionalBool = input.ReadBool();
+              result.hasOptionalBool |= input.ReadBool(ref result.optionalBool_);
               break;
             }
             case 114: {
-              OptionalString = input.ReadString();
+              result.hasOptionalString |= input.ReadString(ref result.optionalString_);
               break;
             }
             case 122: {
-              OptionalBytes = input.ReadBytes();
+              result.hasOptionalBytes |= input.ReadBytes(ref result.optionalBytes_);
               break;
             }
             case 131: {
@@ -3727,243 +3727,226 @@ namespace Google.ProtocolBuffers.TestProtos {
               break;
             }
             case 168: {
-              int rawValue = input.ReadEnum();
-              if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedEnum), rawValue)) {
-              } else {
-                OptionalNestedEnum = (global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedEnum) rawValue;
+              object unknown;
+              if(input.ReadEnum(ref result.optionalNestedEnum_, out unknown)) {
+                result.hasOptionalNestedEnum = true;
+              } else if(unknown is int) {
               }
               break;
             }
             case 176: {
-              int rawValue = input.ReadEnum();
-              if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.TestProtos.ForeignEnumLite), rawValue)) {
-              } else {
-                OptionalForeignEnum = (global::Google.ProtocolBuffers.TestProtos.ForeignEnumLite) rawValue;
+              object unknown;
+              if(input.ReadEnum(ref result.optionalForeignEnum_, out unknown)) {
+                result.hasOptionalForeignEnum = true;
+              } else if(unknown is int) {
               }
               break;
             }
             case 184: {
-              int rawValue = input.ReadEnum();
-              if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.TestProtos.ImportEnumLite), rawValue)) {
-              } else {
-                OptionalImportEnum = (global::Google.ProtocolBuffers.TestProtos.ImportEnumLite) rawValue;
+              object unknown;
+              if(input.ReadEnum(ref result.optionalImportEnum_, out unknown)) {
+                result.hasOptionalImportEnum = true;
+              } else if(unknown is int) {
               }
               break;
             }
             case 194: {
-              OptionalStringPiece = input.ReadString();
+              result.hasOptionalStringPiece |= input.ReadString(ref result.optionalStringPiece_);
               break;
             }
             case 202: {
-              OptionalCord = input.ReadString();
+              result.hasOptionalCord |= input.ReadString(ref result.optionalCord_);
               break;
             }
             case 248: {
-              AddRepeatedInt32(input.ReadInt32());
+              input.ReadPrimitiveArray(pbd::FieldType.Int32, tag, field_name, result.repeatedInt32_);
               break;
             }
             case 256: {
-              AddRepeatedInt64(input.ReadInt64());
+              input.ReadPrimitiveArray(pbd::FieldType.Int64, tag, field_name, result.repeatedInt64_);
               break;
             }
             case 264: {
-              AddRepeatedUint32(input.ReadUInt32());
+              input.ReadPrimitiveArray(pbd::FieldType.UInt32, tag, field_name, result.repeatedUint32_);
               break;
             }
             case 272: {
-              AddRepeatedUint64(input.ReadUInt64());
+              input.ReadPrimitiveArray(pbd::FieldType.UInt64, tag, field_name, result.repeatedUint64_);
               break;
             }
             case 280: {
-              AddRepeatedSint32(input.ReadSInt32());
+              input.ReadPrimitiveArray(pbd::FieldType.SInt32, tag, field_name, result.repeatedSint32_);
               break;
             }
             case 288: {
-              AddRepeatedSint64(input.ReadSInt64());
+              input.ReadPrimitiveArray(pbd::FieldType.SInt64, tag, field_name, result.repeatedSint64_);
               break;
             }
             case 301: {
-              AddRepeatedFixed32(input.ReadFixed32());
+              input.ReadPrimitiveArray(pbd::FieldType.Fixed32, tag, field_name, result.repeatedFixed32_);
               break;
             }
             case 305: {
-              AddRepeatedFixed64(input.ReadFixed64());
+              input.ReadPrimitiveArray(pbd::FieldType.Fixed64, tag, field_name, result.repeatedFixed64_);
               break;
             }
             case 317: {
-              AddRepeatedSfixed32(input.ReadSFixed32());
+              input.ReadPrimitiveArray(pbd::FieldType.SFixed32, tag, field_name, result.repeatedSfixed32_);
               break;
             }
             case 321: {
-              AddRepeatedSfixed64(input.ReadSFixed64());
+              input.ReadPrimitiveArray(pbd::FieldType.SFixed64, tag, field_name, result.repeatedSfixed64_);
               break;
             }
             case 333: {
-              AddRepeatedFloat(input.ReadFloat());
+              input.ReadPrimitiveArray(pbd::FieldType.Float, tag, field_name, result.repeatedFloat_);
               break;
             }
             case 337: {
-              AddRepeatedDouble(input.ReadDouble());
+              input.ReadPrimitiveArray(pbd::FieldType.Double, tag, field_name, result.repeatedDouble_);
               break;
             }
             case 344: {
-              AddRepeatedBool(input.ReadBool());
+              input.ReadPrimitiveArray(pbd::FieldType.Bool, tag, field_name, result.repeatedBool_);
               break;
             }
             case 354: {
-              AddRepeatedString(input.ReadString());
+              input.ReadPrimitiveArray(pbd::FieldType.String, tag, field_name, result.repeatedString_);
               break;
             }
             case 362: {
-              AddRepeatedBytes(input.ReadBytes());
+              input.ReadPrimitiveArray(pbd::FieldType.Bytes, tag, field_name, result.repeatedBytes_);
               break;
             }
             case 371: {
-              global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.RepeatedGroup.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.RepeatedGroup.CreateBuilder();
-              input.ReadGroup(46, subBuilder, extensionRegistry);
-              AddRepeatedGroup(subBuilder.BuildPartial());
+              input.ReadGroupArray(tag, field_name, result.repeatedGroup_, global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.RepeatedGroup.DefaultInstance, extensionRegistry);
               break;
             }
             case 386: {
-              global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddRepeatedNestedMessage(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.repeatedNestedMessage_, global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage.DefaultInstance, extensionRegistry);
               break;
             }
             case 394: {
-              global::Google.ProtocolBuffers.TestProtos.ForeignMessageLite.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.ForeignMessageLite.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddRepeatedForeignMessage(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.repeatedForeignMessage_, global::Google.ProtocolBuffers.TestProtos.ForeignMessageLite.DefaultInstance, extensionRegistry);
               break;
             }
             case 402: {
-              global::Google.ProtocolBuffers.TestProtos.ImportMessageLite.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.ImportMessageLite.CreateBuilder();
-              input.ReadMessage(subBuilder, extensionRegistry);
-              AddRepeatedImportMessage(subBuilder.BuildPartial());
+              input.ReadMessageArray(tag, field_name, result.repeatedImportMessage_, global::Google.ProtocolBuffers.TestProtos.ImportMessageLite.DefaultInstance, extensionRegistry);
               break;
             }
             case 408: {
-              int rawValue = input.ReadEnum();
-              if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedEnum), rawValue)) {
-              } else {
-                AddRepeatedNestedEnum((global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedEnum) rawValue);
-              }
+              scg::ICollection<object> unknownItems;
+              input.ReadEnumArray<global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedEnum>(tag, field_name, result.repeatedNestedEnum_, out unknownItems);
               break;
             }
             case 416: {
-              int rawValue = input.ReadEnum();
-              if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.TestProtos.ForeignEnumLite), rawValue)) {
-              } else {
-                AddRepeatedForeignEnum((global::Google.ProtocolBuffers.TestProtos.ForeignEnumLite) rawValue);
-              }
+              scg::ICollection<object> unknownItems;
+              input.ReadEnumArray<global::Google.ProtocolBuffers.TestProtos.ForeignEnumLite>(tag, field_name, result.repeatedForeignEnum_, out unknownItems);
               break;
             }
             case 424: {
-              int rawValue = input.ReadEnum();
-              if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.TestProtos.ImportEnumLite), rawValue)) {
-              } else {
-                AddRepeatedImportEnum((global::Google.ProtocolBuffers.TestProtos.ImportEnumLite) rawValue);
-              }
+              scg::ICollection<object> unknownItems;
+              input.ReadEnumArray<global::Google.ProtocolBuffers.TestProtos.ImportEnumLite>(tag, field_name, result.repeatedImportEnum_, out unknownItems);
               break;
             }
             case 434: {
-              AddRepeatedStringPiece(input.ReadString());
+              input.ReadPrimitiveArray(pbd::FieldType.String, tag, field_name, result.repeatedStringPiece_);
               break;
             }
             case 442: {
-              AddRepeatedCord(input.ReadString());
+              input.ReadPrimitiveArray(pbd::FieldType.String, tag, field_name, result.repeatedCord_);
               break;
             }
             case 488: {
-              DefaultInt32 = input.ReadInt32();
+              result.hasDefaultInt32 |= input.ReadInt32(ref result.defaultInt32_);
               break;
             }
             case 496: {
-              DefaultInt64 = input.ReadInt64();
+              result.hasDefaultInt64 |= input.ReadInt64(ref result.defaultInt64_);
               break;
             }
             case 504: {
-              DefaultUint32 = input.ReadUInt32();
+              result.hasDefaultUint32 |= input.ReadUInt32(ref result.defaultUint32_);
               break;
             }
             case 512: {
-              DefaultUint64 = input.ReadUInt64();
+              result.hasDefaultUint64 |= input.ReadUInt64(ref result.defaultUint64_);
               break;
             }
             case 520: {
-              DefaultSint32 = input.ReadSInt32();
+              result.hasDefaultSint32 |= input.ReadSInt32(ref result.defaultSint32_);
               break;
             }
             case 528: {
-              DefaultSint64 = input.ReadSInt64();
+              result.hasDefaultSint64 |= input.ReadSInt64(ref result.defaultSint64_);
               break;
             }
             case 541: {
-              DefaultFixed32 = input.ReadFixed32();
+              result.hasDefaultFixed32 |= input.ReadFixed32(ref result.defaultFixed32_);
               break;
             }
             case 545: {
-              DefaultFixed64 = input.ReadFixed64();
+              result.hasDefaultFixed64 |= input.ReadFixed64(ref result.defaultFixed64_);
               break;
             }
             case 557: {
-              DefaultSfixed32 = input.ReadSFixed32();
+              result.hasDefaultSfixed32 |= input.ReadSFixed32(ref result.defaultSfixed32_);
               break;
             }
             case 561: {
-              DefaultSfixed64 = input.ReadSFixed64();
+              result.hasDefaultSfixed64 |= input.ReadSFixed64(ref result.defaultSfixed64_);
               break;
             }
             case 573: {
-              DefaultFloat = input.ReadFloat();
+              result.hasDefaultFloat |= input.ReadFloat(ref result.defaultFloat_);
               break;
             }
             case 577: {
-              DefaultDouble = input.ReadDouble();
+              result.hasDefaultDouble |= input.ReadDouble(ref result.defaultDouble_);
               break;
             }
             case 584: {
-              DefaultBool = input.ReadBool();
+              result.hasDefaultBool |= input.ReadBool(ref result.defaultBool_);
               break;
             }
             case 594: {
-              DefaultString = input.ReadString();
+              result.hasDefaultString |= input.ReadString(ref result.defaultString_);
               break;
             }
             case 602: {
-              DefaultBytes = input.ReadBytes();
+              result.hasDefaultBytes |= input.ReadBytes(ref result.defaultBytes_);
               break;
             }
             case 648: {
-              int rawValue = input.ReadEnum();
-              if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedEnum), rawValue)) {
-              } else {
-                DefaultNestedEnum = (global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedEnum) rawValue;
+              object unknown;
+              if(input.ReadEnum(ref result.defaultNestedEnum_, out unknown)) {
+                result.hasDefaultNestedEnum = true;
+              } else if(unknown is int) {
               }
               break;
             }
             case 656: {
-              int rawValue = input.ReadEnum();
-              if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.TestProtos.ForeignEnumLite), rawValue)) {
-              } else {
-                DefaultForeignEnum = (global::Google.ProtocolBuffers.TestProtos.ForeignEnumLite) rawValue;
+              object unknown;
+              if(input.ReadEnum(ref result.defaultForeignEnum_, out unknown)) {
+                result.hasDefaultForeignEnum = true;
+              } else if(unknown is int) {
               }
               break;
             }
             case 664: {
-              int rawValue = input.ReadEnum();
-              if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.TestProtos.ImportEnumLite), rawValue)) {
-              } else {
-                DefaultImportEnum = (global::Google.ProtocolBuffers.TestProtos.ImportEnumLite) rawValue;
+              object unknown;
+              if(input.ReadEnum(ref result.defaultImportEnum_, out unknown)) {
+                result.hasDefaultImportEnum = true;
+              } else if(unknown is int) {
               }
               break;
             }
             case 674: {
-              DefaultStringPiece = input.ReadString();
+              result.hasDefaultStringPiece |= input.ReadString(ref result.defaultStringPiece_);
               break;
             }
             case 682: {
-              DefaultCord = input.ReadString();
+              result.hasDefaultCord |= input.ReadString(ref result.defaultCord_);
               break;
             }
           }
@@ -5747,11 +5730,11 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (pb::WireFormat.IsEndGroupTag(tag)) {
                 return this;
               }
-              ParseUnknownField(input, extensionRegistry, tag);
+              ParseUnknownField(input, extensionRegistry, tag, field_name);
               break;
             }
             case 8: {
-              C = input.ReadInt32();
+              result.hasC |= input.ReadInt32(ref result.c_);
               break;
             }
           }
@@ -6456,137 +6439,64 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (pb::WireFormat.IsEndGroupTag(tag)) {
                 return this;
               }
-              ParseUnknownField(input, extensionRegistry, tag);
+              ParseUnknownField(input, extensionRegistry, tag, field_name);
               break;
             }
             case 722: {
-              int length = input.ReadInt32();
-              int limit = input.PushLimit(length);
-              while (!input.ReachedLimit) {
-                AddPackedInt32(input.ReadInt32());
-              }
-              input.PopLimit(limit);
+              input.ReadPrimitiveArray(pbd::FieldType.Int32, tag, field_name, result.packedInt32_);
               break;
             }
             case 730: {
-              int length = input.ReadInt32();
-              int limit = input.PushLimit(length);
-              while (!input.ReachedLimit) {
-                AddPackedInt64(input.ReadInt64());
-              }
-              input.PopLimit(limit);
+              input.ReadPrimitiveArray(pbd::FieldType.Int64, tag, field_name, result.packedInt64_);
               break;
             }
             case 738: {
-              int length = input.ReadInt32();
-              int limit = input.PushLimit(length);
-              while (!input.ReachedLimit) {
-                AddPackedUint32(input.ReadUInt32());
-              }
-              input.PopLimit(limit);
+              input.ReadPrimitiveArray(pbd::FieldType.UInt32, tag, field_name, result.packedUint32_);
               break;
             }
             case 746: {
-              int length = input.ReadInt32();
-              int limit = input.PushLimit(length);
-              while (!input.ReachedLimit) {
-                AddPackedUint64(input.ReadUInt64());
-              }
-              input.PopLimit(limit);
+              input.ReadPrimitiveArray(pbd::FieldType.UInt64, tag, field_name, result.packedUint64_);
               break;
             }
             case 754: {
-              int length = input.ReadInt32();
-              int limit = input.PushLimit(length);
-              while (!input.ReachedLimit) {
-                AddPackedSint32(input.ReadSInt32());
-              }
-              input.PopLimit(limit);
+              input.ReadPrimitiveArray(pbd::FieldType.SInt32, tag, field_name, result.packedSint32_);
               break;
             }
             case 762: {
-              int length = input.ReadInt32();
-              int limit = input.PushLimit(length);
-              while (!input.ReachedLimit) {
-                AddPackedSint64(input.ReadSInt64());
-              }
-              input.PopLimit(limit);
+              input.ReadPrimitiveArray(pbd::FieldType.SInt64, tag, field_name, result.packedSint64_);
               break;
             }
             case 770: {
-              int length = input.ReadInt32();
-              int limit = input.PushLimit(length);
-              while (!input.ReachedLimit) {
-                AddPackedFixed32(input.ReadFixed32());
-              }
-              input.PopLimit(limit);
+              input.ReadPrimitiveArray(pbd::FieldType.Fixed32, tag, field_name, result.packedFixed32_);
               break;
             }
             case 778: {
-              int length = input.ReadInt32();
-              int limit = input.PushLimit(length);
-              while (!input.ReachedLimit) {
-                AddPackedFixed64(input.ReadFixed64());
-              }
-              input.PopLimit(limit);
+              input.ReadPrimitiveArray(pbd::FieldType.Fixed64, tag, field_name, result.packedFixed64_);
               break;
             }
             case 786: {
-              int length = input.ReadInt32();
-              int limit = input.PushLimit(length);
-              while (!input.ReachedLimit) {
-                AddPackedSfixed32(input.ReadSFixed32());
-              }
-              input.PopLimit(limit);
+              input.ReadPrimitiveArray(pbd::FieldType.SFixed32, tag, field_name, result.packedSfixed32_);
               break;
             }
             case 794: {
-              int length = input.ReadInt32();
-              int limit = input.PushLimit(length);
-              while (!input.ReachedLimit) {
-                AddPackedSfixed64(input.ReadSFixed64());
-              }
-              input.PopLimit(limit);
+              input.ReadPrimitiveArray(pbd::FieldType.SFixed64, tag, field_name, result.packedSfixed64_);
               break;
             }
             case 802: {
-              int length = input.ReadInt32();
-              int limit = input.PushLimit(length);
-              while (!input.ReachedLimit) {
-                AddPackedFloat(input.ReadFloat());
-              }
-              input.PopLimit(limit);
+              input.ReadPrimitiveArray(pbd::FieldType.Float, tag, field_name, result.packedFloat_);
               break;
             }
             case 810: {
-              int length = input.ReadInt32();
-              int limit = input.PushLimit(length);
-              while (!input.ReachedLimit) {
-                AddPackedDouble(input.ReadDouble());
-              }
-              input.PopLimit(limit);
+              input.ReadPrimitiveArray(pbd::FieldType.Double, tag, field_name, result.packedDouble_);
               break;
             }
             case 818: {
-              int length = input.ReadInt32();
-              int limit = input.PushLimit(length);
-              while (!input.ReachedLimit) {
-                AddPackedBool(input.ReadBool());
-              }
-              input.PopLimit(limit);
+              input.ReadPrimitiveArray(pbd::FieldType.Bool, tag, field_name, result.packedBool_);
               break;
             }
             case 826: {
-              int length = input.ReadInt32();
-              int oldLimit = input.PushLimit(length);
-              while (!input.ReachedLimit) {
-                int rawValue = input.ReadEnum();
-                if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.TestProtos.ForeignEnumLite), rawValue)) {
-                } else {
-                  AddPackedEnum((global::Google.ProtocolBuffers.TestProtos.ForeignEnumLite) rawValue);
-                }
-              }
-              input.PopLimit(oldLimit);
+              scg::ICollection<object> unknownItems;
+              input.ReadEnumArray<global::Google.ProtocolBuffers.TestProtos.ForeignEnumLite>(tag, field_name, result.packedEnum_, out unknownItems);
               break;
             }
           }
@@ -7152,7 +7062,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (pb::WireFormat.IsEndGroupTag(tag)) {
                 return this;
               }
-              ParseUnknownField(input, extensionRegistry, tag);
+              ParseUnknownField(input, extensionRegistry, tag, field_name);
               break;
             }
           }
@@ -7348,11 +7258,11 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (pb::WireFormat.IsEndGroupTag(tag)) {
                 return this;
               }
-              ParseUnknownField(input, extensionRegistry, tag);
+              ParseUnknownField(input, extensionRegistry, tag, field_name);
               break;
             }
             case 136: {
-              A = input.ReadInt32();
+              result.hasA |= input.ReadInt32(ref result.a_);
               break;
             }
           }
@@ -7566,11 +7476,11 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (pb::WireFormat.IsEndGroupTag(tag)) {
                 return this;
               }
-              ParseUnknownField(input, extensionRegistry, tag);
+              ParseUnknownField(input, extensionRegistry, tag, field_name);
               break;
             }
             case 376: {
-              A = input.ReadInt32();
+              result.hasA |= input.ReadInt32(ref result.a_);
               break;
             }
           }
@@ -7770,7 +7680,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (pb::WireFormat.IsEndGroupTag(tag)) {
                 return this;
               }
-              ParseUnknownField(input, extensionRegistry, tag);
+              ParseUnknownField(input, extensionRegistry, tag, field_name);
               break;
             }
           }
@@ -7946,7 +7856,7 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (pb::WireFormat.IsEndGroupTag(tag)) {
                 return this;
               }
-              ParseUnknownField(input, extensionRegistry, tag);
+              ParseUnknownField(input, extensionRegistry, tag, field_name);
               break;
             }
           }
@@ -8142,11 +8052,11 @@ namespace Google.ProtocolBuffers.TestProtos {
               if (pb::WireFormat.IsEndGroupTag(tag)) {
                 return this;
               }
-              ParseUnknownField(input, extensionRegistry, tag);
+              ParseUnknownField(input, extensionRegistry, tag, field_name);
               break;
             }
             case 8: {
-              DeprecatedField = input.ReadInt32();
+              result.hasDeprecatedField |= input.ReadInt32(ref result.deprecatedField_);
               break;
             }
           }

File diff suppressed because it is too large
+ 200 - 210
src/ProtocolBuffersLite.Test/TestProtos/UnitTestProtoFile.cs


Some files were not shown because too many files changed in this diff