소스 검색

Merge pull request #543 from jskeet/proto3-map

Proto3 map support for C#
Jon Skeet 10 년 전
부모
커밋
6b01539dfc
35개의 변경된 파일8878개의 추가작업 그리고 102개의 파일을 삭제
  1. 1 0
      cmake/libprotoc.cmake
  2. 2 0
      csharp/generate_protos.sh
  3. 6 3
      csharp/src/AddressBook/Addressbook.cs
  4. 354 0
      csharp/src/ProtocolBuffers.Test/Collections/MapFieldTest.cs
  5. 1 2
      csharp/src/ProtocolBuffers.Test/Collections/RepeatedFieldTest.cs
  6. 63 0
      csharp/src/ProtocolBuffers.Test/EqualityTester.cs
  7. 149 0
      csharp/src/ProtocolBuffers.Test/FieldCodecTest.cs
  8. 210 0
      csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs
  9. 6 4
      csharp/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj
  10. 6938 0
      csharp/src/ProtocolBuffers.Test/TestProtos/MapUnittestProto3.cs
  11. 2 1
      csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs
  12. 2 1
      csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportPublicProto3.cs
  13. 8 4
      csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs
  14. 70 35
      csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs
  15. 10 18
      csharp/src/ProtocolBuffers/CodedInputStream.cs
  16. 8 0
      csharp/src/ProtocolBuffers/CodedOutputStream.cs
  17. 433 0
      csharp/src/ProtocolBuffers/Collections/MapField.cs
  18. 1 1
      csharp/src/ProtocolBuffers/Collections/RepeatedField.cs
  19. 44 22
      csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
  20. 188 0
      csharp/src/ProtocolBuffers/FieldCodec.cs
  21. 2 0
      csharp/src/ProtocolBuffers/ProtocolBuffers.csproj
  22. 2 0
      src/Makefile.am
  23. 6 0
      src/google/protobuf/compiler/csharp/csharp_enum_field.cc
  24. 1 0
      src/google/protobuf/compiler/csharp/csharp_enum_field.h
  25. 13 3
      src/google/protobuf/compiler/csharp/csharp_field_base.cc
  26. 2 0
      src/google/protobuf/compiler/csharp/csharp_field_base.h
  27. 6 1
      src/google/protobuf/compiler/csharp/csharp_helpers.cc
  28. 141 0
      src/google/protobuf/compiler/csharp/csharp_map_field.cc
  29. 71 0
      src/google/protobuf/compiler/csharp/csharp_map_field.h
  30. 3 6
      src/google/protobuf/compiler/csharp/csharp_message.cc
  31. 6 0
      src/google/protobuf/compiler/csharp/csharp_message_field.cc
  32. 1 0
      src/google/protobuf/compiler/csharp/csharp_message_field.h
  33. 7 1
      src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
  34. 1 0
      src/google/protobuf/compiler/csharp/csharp_primitive_field.h
  35. 120 0
      src/google/protobuf/map_unittest_proto3.proto

+ 1 - 0
cmake/libprotoc.cmake

@@ -19,6 +19,7 @@ set(libprotoc_files
   ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_field_base.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_generator.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_helpers.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_map_field.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_message.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_message_field.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc

+ 2 - 0
csharp/generate_protos.sh

@@ -43,10 +43,12 @@ $PROTOC -Isrc --csharp_out=csharp/src/ProtocolBuffers/DescriptorProtos \
 rm src/google/protobuf/descriptor_proto_file.proto
 
 $PROTOC -Isrc --csharp_out=csharp/src/ProtocolBuffers.Test/TestProtos \
+    src/google/protobuf/map_unittest_proto3.proto \
     src/google/protobuf/unittest_proto3.proto \
     src/google/protobuf/unittest_import_proto3.proto \
     src/google/protobuf/unittest_import_public_proto3.proto
 
+
 $PROTOC -Icsharp/protos/extest --csharp_out=csharp/src/ProtocolBuffers.Test/TestProtos \
     csharp/protos/extest/unittest_issues.proto
 

+ 6 - 3
csharp/src/AddressBook/Addressbook.cs

@@ -155,7 +155,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
       if (Id != 0) hash ^= Id.GetHashCode();
       if (Email.Length != 0) hash ^= Email.GetHashCode();
@@ -200,6 +200,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       }
       return size;
     }
+
     public void MergeFrom(Person other) {
       if (other == null) {
         return;
@@ -329,7 +330,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
         }
 
         public override int GetHashCode() {
-          int hash = 0;
+          int hash = 1;
           if (Number.Length != 0) hash ^= Number.GetHashCode();
           if (Type != global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneType.HOME) hash ^= Type.GetHashCode();
           return hash;
@@ -356,6 +357,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
           }
           return size;
         }
+
         public void MergeFrom(PhoneNumber other) {
           if (other == null) {
             return;
@@ -456,7 +458,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       hash ^= person_.GetHashCode();
       return hash;
     }
@@ -477,6 +479,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       }
       return size;
     }
+
     public void MergeFrom(AddressBook other) {
       if (other == null) {
         return;

+ 354 - 0
csharp/src/ProtocolBuffers.Test/Collections/MapFieldTest.cs

@@ -0,0 +1,354 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+
+namespace Google.Protobuf.Collections
+{
+    /// <summary>
+    /// Tests for MapField which aren't reliant on the encoded format -
+    /// tests for serialization/deserialization are part of GeneratedMessageTest.
+    /// </summary>
+    public class MapFieldTest
+    {
+        // Protobuf-specific tests
+        [Test]
+        public void Freeze_FreezesMessages()
+        {
+            var message = new ForeignMessage { C = 20 };
+            var map = new MapField<string, ForeignMessage> { { "x", message } };
+            map.Freeze();
+            Assert.IsTrue(message.IsFrozen);
+        }
+
+        [Test]
+        public void Freeze_PreventsMutation()
+        {
+            var map = new MapField<string, string>();
+            map.Freeze();
+            Assert.IsTrue(map.IsFrozen);
+            Assert.IsTrue(map.IsReadOnly);
+            ICollection<KeyValuePair<string, string>> collection = map;
+            Assert.Throws<InvalidOperationException>(() => map["x"] = "y");
+            Assert.Throws<InvalidOperationException>(() => map.Add("x", "y"));
+            Assert.Throws<InvalidOperationException>(() => map.Remove("x"));
+            Assert.Throws<InvalidOperationException>(() => map.Clear());
+            Assert.Throws<InvalidOperationException>(() => collection.Add(NewKeyValuePair("x", "y")));
+            Assert.Throws<InvalidOperationException>(() => collection.Remove(NewKeyValuePair("x", "y")));
+        }
+
+        [Test]
+        public void Clone_ReturnsNonFrozen()
+        {
+            var map = new MapField<string, string>();
+            map.Freeze();
+            var clone = map.Clone();
+            clone.Add("x", "y");
+        }
+
+        [Test]
+        public void Clone_ClonesMessages()
+        {
+            var message = new ForeignMessage { C = 20 };
+            var map = new MapField<string, ForeignMessage> { { "x", message } };
+            var clone = map.Clone();
+            map["x"].C = 30;
+            Assert.AreEqual(20, clone["x"].C);
+        }
+
+        [Test]
+        public void Add_ForbidsNullKeys()
+        {
+            var map = new MapField<string, ForeignMessage>();
+            Assert.Throws<ArgumentNullException>(() => map.Add(null, new ForeignMessage()));
+        }
+
+        [Test]
+        public void Add_AcceptsNullMessageValues()
+        {
+            var map = new MapField<string, ForeignMessage>();
+            map.Add("missing", null);
+            Assert.IsNull(map["missing"]);
+        }
+
+        [Test]
+        public void Add_ForbidsNullStringValues()
+        {
+            var map = new MapField<string, string>();
+            Assert.Throws<ArgumentNullException>(() => map.Add("missing", null));
+        }
+
+        [Test]
+        public void Add_ForbidsNullByteStringValues()
+        {
+            var map = new MapField<string, ByteString>();
+            Assert.Throws<ArgumentNullException>(() => map.Add("missing", null));
+        }
+
+        [Test]
+        public void Indexer_ForbidsNullKeys()
+        {
+            var map = new MapField<string, ForeignMessage>();
+            Assert.Throws<ArgumentNullException>(() => map[null] = new ForeignMessage());
+        }
+
+        [Test]
+        public void Indexer_AcceptsNullMessageValues()
+        {
+            var map = new MapField<string, ForeignMessage>();
+            map["missing"] = null;
+            Assert.IsNull(map["missing"]);
+        }
+
+        [Test]
+        public void Indexer_ForbidsNullStringValues()
+        {
+            var map = new MapField<string, string>();
+            Assert.Throws<ArgumentNullException>(() => map["missing"] = null);
+        }
+
+        [Test]
+        public void Indexer_ForbidsNullByteStringValues()
+        {
+            var map = new MapField<string, ByteString>();
+            Assert.Throws<ArgumentNullException>(() => map["missing"] = null);
+        }
+
+        [Test]
+        public void AddPreservesInsertionOrder()
+        {
+            var map = new MapField<string, string>();
+            map.Add("a", "v1");
+            map.Add("b", "v2");
+            map.Add("c", "v3");
+            map.Remove("b");
+            map.Add("d", "v4");
+            CollectionAssert.AreEqual(new[] { "a", "c", "d" }, map.Keys);
+            CollectionAssert.AreEqual(new[] { "v1", "v3", "v4" }, map.Values);
+        }
+
+        [Test]
+        public void EqualityIsOrderInsensitive()
+        {
+            var map1 = new MapField<string, string>();
+            map1.Add("a", "v1");
+            map1.Add("b", "v2");
+
+            var map2 = new MapField<string, string>();
+            map2.Add("b", "v2");
+            map2.Add("a", "v1");
+
+            EqualityTester.AssertEquality(map1, map2);
+        }
+
+        [Test]
+        public void EqualityIsKeySensitive()
+        {
+            var map1 = new MapField<string, string>();
+            map1.Add("first key", "v1");
+            map1.Add("second key", "v2");
+
+            var map2 = new MapField<string, string>();
+            map2.Add("third key", "v1");
+            map2.Add("fourth key", "v2");
+
+            EqualityTester.AssertInequality(map1, map2);
+        }
+
+        [Test]
+        public void EqualityIsValueSensitive()
+        {
+            // Note: Without some care, it's a little easier than one might
+            // hope to see hash collisions, but only in some environments...
+            var map1 = new MapField<string, string>();
+            map1.Add("a", "first value");
+            map1.Add("b", "second value");
+
+            var map2 = new MapField<string, string>();
+            map2.Add("a", "third value");
+            map2.Add("b", "fourth value");
+
+            EqualityTester.AssertInequality(map1, map2);
+        }
+
+        [Test]
+        public void EqualityHandlesNullValues()
+        {
+            var map1 = new MapField<string, ForeignMessage>();
+            map1.Add("a", new ForeignMessage { C = 10 });
+            map1.Add("b", null);
+
+            var map2 = new MapField<string, ForeignMessage>();
+            map2.Add("a", new ForeignMessage { C = 10 });
+            map2.Add("b", null);
+
+            EqualityTester.AssertEquality(map1, map2);
+            // Check the null value isn't ignored entirely...
+            Assert.IsTrue(map1.Remove("b"));
+            EqualityTester.AssertInequality(map1, map2);
+            map1.Add("b", new ForeignMessage());
+            EqualityTester.AssertInequality(map1, map2);
+            map1["b"] = null;
+            EqualityTester.AssertEquality(map1, map2);
+        }
+
+        [Test]
+        public void Add_Dictionary()
+        {
+            var map1 = new MapField<string, string>
+            {
+                { "x", "y" },
+                { "a", "b" }
+            };
+            var map2 = new MapField<string, string>
+            {
+                { "before", "" },
+                map1,
+                { "after", "" }
+            };
+            var expected = new MapField<string, string>
+            {
+                { "before", "" },
+                { "x", "y" },
+                { "a", "b" },
+                { "after", "" }
+            };
+            Assert.AreEqual(expected, map2);
+            CollectionAssert.AreEqual(new[] { "before", "x", "a", "after" }, map2.Keys);
+        }
+
+        // General IDictionary<TKey, TValue> behavior tests
+        [Test]
+        public void Add_KeyAlreadyExists()
+        {
+            var map = new MapField<string, string>();
+            map.Add("foo", "bar");
+            Assert.Throws<ArgumentException>(() => map.Add("foo", "baz"));
+        }
+
+        [Test]
+        public void Add_Pair()
+        {
+            var map = new MapField<string, string>();
+            ICollection<KeyValuePair<string, string>> collection = map;
+            collection.Add(NewKeyValuePair("x", "y"));
+            Assert.AreEqual("y", map["x"]);
+            Assert.Throws<ArgumentException>(() => collection.Add(NewKeyValuePair("x", "z")));
+        }
+
+        [Test]
+        public void Contains_Pair()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            ICollection<KeyValuePair<string, string>> collection = map;
+            Assert.IsTrue(collection.Contains(NewKeyValuePair("x", "y")));
+            Assert.IsFalse(collection.Contains(NewKeyValuePair("x", "z")));
+            Assert.IsFalse(collection.Contains(NewKeyValuePair("z", "y")));
+        }
+
+        [Test]
+        public void Remove_Key()
+        {
+            var map = new MapField<string, string>();
+            map.Add("foo", "bar");
+            Assert.AreEqual(1, map.Count);
+            Assert.IsFalse(map.Remove("missing"));
+            Assert.AreEqual(1, map.Count);
+            Assert.IsTrue(map.Remove("foo"));
+            Assert.AreEqual(0, map.Count);           
+        }
+
+        [Test]
+        public void Remove_Pair()
+        {
+            var map = new MapField<string, string>();
+            map.Add("foo", "bar");
+            ICollection<KeyValuePair<string, string>> collection = map;
+            Assert.AreEqual(1, map.Count);
+            Assert.IsFalse(collection.Remove(NewKeyValuePair("wrong key", "bar")));
+            Assert.AreEqual(1, map.Count);
+            Assert.IsFalse(collection.Remove(NewKeyValuePair("foo", "wrong value")));
+            Assert.AreEqual(1, map.Count);
+            Assert.IsTrue(collection.Remove(NewKeyValuePair("foo", "bar")));
+            Assert.AreEqual(0, map.Count);
+            Assert.Throws<ArgumentException>(() => collection.Remove(new KeyValuePair<string, string>(null, "")));
+        }
+
+        [Test]
+        public void CopyTo_Pair()
+        {
+            var map = new MapField<string, string>();
+            map.Add("foo", "bar");
+            ICollection<KeyValuePair<string, string>> collection = map;
+            KeyValuePair<string, string>[] array = new KeyValuePair<string, string>[3];
+            collection.CopyTo(array, 1);
+            Assert.AreEqual(NewKeyValuePair("foo", "bar"), array[1]);
+        }
+
+        [Test]
+        public void Clear()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            Assert.AreEqual(1, map.Count);
+            map.Clear();
+            Assert.AreEqual(0, map.Count);
+            map.Add("x", "y");
+            Assert.AreEqual(1, map.Count);
+        }
+
+        [Test]
+        public void Indexer_Get()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            Assert.AreEqual("y", map["x"]);
+            Assert.Throws<KeyNotFoundException>(() => { var ignored = map["z"]; });
+        }
+
+        [Test]
+        public void Indexer_Set()
+        {
+            var map = new MapField<string, string>();
+            map["x"] = "y";
+            Assert.AreEqual("y", map["x"]);
+            map["x"] = "z"; // This won't throw, unlike Add.
+            Assert.AreEqual("z", map["x"]);
+        }
+
+        private static KeyValuePair<TKey, TValue> NewKeyValuePair<TKey, TValue>(TKey key, TValue value)
+        {
+            return new KeyValuePair<TKey, TValue>(key, value);
+        }
+    }
+}

+ 1 - 2
csharp/src/ProtocolBuffers.Test/RepeatedFieldTest.cs → csharp/src/ProtocolBuffers.Test/Collections/RepeatedFieldTest.cs

@@ -1,10 +1,9 @@
 using System;
 using System.Collections.Generic;
-using Google.Protobuf.Collections;
 using Google.Protobuf.TestProtos;
 using NUnit.Framework;
 
-namespace Google.Protobuf
+namespace Google.Protobuf.Collections
 {
     public class RepeatedFieldTest
     {

+ 63 - 0
csharp/src/ProtocolBuffers.Test/EqualityTester.cs

@@ -0,0 +1,63 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using NUnit.Framework;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Helper methods when testing equality. NUnit's Assert.AreEqual and
+    /// Assert.AreNotEqual methods try to be clever with collections, which can
+    /// be annoying...
+    /// </summary>
+    internal static class EqualityTester
+    {
+        public static void AssertEquality<T>(T first, T second) where T : IEquatable<T>
+        {
+            Assert.IsTrue(first.Equals(second));
+            Assert.AreEqual(first.GetHashCode(), second.GetHashCode());
+        }
+
+        public static void AssertInequality<T>(T first, T second) where T : IEquatable<T>
+        {
+            Assert.IsFalse(first.Equals(second));
+            // While this isn't a requirement, the chances of this test failing due to
+            // coincidence rather than a bug are very small.
+            Assert.AreNotEqual(first.GetHashCode(), second.GetHashCode());
+        }
+    }
+}

+ 149 - 0
csharp/src/ProtocolBuffers.Test/FieldCodecTest.cs

@@ -0,0 +1,149 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System.Collections.Generic;
+using System.IO;
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+
+namespace Google.Protobuf
+{
+    public class FieldCodecTest
+    {
+        private static readonly List<ICodecTestData> Codecs = new List<ICodecTestData>
+        {
+            new FieldCodecTestData<bool>(FieldCodec.ForBool(100), true, "Bool"),
+            new FieldCodecTestData<string>(FieldCodec.ForString(100), "sample", "String"),
+            new FieldCodecTestData<ByteString>(FieldCodec.ForBytes(100), ByteString.CopyFrom(1, 2, 3), "Bytes"),
+            new FieldCodecTestData<int>(FieldCodec.ForInt32(100), -1000, "Int32"),
+            new FieldCodecTestData<int>(FieldCodec.ForSInt32(100), -1000, "SInt32"),
+            new FieldCodecTestData<int>(FieldCodec.ForSFixed32(100), -1000, "SFixed32"),
+            new FieldCodecTestData<uint>(FieldCodec.ForUInt32(100), 1234, "UInt32"),
+            new FieldCodecTestData<uint>(FieldCodec.ForFixed32(100), 1234, "Fixed32"),
+            new FieldCodecTestData<long>(FieldCodec.ForInt64(100), -1000, "Int64"),
+            new FieldCodecTestData<long>(FieldCodec.ForSInt64(100), -1000, "SInt64"),
+            new FieldCodecTestData<long>(FieldCodec.ForSFixed64(100), -1000, "SFixed64"),
+            new FieldCodecTestData<ulong>(FieldCodec.ForUInt64(100), 1234, "UInt64"),
+            new FieldCodecTestData<ulong>(FieldCodec.ForFixed64(100), 1234, "Fixed64"),
+            new FieldCodecTestData<float>(FieldCodec.ForFloat(100), 1234.5f, "Float"),
+            new FieldCodecTestData<double>(FieldCodec.ForDouble(100), 1234567890.5d, "Double"),
+            new FieldCodecTestData<ForeignEnum>(
+                FieldCodec.ForEnum(100, t => (int) t, t => (ForeignEnum) t), ForeignEnum.FOREIGN_BAZ, "Enum"),
+            new FieldCodecTestData<ForeignMessage>(
+                FieldCodec.ForMessage(100, ForeignMessage.Parser), new ForeignMessage { C = 10 }, "Message"),
+        };
+
+        [Test, TestCaseSource("Codecs")]
+        public void RoundTrip(ICodecTestData codec)
+        {
+            codec.TestRoundTrip();
+        }
+
+        [Test, TestCaseSource("Codecs")]
+        public void CalculateSize(ICodecTestData codec)
+        {
+            codec.TestCalculateSize();
+        }
+
+        [Test, TestCaseSource("Codecs")]
+        public void DefaultValue(ICodecTestData codec)
+        {
+            codec.TestDefaultValue();
+        }
+
+        public interface ICodecTestData
+        {
+            void TestRoundTrip();
+            void TestCalculateSize();
+            void TestDefaultValue();
+        }
+
+        public class FieldCodecTestData<T> : ICodecTestData
+        {
+            private readonly FieldCodec<T> codec;
+            private readonly T sampleValue;
+            private readonly string name;
+
+            public FieldCodecTestData(FieldCodec<T> codec, T sampleValue, string name)
+            {
+                this.codec = codec;
+                this.sampleValue = sampleValue;
+                this.name = name;
+            }
+
+            public void TestRoundTrip()
+            {
+                var stream = new MemoryStream();
+                var codedOutput = CodedOutputStream.CreateInstance(stream);
+                codec.Write(codedOutput, sampleValue);
+                codedOutput.Flush();
+                stream.Position = 0;
+                var codedInput = CodedInputStream.CreateInstance(stream);
+                uint tag;
+                Assert.IsTrue(codedInput.ReadTag(out tag));
+                Assert.AreEqual(codec.Tag, tag);
+                Assert.AreEqual(sampleValue, codec.Read(codedInput));
+                Assert.IsTrue(codedInput.IsAtEnd);
+            }
+
+            public void TestCalculateSize()
+            {
+                var stream = new MemoryStream();
+                var codedOutput = CodedOutputStream.CreateInstance(stream);
+                codec.Write(codedOutput, sampleValue);
+                codedOutput.Flush();
+                Assert.AreEqual(stream.Position, codec.CalculateSize(sampleValue));
+            }
+
+            public void TestDefaultValue()
+            {
+                var stream = new MemoryStream();
+                var codedOutput = CodedOutputStream.CreateInstance(stream);
+                codec.Write(codedOutput, codec.DefaultValue);
+                codedOutput.Flush();
+                Assert.AreEqual(0, stream.Position);
+                Assert.AreEqual(0, codec.CalculateSize(codec.DefaultValue));
+                if (typeof(T).IsValueType)
+                {
+                    Assert.AreEqual(default(T), codec.DefaultValue);
+                }
+            }
+
+            public string Description { get { return name; } }
+
+            public override string ToString()
+            {
+                return name;
+            }
+        }
+    }
+}

+ 210 - 0
csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs

@@ -1,4 +1,5 @@
 using System;
+using System.IO;
 using Google.Protobuf.TestProtos;
 using NUnit.Framework;
 
@@ -9,6 +10,15 @@ namespace Google.Protobuf
     /// </summary>
     public class GeneratedMessageTest
     {
+        [Test]
+        public void EmptyMessageFieldDistinctFromMissingMessageField()
+        {
+            // This demonstrates what we're really interested in...
+            var message1 = new TestAllTypes { SingleForeignMessage = new ForeignMessage() };
+            var message2 = new TestAllTypes(); // SingleForeignMessage is null
+            EqualityTester.AssertInequality(message1, message2);
+        }
+
         [Test]
         public void DefaultValues()
         {
@@ -146,6 +156,206 @@ namespace Google.Protobuf
             Assert.AreEqual(message, parsed);
         }
 
+        // Note that not every map within map_unittest_proto3 is used. They all go through very
+        // similar code paths. The fact that all maps are present is validation that we have codecs
+        // for every type.
+        [Test]
+        public void RoundTrip_Maps()
+        {
+            var message = new TestMap
+            {
+                MapBoolBool = {
+                    { false, true },
+                    { true, false }
+                },
+                MapInt32Bytes = {
+                    { 5, ByteString.CopyFrom(6, 7, 8) },
+                    { 25, ByteString.CopyFrom(1, 2, 3, 4, 5) },
+                    { 10, ByteString.Empty }
+                },
+                MapInt32ForeignMessage = {
+                    { 0, new ForeignMessage { C = 10 } },
+                    { 5, null },
+                },
+                MapInt32Enum = {
+                    { 1, MapEnum.MAP_ENUM_BAR },
+                    { 2000, MapEnum.MAP_ENUM_FOO }
+                }
+            };
+
+            byte[] bytes = message.ToByteArray();
+            TestMap parsed = TestMap.Parser.ParseFrom(bytes);
+            Assert.AreEqual(message, parsed);
+        }
+
+        [Test]
+        public void MapWithEmptyEntry()
+        {
+            var message = new TestMap
+            {
+                MapInt32Bytes = { { 0, ByteString.Empty } }
+            };
+
+            byte[] bytes = message.ToByteArray();
+            Assert.AreEqual(2, bytes.Length); // Tag for field entry (1 byte), length of entry (0; 1 byte)
+
+            var parsed = TestMap.Parser.ParseFrom(bytes);
+            Assert.AreEqual(1, parsed.MapInt32Bytes.Count);
+            Assert.AreEqual(ByteString.Empty, parsed.MapInt32Bytes[0]);
+        }
+        
+        [Test]
+        public void MapWithOnlyValue()
+        {
+            // Hand-craft the stream to contain a single entry with just a value.
+            var memoryStream = new MemoryStream();
+            var output = CodedOutputStream.CreateInstance(memoryStream);
+            output.WriteTag(TestMap.MapInt32ForeignMessageFieldNumber, WireFormat.WireType.LengthDelimited);
+            var nestedMessage = new ForeignMessage { C = 20 };
+            // Size of the entry (tag, size written by WriteMessage, data written by WriteMessage)
+            output.WriteRawVarint32((uint)(nestedMessage.CalculateSize() + 3));
+            output.WriteTag(2, WireFormat.WireType.LengthDelimited);
+            output.WriteMessage(nestedMessage);
+            output.Flush();
+
+            var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
+            Assert.AreEqual(nestedMessage, parsed.MapInt32ForeignMessage[0]);
+        }
+
+        [Test]
+        public void MapIgnoresExtraFieldsWithinEntryMessages()
+        {
+            // Hand-craft the stream to contain a single entry with three fields
+            var memoryStream = new MemoryStream();
+            var output = CodedOutputStream.CreateInstance(memoryStream);
+
+            output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
+
+            var key = 10; // Field 1 
+            var value = 20; // Field 2
+            var extra = 30; // Field 3
+
+            // Each field can be represented in a single byte, with a single byte tag.
+            // Total message size: 6 bytes.
+            output.WriteRawVarint32(6);
+            output.WriteTag(1, WireFormat.WireType.Varint);
+            output.WriteInt32(key);
+            output.WriteTag(2, WireFormat.WireType.Varint);
+            output.WriteInt32(value);
+            output.WriteTag(3, WireFormat.WireType.Varint);
+            output.WriteInt32(extra);
+            output.Flush();
+
+            var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
+            Assert.AreEqual(value, parsed.MapInt32Int32[key]);
+        }
+
+        [Test]
+        public void MapFieldOrderIsIrrelevant()
+        {
+            var memoryStream = new MemoryStream();
+            var output = CodedOutputStream.CreateInstance(memoryStream);
+
+            output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
+
+            var key = 10;
+            var value = 20;
+
+            // Each field can be represented in a single byte, with a single byte tag.
+            // Total message size: 4 bytes.
+            output.WriteRawVarint32(4);
+            output.WriteTag(2, WireFormat.WireType.Varint);
+            output.WriteInt32(value);
+            output.WriteTag(1, WireFormat.WireType.Varint);
+            output.WriteInt32(key);
+            output.Flush();
+
+            var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
+            Assert.AreEqual(value, parsed.MapInt32Int32[key]);
+        }
+
+        [Test]
+        public void MapNonContiguousEntries()
+        {
+            var memoryStream = new MemoryStream();
+            var output = CodedOutputStream.CreateInstance(memoryStream);
+
+            // Message structure:
+            // Entry for MapInt32Int32
+            // Entry for MapStringString
+            // Entry for MapInt32Int32
+
+            // First entry
+            var key1 = 10;
+            var value1 = 20;
+            output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
+            output.WriteRawVarint32(4);
+            output.WriteTag(1, WireFormat.WireType.Varint);
+            output.WriteInt32(key1);
+            output.WriteTag(2, WireFormat.WireType.Varint);
+            output.WriteInt32(value1);
+
+            // Second entry
+            var key2 = "a";
+            var value2 = "b";
+            output.WriteTag(TestMap.MapStringStringFieldNumber, WireFormat.WireType.LengthDelimited);
+            output.WriteRawVarint32(6); // 3 bytes per entry: tag, size, character
+            output.WriteTag(1, WireFormat.WireType.LengthDelimited);
+            output.WriteString(key2);
+            output.WriteTag(2, WireFormat.WireType.LengthDelimited);
+            output.WriteString(value2);
+
+            // Third entry
+            var key3 = 15;
+            var value3 = 25;
+            output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
+            output.WriteRawVarint32(4);
+            output.WriteTag(1, WireFormat.WireType.Varint);
+            output.WriteInt32(key3);
+            output.WriteTag(2, WireFormat.WireType.Varint);
+            output.WriteInt32(value3);
+
+            output.Flush();
+            var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
+            var expected = new TestMap
+            {
+                MapInt32Int32 = { { key1, value1 }, { key3, value3 } },
+                MapStringString = { { key2, value2 } }
+            };
+            Assert.AreEqual(expected, parsed);
+        }
+
+        [Test]
+        public void DuplicateKeys_LastEntryWins()
+        {
+            var memoryStream = new MemoryStream();
+            var output = CodedOutputStream.CreateInstance(memoryStream);
+
+            var key = 10;
+            var value1 = 20;
+            var value2 = 30;
+
+            // First entry
+            output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
+            output.WriteRawVarint32(4);
+            output.WriteTag(1, WireFormat.WireType.Varint);
+            output.WriteInt32(key);
+            output.WriteTag(2, WireFormat.WireType.Varint);
+            output.WriteInt32(value1);
+
+            // Second entry - same key, different value
+            output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
+            output.WriteRawVarint32(4);
+            output.WriteTag(1, WireFormat.WireType.Varint);
+            output.WriteInt32(key);
+            output.WriteTag(2, WireFormat.WireType.Varint);
+            output.WriteInt32(value2);
+            output.Flush();
+
+            var parsed = TestMap.Parser.ParseFrom(memoryStream.ToArray());
+            Assert.AreEqual(value2, parsed.MapInt32Int32[key]);
+        }
+
         [Test]
         public void CloneSingleNonMessageValues()
         {

+ 6 - 4
csharp/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj

@@ -74,8 +74,12 @@
     <Compile Include="ByteStringTest.cs" />
     <Compile Include="CodedInputStreamTest.cs" />
     <Compile Include="CodedOutputStreamTest.cs" />
+    <Compile Include="EqualityTester.cs" />
+    <Compile Include="FieldCodecTest.cs" />
     <Compile Include="GeneratedMessageTest.cs" />
-    <Compile Include="RepeatedFieldTest.cs" />
+    <Compile Include="Collections\MapFieldTest.cs" />
+    <Compile Include="Collections\RepeatedFieldTest.cs" />
+    <Compile Include="TestProtos\MapUnittestProto3.cs" />
     <Compile Include="TestProtos\UnittestImportProto3.cs" />
     <Compile Include="TestProtos\UnittestImportPublicProto3.cs" />
     <Compile Include="TestProtos\UnittestIssues.cs" />
@@ -99,9 +103,7 @@
   <ItemGroup>
     <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
   </ItemGroup>
-  <ItemGroup>
-    <Folder Include="Collections\" />
-  </ItemGroup>
+  <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.

+ 6938 - 0
csharp/src/ProtocolBuffers.Test/TestProtos/MapUnittestProto3.cs

@@ -0,0 +1,6938 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/map_unittest_proto3.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbd = global::Google.Protobuf.Descriptors;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.TestProtos {
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class MapUnittestProto3 {
+
+    #region Static variables
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap> internal__static_protobuf_unittest_TestMap__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapInt32Int32Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32Int32Entry> internal__static_protobuf_unittest_TestMap_MapInt32Int32Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapInt64Int64Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt64Int64Entry> internal__static_protobuf_unittest_TestMap_MapInt64Int64Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapUint32Uint32Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapUint32Uint32Entry> internal__static_protobuf_unittest_TestMap_MapUint32Uint32Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapUint64Uint64Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapUint64Uint64Entry> internal__static_protobuf_unittest_TestMap_MapUint64Uint64Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapSint32Sint32Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapSint32Sint32Entry> internal__static_protobuf_unittest_TestMap_MapSint32Sint32Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapSint64Sint64Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapSint64Sint64Entry> internal__static_protobuf_unittest_TestMap_MapSint64Sint64Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapFixed32Fixed32Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapFixed32Fixed32Entry> internal__static_protobuf_unittest_TestMap_MapFixed32Fixed32Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapFixed64Fixed64Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapFixed64Fixed64Entry> internal__static_protobuf_unittest_TestMap_MapFixed64Fixed64Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapSfixed32Sfixed32Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapSfixed32Sfixed32Entry> internal__static_protobuf_unittest_TestMap_MapSfixed32Sfixed32Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapSfixed64Sfixed64Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapSfixed64Sfixed64Entry> internal__static_protobuf_unittest_TestMap_MapSfixed64Sfixed64Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapInt32FloatEntry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32FloatEntry> internal__static_protobuf_unittest_TestMap_MapInt32FloatEntry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapInt32DoubleEntry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32DoubleEntry> internal__static_protobuf_unittest_TestMap_MapInt32DoubleEntry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapBoolBoolEntry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapBoolBoolEntry> internal__static_protobuf_unittest_TestMap_MapBoolBoolEntry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapStringStringEntry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapStringStringEntry> internal__static_protobuf_unittest_TestMap_MapStringStringEntry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapInt32BytesEntry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32BytesEntry> internal__static_protobuf_unittest_TestMap_MapInt32BytesEntry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapInt32EnumEntry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32EnumEntry> internal__static_protobuf_unittest_TestMap_MapInt32EnumEntry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMap_MapInt32ForeignMessageEntry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32ForeignMessageEntry> internal__static_protobuf_unittest_TestMap_MapInt32ForeignMessageEntry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMapSubmessage__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMapSubmessage> internal__static_protobuf_unittest_TestMapSubmessage__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMessageMap__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMessageMap> internal__static_protobuf_unittest_TestMessageMap__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMessageMap_MapInt32MessageEntry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMessageMap.Types.MapInt32MessageEntry> internal__static_protobuf_unittest_TestMessageMap_MapInt32MessageEntry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestSameTypeMap__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestSameTypeMap> internal__static_protobuf_unittest_TestSameTypeMap__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestSameTypeMap_Map1Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestSameTypeMap.Types.Map1Entry> internal__static_protobuf_unittest_TestSameTypeMap_Map1Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestSameTypeMap_Map2Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestSameTypeMap.Types.Map2Entry> internal__static_protobuf_unittest_TestSameTypeMap_Map2Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap> internal__static_protobuf_unittest_TestArenaMap__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapInt32Int32Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32Int32Entry> internal__static_protobuf_unittest_TestArenaMap_MapInt32Int32Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapInt64Int64Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt64Int64Entry> internal__static_protobuf_unittest_TestArenaMap_MapInt64Int64Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapUint32Uint32Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapUint32Uint32Entry> internal__static_protobuf_unittest_TestArenaMap_MapUint32Uint32Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapUint64Uint64Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapUint64Uint64Entry> internal__static_protobuf_unittest_TestArenaMap_MapUint64Uint64Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapSint32Sint32Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapSint32Sint32Entry> internal__static_protobuf_unittest_TestArenaMap_MapSint32Sint32Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapSint64Sint64Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapSint64Sint64Entry> internal__static_protobuf_unittest_TestArenaMap_MapSint64Sint64Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapFixed32Fixed32Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapFixed32Fixed32Entry> internal__static_protobuf_unittest_TestArenaMap_MapFixed32Fixed32Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapFixed64Fixed64Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapFixed64Fixed64Entry> internal__static_protobuf_unittest_TestArenaMap_MapFixed64Fixed64Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapSfixed32Sfixed32Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapSfixed32Sfixed32Entry> internal__static_protobuf_unittest_TestArenaMap_MapSfixed32Sfixed32Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapSfixed64Sfixed64Entry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapSfixed64Sfixed64Entry> internal__static_protobuf_unittest_TestArenaMap_MapSfixed64Sfixed64Entry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapInt32FloatEntry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32FloatEntry> internal__static_protobuf_unittest_TestArenaMap_MapInt32FloatEntry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapInt32DoubleEntry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32DoubleEntry> internal__static_protobuf_unittest_TestArenaMap_MapInt32DoubleEntry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapBoolBoolEntry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapBoolBoolEntry> internal__static_protobuf_unittest_TestArenaMap_MapBoolBoolEntry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapInt32EnumEntry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32EnumEntry> internal__static_protobuf_unittest_TestArenaMap_MapInt32EnumEntry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestArenaMap_MapInt32ForeignMessageEntry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32ForeignMessageEntry> internal__static_protobuf_unittest_TestArenaMap_MapInt32ForeignMessageEntry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_MessageContainingEnumCalledType__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType> internal__static_protobuf_unittest_MessageContainingEnumCalledType__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_MessageContainingEnumCalledType_TypeEntry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Types.TypeEntry> internal__static_protobuf_unittest_MessageContainingEnumCalledType_TypeEntry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_MessageContainingMapCalledEntry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry> internal__static_protobuf_unittest_MessageContainingMapCalledEntry__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_MessageContainingMapCalledEntry_EntryEntry__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry.Types.EntryEntry> internal__static_protobuf_unittest_MessageContainingMapCalledEntry_EntryEntry__FieldAccessorTable;
+    #endregion
+    #region Descriptor
+    public static pbd::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbd::FileDescriptor descriptor;
+
+    static MapUnittestProto3() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "Cilnb29nbGUvcHJvdG9idWYvbWFwX3VuaXR0ZXN0X3Byb3RvMy5wcm90bxIR", 
+            "cHJvdG9idWZfdW5pdHRlc3QaJWdvb2dsZS9wcm90b2J1Zi91bml0dGVzdF9w", 
+            "cm90bzMucHJvdG8ilhIKB1Rlc3RNYXASRgoPbWFwX2ludDMyX2ludDMyGAEg", 
+            "AygLMi0ucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5NYXBJbnQzMkludDMy", 
+            "RW50cnkSRgoPbWFwX2ludDY0X2ludDY0GAIgAygLMi0ucHJvdG9idWZfdW5p", 
+            "dHRlc3QuVGVzdE1hcC5NYXBJbnQ2NEludDY0RW50cnkSSgoRbWFwX3VpbnQz", 
+            "Ml91aW50MzIYAyADKAsyLy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwLk1h", 
+            "cFVpbnQzMlVpbnQzMkVudHJ5EkoKEW1hcF91aW50NjRfdWludDY0GAQgAygL", 
+            "Mi8ucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5NYXBVaW50NjRVaW50NjRF", 
+            "bnRyeRJKChFtYXBfc2ludDMyX3NpbnQzMhgFIAMoCzIvLnByb3RvYnVmX3Vu", 
+            "aXR0ZXN0LlRlc3RNYXAuTWFwU2ludDMyU2ludDMyRW50cnkSSgoRbWFwX3Np", 
+            "bnQ2NF9zaW50NjQYBiADKAsyLy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFw", 
+            "Lk1hcFNpbnQ2NFNpbnQ2NEVudHJ5Ek4KE21hcF9maXhlZDMyX2ZpeGVkMzIY", 
+            "ByADKAsyMS5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwLk1hcEZpeGVkMzJG", 
+            "aXhlZDMyRW50cnkSTgoTbWFwX2ZpeGVkNjRfZml4ZWQ2NBgIIAMoCzIxLnBy", 
+            "b3RvYnVmX3VuaXR0ZXN0LlRlc3RNYXAuTWFwRml4ZWQ2NEZpeGVkNjRFbnRy", 
+            "eRJSChVtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIYCSADKAsyMy5wcm90b2J1Zl91", 
+            "bml0dGVzdC5UZXN0TWFwLk1hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeRJSChVt", 
+            "YXBfc2ZpeGVkNjRfc2ZpeGVkNjQYCiADKAsyMy5wcm90b2J1Zl91bml0dGVz", 
+            "dC5UZXN0TWFwLk1hcFNmaXhlZDY0U2ZpeGVkNjRFbnRyeRJGCg9tYXBfaW50", 
+            "MzJfZmxvYXQYCyADKAsyLS5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwLk1h", 
+            "cEludDMyRmxvYXRFbnRyeRJIChBtYXBfaW50MzJfZG91YmxlGAwgAygLMi4u", 
+            "cHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5NYXBJbnQzMkRvdWJsZUVudHJ5", 
+            "EkIKDW1hcF9ib29sX2Jvb2wYDSADKAsyKy5wcm90b2J1Zl91bml0dGVzdC5U", 
+            "ZXN0TWFwLk1hcEJvb2xCb29sRW50cnkSSgoRbWFwX3N0cmluZ19zdHJpbmcY", 
+            "DiADKAsyLy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TWFwLk1hcFN0cmluZ1N0", 
+            "cmluZ0VudHJ5EkYKD21hcF9pbnQzMl9ieXRlcxgPIAMoCzItLnByb3RvYnVm", 
+            "X3VuaXR0ZXN0LlRlc3RNYXAuTWFwSW50MzJCeXRlc0VudHJ5EkQKDm1hcF9p", 
+            "bnQzMl9lbnVtGBAgAygLMiwucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5N", 
+            "YXBJbnQzMkVudW1FbnRyeRJZChltYXBfaW50MzJfZm9yZWlnbl9tZXNzYWdl", 
+            "GBEgAygLMjYucHJvdG9idWZfdW5pdHRlc3QuVGVzdE1hcC5NYXBJbnQzMkZv", 
+            "cmVpZ25NZXNzYWdlRW50cnkaNAoSTWFwSW50MzJJbnQzMkVudHJ5EgsKA2tl", 
+            "eRgBIAEoBRINCgV2YWx1ZRgCIAEoBToCOAEaNAoSTWFwSW50NjRJbnQ2NEVu", 
+            "dHJ5EgsKA2tleRgBIAEoAxINCgV2YWx1ZRgCIAEoAzoCOAEaNgoUTWFwVWlu", 
+            "dDMyVWludDMyRW50cnkSCwoDa2V5GAEgASgNEg0KBXZhbHVlGAIgASgNOgI4", 
+            "ARo2ChRNYXBVaW50NjRVaW50NjRFbnRyeRILCgNrZXkYASABKAQSDQoFdmFs", 
+            "dWUYAiABKAQ6AjgBGjYKFE1hcFNpbnQzMlNpbnQzMkVudHJ5EgsKA2tleRgB", 
+            "IAEoERINCgV2YWx1ZRgCIAEoEToCOAEaNgoUTWFwU2ludDY0U2ludDY0RW50", 
+            "cnkSCwoDa2V5GAEgASgSEg0KBXZhbHVlGAIgASgSOgI4ARo4ChZNYXBGaXhl", 
+            "ZDMyRml4ZWQzMkVudHJ5EgsKA2tleRgBIAEoBxINCgV2YWx1ZRgCIAEoBzoC", 
+            "OAEaOAoWTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeRILCgNrZXkYASABKAYSDQoF", 
+            "dmFsdWUYAiABKAY6AjgBGjoKGE1hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeRIL", 
+            "CgNrZXkYASABKA8SDQoFdmFsdWUYAiABKA86AjgBGjoKGE1hcFNmaXhlZDY0", 
+            "U2ZpeGVkNjRFbnRyeRILCgNrZXkYASABKBASDQoFdmFsdWUYAiABKBA6AjgB", 
+            "GjQKEk1hcEludDMyRmxvYXRFbnRyeRILCgNrZXkYASABKAUSDQoFdmFsdWUY", 
+            "AiABKAI6AjgBGjUKE01hcEludDMyRG91YmxlRW50cnkSCwoDa2V5GAEgASgF", 
+            "Eg0KBXZhbHVlGAIgASgBOgI4ARoyChBNYXBCb29sQm9vbEVudHJ5EgsKA2tl", 
+            "eRgBIAEoCBINCgV2YWx1ZRgCIAEoCDoCOAEaNgoUTWFwU3RyaW5nU3RyaW5n", 
+            "RW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJOgI4ARo0ChJNYXBJ", 
+            "bnQzMkJ5dGVzRW50cnkSCwoDa2V5GAEgASgFEg0KBXZhbHVlGAIgASgMOgI4", 
+            "ARpPChFNYXBJbnQzMkVudW1FbnRyeRILCgNrZXkYASABKAUSKQoFdmFsdWUY", 
+            "AiABKA4yGi5wcm90b2J1Zl91bml0dGVzdC5NYXBFbnVtOgI4ARpgChtNYXBJ", 
+            "bnQzMkZvcmVpZ25NZXNzYWdlRW50cnkSCwoDa2V5GAEgASgFEjAKBXZhbHVl", 
+            "GAIgASgLMiEucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2U6AjgB", 
+            "IkEKEVRlc3RNYXBTdWJtZXNzYWdlEiwKCHRlc3RfbWFwGAEgASgLMhoucHJv", 
+            "dG9idWZfdW5pdHRlc3QuVGVzdE1hcCK8AQoOVGVzdE1lc3NhZ2VNYXASUQoR", 
+            "bWFwX2ludDMyX21lc3NhZ2UYASADKAsyNi5wcm90b2J1Zl91bml0dGVzdC5U", 
+            "ZXN0TWVzc2FnZU1hcC5NYXBJbnQzMk1lc3NhZ2VFbnRyeRpXChRNYXBJbnQz", 
+            "Mk1lc3NhZ2VFbnRyeRILCgNrZXkYASABKAUSLgoFdmFsdWUYAiABKAsyHy5w", 
+            "cm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXM6AjgBIuMBCg9UZXN0U2Ft", 
+            "ZVR5cGVNYXASOgoEbWFwMRgBIAMoCzIsLnByb3RvYnVmX3VuaXR0ZXN0LlRl", 
+            "c3RTYW1lVHlwZU1hcC5NYXAxRW50cnkSOgoEbWFwMhgCIAMoCzIsLnByb3Rv", 
+            "YnVmX3VuaXR0ZXN0LlRlc3RTYW1lVHlwZU1hcC5NYXAyRW50cnkaKwoJTWFw", 
+            "MUVudHJ5EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEoBToCOAEaKwoJTWFw", 
+            "MkVudHJ5EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEoBToCOAEi5BAKDFRl", 
+            "c3RBcmVuYU1hcBJLCg9tYXBfaW50MzJfaW50MzIYASADKAsyMi5wcm90b2J1", 
+            "Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAuTWFwSW50MzJJbnQzMkVudHJ5EksK", 
+            "D21hcF9pbnQ2NF9pbnQ2NBgCIAMoCzIyLnByb3RvYnVmX3VuaXR0ZXN0LlRl", 
+            "c3RBcmVuYU1hcC5NYXBJbnQ2NEludDY0RW50cnkSTwoRbWFwX3VpbnQzMl91", 
+            "aW50MzIYAyADKAsyNC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAu", 
+            "TWFwVWludDMyVWludDMyRW50cnkSTwoRbWFwX3VpbnQ2NF91aW50NjQYBCAD", 
+            "KAsyNC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAuTWFwVWludDY0", 
+            "VWludDY0RW50cnkSTwoRbWFwX3NpbnQzMl9zaW50MzIYBSADKAsyNC5wcm90", 
+            "b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAuTWFwU2ludDMyU2ludDMyRW50", 
+            "cnkSTwoRbWFwX3NpbnQ2NF9zaW50NjQYBiADKAsyNC5wcm90b2J1Zl91bml0", 
+            "dGVzdC5UZXN0QXJlbmFNYXAuTWFwU2ludDY0U2ludDY0RW50cnkSUwoTbWFw", 
+            "X2ZpeGVkMzJfZml4ZWQzMhgHIAMoCzI2LnByb3RvYnVmX3VuaXR0ZXN0LlRl", 
+            "c3RBcmVuYU1hcC5NYXBGaXhlZDMyRml4ZWQzMkVudHJ5ElMKE21hcF9maXhl", 
+            "ZDY0X2ZpeGVkNjQYCCADKAsyNi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJl", 
+            "bmFNYXAuTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeRJXChVtYXBfc2ZpeGVkMzJf", 
+            "c2ZpeGVkMzIYCSADKAsyOC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFN", 
+            "YXAuTWFwU2ZpeGVkMzJTZml4ZWQzMkVudHJ5ElcKFW1hcF9zZml4ZWQ2NF9z", 
+            "Zml4ZWQ2NBgKIAMoCzI4LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBcmVuYU1h", 
+            "cC5NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnkSSwoPbWFwX2ludDMyX2Zsb2F0", 
+            "GAsgAygLMjIucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFyZW5hTWFwLk1hcElu", 
+            "dDMyRmxvYXRFbnRyeRJNChBtYXBfaW50MzJfZG91YmxlGAwgAygLMjMucHJv", 
+            "dG9idWZfdW5pdHRlc3QuVGVzdEFyZW5hTWFwLk1hcEludDMyRG91YmxlRW50", 
+            "cnkSRwoNbWFwX2Jvb2xfYm9vbBgNIAMoCzIwLnByb3RvYnVmX3VuaXR0ZXN0", 
+            "LlRlc3RBcmVuYU1hcC5NYXBCb29sQm9vbEVudHJ5EkkKDm1hcF9pbnQzMl9l", 
+            "bnVtGA4gAygLMjEucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFyZW5hTWFwLk1h", 
+            "cEludDMyRW51bUVudHJ5El4KGW1hcF9pbnQzMl9mb3JlaWduX21lc3NhZ2UY", 
+            "DyADKAsyOy5wcm90b2J1Zl91bml0dGVzdC5UZXN0QXJlbmFNYXAuTWFwSW50", 
+            "MzJGb3JlaWduTWVzc2FnZUVudHJ5GjQKEk1hcEludDMySW50MzJFbnRyeRIL", 
+            "CgNrZXkYASABKAUSDQoFdmFsdWUYAiABKAU6AjgBGjQKEk1hcEludDY0SW50", 
+            "NjRFbnRyeRILCgNrZXkYASABKAMSDQoFdmFsdWUYAiABKAM6AjgBGjYKFE1h", 
+            "cFVpbnQzMlVpbnQzMkVudHJ5EgsKA2tleRgBIAEoDRINCgV2YWx1ZRgCIAEo", 
+            "DToCOAEaNgoUTWFwVWludDY0VWludDY0RW50cnkSCwoDa2V5GAEgASgEEg0K", 
+            "BXZhbHVlGAIgASgEOgI4ARo2ChRNYXBTaW50MzJTaW50MzJFbnRyeRILCgNr", 
+            "ZXkYASABKBESDQoFdmFsdWUYAiABKBE6AjgBGjYKFE1hcFNpbnQ2NFNpbnQ2", 
+            "NEVudHJ5EgsKA2tleRgBIAEoEhINCgV2YWx1ZRgCIAEoEjoCOAEaOAoWTWFw", 
+            "Rml4ZWQzMkZpeGVkMzJFbnRyeRILCgNrZXkYASABKAcSDQoFdmFsdWUYAiAB", 
+            "KAc6AjgBGjgKFk1hcEZpeGVkNjRGaXhlZDY0RW50cnkSCwoDa2V5GAEgASgG", 
+            "Eg0KBXZhbHVlGAIgASgGOgI4ARo6ChhNYXBTZml4ZWQzMlNmaXhlZDMyRW50", 
+            "cnkSCwoDa2V5GAEgASgPEg0KBXZhbHVlGAIgASgPOgI4ARo6ChhNYXBTZml4", 
+            "ZWQ2NFNmaXhlZDY0RW50cnkSCwoDa2V5GAEgASgQEg0KBXZhbHVlGAIgASgQ", 
+            "OgI4ARo0ChJNYXBJbnQzMkZsb2F0RW50cnkSCwoDa2V5GAEgASgFEg0KBXZh", 
+            "bHVlGAIgASgCOgI4ARo1ChNNYXBJbnQzMkRvdWJsZUVudHJ5EgsKA2tleRgB", 
+            "IAEoBRINCgV2YWx1ZRgCIAEoAToCOAEaMgoQTWFwQm9vbEJvb2xFbnRyeRIL", 
+            "CgNrZXkYASABKAgSDQoFdmFsdWUYAiABKAg6AjgBGk8KEU1hcEludDMyRW51", 
+            "bUVudHJ5EgsKA2tleRgBIAEoBRIpCgV2YWx1ZRgCIAEoDjIaLnByb3RvYnVm", 
+            "X3VuaXR0ZXN0Lk1hcEVudW06AjgBGmAKG01hcEludDMyRm9yZWlnbk1lc3Nh", 
+            "Z2VFbnRyeRILCgNrZXkYASABKAUSMAoFdmFsdWUYAiABKAsyIS5wcm90b2J1", 
+            "Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZToCOAEi5AEKH01lc3NhZ2VDb250", 
+            "YWluaW5nRW51bUNhbGxlZFR5cGUSSgoEdHlwZRgBIAMoCzI8LnByb3RvYnVm", 
+            "X3VuaXR0ZXN0Lk1lc3NhZ2VDb250YWluaW5nRW51bUNhbGxlZFR5cGUuVHlw", 
+            "ZUVudHJ5Gl8KCVR5cGVFbnRyeRILCgNrZXkYASABKAUSQQoFdmFsdWUYAiAB", 
+            "KAsyMi5wcm90b2J1Zl91bml0dGVzdC5NZXNzYWdlQ29udGFpbmluZ0VudW1D", 
+            "YWxsZWRUeXBlOgI4ASIUCgRUeXBlEgwKCFRZUEVfRk9PEAAinQEKH01lc3Nh", 
+            "Z2VDb250YWluaW5nTWFwQ2FsbGVkRW50cnkSTAoFZW50cnkYASADKAsyPS5w", 
+            "cm90b2J1Zl91bml0dGVzdC5NZXNzYWdlQ29udGFpbmluZ01hcENhbGxlZEVu", 
+            "dHJ5LkVudHJ5RW50cnkaLAoKRW50cnlFbnRyeRILCgNrZXkYASABKAUSDQoF", 
+            "dmFsdWUYAiABKAU6AjgBKj8KB01hcEVudW0SEAoMTUFQX0VOVU1fRk9PEAAS", 
+            "EAoMTUFQX0VOVU1fQkFSEAESEAoMTUFQX0VOVU1fQkFaEAJCIPgBAaoCGkdv", 
+          "b2dsZS5Qcm90b2J1Zi5UZXN0UHJvdG9zYgZwcm90bzM="));
+      pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
+        descriptor = root;
+        internal__static_protobuf_unittest_TestMap__Descriptor = Descriptor.MessageTypes[0];
+        internal__static_protobuf_unittest_TestMap__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap>(internal__static_protobuf_unittest_TestMap__Descriptor,
+                new string[] { "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapInt32Bytes", "MapInt32Enum", "MapInt32ForeignMessage", });
+        internal__static_protobuf_unittest_TestMap_MapInt32Int32Entry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[0];
+        internal__static_protobuf_unittest_TestMap_MapInt32Int32Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32Int32Entry>(internal__static_protobuf_unittest_TestMap_MapInt32Int32Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestMap_MapInt64Int64Entry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[1];
+        internal__static_protobuf_unittest_TestMap_MapInt64Int64Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt64Int64Entry>(internal__static_protobuf_unittest_TestMap_MapInt64Int64Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestMap_MapUint32Uint32Entry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[2];
+        internal__static_protobuf_unittest_TestMap_MapUint32Uint32Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapUint32Uint32Entry>(internal__static_protobuf_unittest_TestMap_MapUint32Uint32Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestMap_MapUint64Uint64Entry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[3];
+        internal__static_protobuf_unittest_TestMap_MapUint64Uint64Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapUint64Uint64Entry>(internal__static_protobuf_unittest_TestMap_MapUint64Uint64Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestMap_MapSint32Sint32Entry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[4];
+        internal__static_protobuf_unittest_TestMap_MapSint32Sint32Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapSint32Sint32Entry>(internal__static_protobuf_unittest_TestMap_MapSint32Sint32Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestMap_MapSint64Sint64Entry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[5];
+        internal__static_protobuf_unittest_TestMap_MapSint64Sint64Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapSint64Sint64Entry>(internal__static_protobuf_unittest_TestMap_MapSint64Sint64Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestMap_MapFixed32Fixed32Entry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[6];
+        internal__static_protobuf_unittest_TestMap_MapFixed32Fixed32Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapFixed32Fixed32Entry>(internal__static_protobuf_unittest_TestMap_MapFixed32Fixed32Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestMap_MapFixed64Fixed64Entry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[7];
+        internal__static_protobuf_unittest_TestMap_MapFixed64Fixed64Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapFixed64Fixed64Entry>(internal__static_protobuf_unittest_TestMap_MapFixed64Fixed64Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestMap_MapSfixed32Sfixed32Entry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[8];
+        internal__static_protobuf_unittest_TestMap_MapSfixed32Sfixed32Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapSfixed32Sfixed32Entry>(internal__static_protobuf_unittest_TestMap_MapSfixed32Sfixed32Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestMap_MapSfixed64Sfixed64Entry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[9];
+        internal__static_protobuf_unittest_TestMap_MapSfixed64Sfixed64Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapSfixed64Sfixed64Entry>(internal__static_protobuf_unittest_TestMap_MapSfixed64Sfixed64Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestMap_MapInt32FloatEntry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[10];
+        internal__static_protobuf_unittest_TestMap_MapInt32FloatEntry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32FloatEntry>(internal__static_protobuf_unittest_TestMap_MapInt32FloatEntry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestMap_MapInt32DoubleEntry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[11];
+        internal__static_protobuf_unittest_TestMap_MapInt32DoubleEntry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32DoubleEntry>(internal__static_protobuf_unittest_TestMap_MapInt32DoubleEntry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestMap_MapBoolBoolEntry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[12];
+        internal__static_protobuf_unittest_TestMap_MapBoolBoolEntry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapBoolBoolEntry>(internal__static_protobuf_unittest_TestMap_MapBoolBoolEntry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestMap_MapStringStringEntry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[13];
+        internal__static_protobuf_unittest_TestMap_MapStringStringEntry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapStringStringEntry>(internal__static_protobuf_unittest_TestMap_MapStringStringEntry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestMap_MapInt32BytesEntry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[14];
+        internal__static_protobuf_unittest_TestMap_MapInt32BytesEntry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32BytesEntry>(internal__static_protobuf_unittest_TestMap_MapInt32BytesEntry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestMap_MapInt32EnumEntry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[15];
+        internal__static_protobuf_unittest_TestMap_MapInt32EnumEntry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32EnumEntry>(internal__static_protobuf_unittest_TestMap_MapInt32EnumEntry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestMap_MapInt32ForeignMessageEntry__Descriptor = internal__static_protobuf_unittest_TestMap__Descriptor.NestedTypes[16];
+        internal__static_protobuf_unittest_TestMap_MapInt32ForeignMessageEntry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMap.Types.MapInt32ForeignMessageEntry>(internal__static_protobuf_unittest_TestMap_MapInt32ForeignMessageEntry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestMapSubmessage__Descriptor = Descriptor.MessageTypes[1];
+        internal__static_protobuf_unittest_TestMapSubmessage__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMapSubmessage>(internal__static_protobuf_unittest_TestMapSubmessage__Descriptor,
+                new string[] { "TestMap", });
+        internal__static_protobuf_unittest_TestMessageMap__Descriptor = Descriptor.MessageTypes[2];
+        internal__static_protobuf_unittest_TestMessageMap__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMessageMap>(internal__static_protobuf_unittest_TestMessageMap__Descriptor,
+                new string[] { "MapInt32Message", });
+        internal__static_protobuf_unittest_TestMessageMap_MapInt32MessageEntry__Descriptor = internal__static_protobuf_unittest_TestMessageMap__Descriptor.NestedTypes[0];
+        internal__static_protobuf_unittest_TestMessageMap_MapInt32MessageEntry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestMessageMap.Types.MapInt32MessageEntry>(internal__static_protobuf_unittest_TestMessageMap_MapInt32MessageEntry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestSameTypeMap__Descriptor = Descriptor.MessageTypes[3];
+        internal__static_protobuf_unittest_TestSameTypeMap__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestSameTypeMap>(internal__static_protobuf_unittest_TestSameTypeMap__Descriptor,
+                new string[] { "Map1", "Map2", });
+        internal__static_protobuf_unittest_TestSameTypeMap_Map1Entry__Descriptor = internal__static_protobuf_unittest_TestSameTypeMap__Descriptor.NestedTypes[0];
+        internal__static_protobuf_unittest_TestSameTypeMap_Map1Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestSameTypeMap.Types.Map1Entry>(internal__static_protobuf_unittest_TestSameTypeMap_Map1Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestSameTypeMap_Map2Entry__Descriptor = internal__static_protobuf_unittest_TestSameTypeMap__Descriptor.NestedTypes[1];
+        internal__static_protobuf_unittest_TestSameTypeMap_Map2Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestSameTypeMap.Types.Map2Entry>(internal__static_protobuf_unittest_TestSameTypeMap_Map2Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestArenaMap__Descriptor = Descriptor.MessageTypes[4];
+        internal__static_protobuf_unittest_TestArenaMap__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap>(internal__static_protobuf_unittest_TestArenaMap__Descriptor,
+                new string[] { "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapInt32Enum", "MapInt32ForeignMessage", });
+        internal__static_protobuf_unittest_TestArenaMap_MapInt32Int32Entry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[0];
+        internal__static_protobuf_unittest_TestArenaMap_MapInt32Int32Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32Int32Entry>(internal__static_protobuf_unittest_TestArenaMap_MapInt32Int32Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestArenaMap_MapInt64Int64Entry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[1];
+        internal__static_protobuf_unittest_TestArenaMap_MapInt64Int64Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt64Int64Entry>(internal__static_protobuf_unittest_TestArenaMap_MapInt64Int64Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestArenaMap_MapUint32Uint32Entry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[2];
+        internal__static_protobuf_unittest_TestArenaMap_MapUint32Uint32Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapUint32Uint32Entry>(internal__static_protobuf_unittest_TestArenaMap_MapUint32Uint32Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestArenaMap_MapUint64Uint64Entry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[3];
+        internal__static_protobuf_unittest_TestArenaMap_MapUint64Uint64Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapUint64Uint64Entry>(internal__static_protobuf_unittest_TestArenaMap_MapUint64Uint64Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestArenaMap_MapSint32Sint32Entry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[4];
+        internal__static_protobuf_unittest_TestArenaMap_MapSint32Sint32Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapSint32Sint32Entry>(internal__static_protobuf_unittest_TestArenaMap_MapSint32Sint32Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestArenaMap_MapSint64Sint64Entry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[5];
+        internal__static_protobuf_unittest_TestArenaMap_MapSint64Sint64Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapSint64Sint64Entry>(internal__static_protobuf_unittest_TestArenaMap_MapSint64Sint64Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestArenaMap_MapFixed32Fixed32Entry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[6];
+        internal__static_protobuf_unittest_TestArenaMap_MapFixed32Fixed32Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapFixed32Fixed32Entry>(internal__static_protobuf_unittest_TestArenaMap_MapFixed32Fixed32Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestArenaMap_MapFixed64Fixed64Entry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[7];
+        internal__static_protobuf_unittest_TestArenaMap_MapFixed64Fixed64Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapFixed64Fixed64Entry>(internal__static_protobuf_unittest_TestArenaMap_MapFixed64Fixed64Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestArenaMap_MapSfixed32Sfixed32Entry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[8];
+        internal__static_protobuf_unittest_TestArenaMap_MapSfixed32Sfixed32Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapSfixed32Sfixed32Entry>(internal__static_protobuf_unittest_TestArenaMap_MapSfixed32Sfixed32Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestArenaMap_MapSfixed64Sfixed64Entry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[9];
+        internal__static_protobuf_unittest_TestArenaMap_MapSfixed64Sfixed64Entry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapSfixed64Sfixed64Entry>(internal__static_protobuf_unittest_TestArenaMap_MapSfixed64Sfixed64Entry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestArenaMap_MapInt32FloatEntry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[10];
+        internal__static_protobuf_unittest_TestArenaMap_MapInt32FloatEntry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32FloatEntry>(internal__static_protobuf_unittest_TestArenaMap_MapInt32FloatEntry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestArenaMap_MapInt32DoubleEntry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[11];
+        internal__static_protobuf_unittest_TestArenaMap_MapInt32DoubleEntry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32DoubleEntry>(internal__static_protobuf_unittest_TestArenaMap_MapInt32DoubleEntry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestArenaMap_MapBoolBoolEntry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[12];
+        internal__static_protobuf_unittest_TestArenaMap_MapBoolBoolEntry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapBoolBoolEntry>(internal__static_protobuf_unittest_TestArenaMap_MapBoolBoolEntry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestArenaMap_MapInt32EnumEntry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[13];
+        internal__static_protobuf_unittest_TestArenaMap_MapInt32EnumEntry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32EnumEntry>(internal__static_protobuf_unittest_TestArenaMap_MapInt32EnumEntry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_TestArenaMap_MapInt32ForeignMessageEntry__Descriptor = internal__static_protobuf_unittest_TestArenaMap__Descriptor.NestedTypes[14];
+        internal__static_protobuf_unittest_TestArenaMap_MapInt32ForeignMessageEntry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.TestArenaMap.Types.MapInt32ForeignMessageEntry>(internal__static_protobuf_unittest_TestArenaMap_MapInt32ForeignMessageEntry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_MessageContainingEnumCalledType__Descriptor = Descriptor.MessageTypes[5];
+        internal__static_protobuf_unittest_MessageContainingEnumCalledType__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType>(internal__static_protobuf_unittest_MessageContainingEnumCalledType__Descriptor,
+                new string[] { "Type", });
+        internal__static_protobuf_unittest_MessageContainingEnumCalledType_TypeEntry__Descriptor = internal__static_protobuf_unittest_MessageContainingEnumCalledType__Descriptor.NestedTypes[0];
+        internal__static_protobuf_unittest_MessageContainingEnumCalledType_TypeEntry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Types.TypeEntry>(internal__static_protobuf_unittest_MessageContainingEnumCalledType_TypeEntry__Descriptor,
+                new string[] { "Key", "Value", });
+        internal__static_protobuf_unittest_MessageContainingMapCalledEntry__Descriptor = Descriptor.MessageTypes[6];
+        internal__static_protobuf_unittest_MessageContainingMapCalledEntry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry>(internal__static_protobuf_unittest_MessageContainingMapCalledEntry__Descriptor,
+                new string[] { "Entry", });
+        internal__static_protobuf_unittest_MessageContainingMapCalledEntry_EntryEntry__Descriptor = internal__static_protobuf_unittest_MessageContainingMapCalledEntry__Descriptor.NestedTypes[0];
+        internal__static_protobuf_unittest_MessageContainingMapCalledEntry_EntryEntry__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry.Types.EntryEntry>(internal__static_protobuf_unittest_MessageContainingMapCalledEntry_EntryEntry__Descriptor,
+                new string[] { "Key", "Value", });
+      };
+      pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+          new pbd::FileDescriptor[] {
+          global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor, 
+          }, assigner);
+    }
+    #endregion
+
+  }
+  #region Enums
+  public enum MapEnum {
+    MAP_ENUM_FOO = 0,
+    MAP_ENUM_BAR = 1,
+    MAP_ENUM_BAZ = 2,
+  }
+
+  #endregion
+
+  #region Messages
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestMap : pb::IMessage<TestMap> {
+    private static readonly pb::MessageParser<TestMap> _parser = new pb::MessageParser<TestMap>(() => new TestMap());
+    public static pb::MessageParser<TestMap> Parser { get { return _parser; } }
+
+    private static readonly string[] _fieldNames = new string[] { "map_bool_bool", "map_fixed32_fixed32", "map_fixed64_fixed64", "map_int32_bytes", "map_int32_double", "map_int32_enum", "map_int32_float", "map_int32_foreign_message", "map_int32_int32", "map_int64_int64", "map_sfixed32_sfixed32", "map_sfixed64_sfixed64", "map_sint32_sint32", "map_sint64_sint64", "map_string_string", "map_uint32_uint32", "map_uint64_uint64" };
+    private static readonly uint[] _fieldTags = new uint[] { 106, 58, 66, 122, 98, 130, 90, 138, 10, 18, 74, 82, 42, 50, 114, 26, 34 };
+    public static pbd::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap__Descriptor; }
+    }
+
+    public pb::FieldAccess.FieldAccessorTable<TestMap> Fields {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap__FieldAccessorTable; }
+    }
+
+    private bool _frozen = false;
+    public bool IsFrozen { get { return _frozen; } }
+
+    public TestMap() { }
+
+    public TestMap(TestMap other) {
+      mapInt32Int32_ = other.mapInt32Int32_.Clone();
+      mapInt64Int64_ = other.mapInt64Int64_.Clone();
+      mapUint32Uint32_ = other.mapUint32Uint32_.Clone();
+      mapUint64Uint64_ = other.mapUint64Uint64_.Clone();
+      mapSint32Sint32_ = other.mapSint32Sint32_.Clone();
+      mapSint64Sint64_ = other.mapSint64Sint64_.Clone();
+      mapFixed32Fixed32_ = other.mapFixed32Fixed32_.Clone();
+      mapFixed64Fixed64_ = other.mapFixed64Fixed64_.Clone();
+      mapSfixed32Sfixed32_ = other.mapSfixed32Sfixed32_.Clone();
+      mapSfixed64Sfixed64_ = other.mapSfixed64Sfixed64_.Clone();
+      mapInt32Float_ = other.mapInt32Float_.Clone();
+      mapInt32Double_ = other.mapInt32Double_.Clone();
+      mapBoolBool_ = other.mapBoolBool_.Clone();
+      mapStringString_ = other.mapStringString_.Clone();
+      mapInt32Bytes_ = other.mapInt32Bytes_.Clone();
+      mapInt32Enum_ = other.mapInt32Enum_.Clone();
+      mapInt32ForeignMessage_ = other.mapInt32ForeignMessage_.Clone();
+    }
+
+    public TestMap Clone() {
+      return new TestMap(this);
+    }
+
+    public void Freeze() {
+      if (IsFrozen) {
+        return;
+      }
+      _frozen = true;
+      mapInt32Int32_.Freeze();
+      mapInt64Int64_.Freeze();
+      mapUint32Uint32_.Freeze();
+      mapUint64Uint64_.Freeze();
+      mapSint32Sint32_.Freeze();
+      mapSint64Sint64_.Freeze();
+      mapFixed32Fixed32_.Freeze();
+      mapFixed64Fixed64_.Freeze();
+      mapSfixed32Sfixed32_.Freeze();
+      mapSfixed64Sfixed64_.Freeze();
+      mapInt32Float_.Freeze();
+      mapInt32Double_.Freeze();
+      mapBoolBool_.Freeze();
+      mapStringString_.Freeze();
+      mapInt32Bytes_.Freeze();
+      mapInt32Enum_.Freeze();
+      mapInt32ForeignMessage_.Freeze();
+    }
+
+    public const int MapInt32Int32FieldNumber = 1;
+    private static readonly pbc::MapField<int, int>.Codec _map_mapInt32Int32_codec
+        = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForInt32(16), 10);
+    private readonly pbc::MapField<int, int> mapInt32Int32_ = new pbc::MapField<int, int>();
+    public pbc::MapField<int, int> MapInt32Int32 {
+      get { return mapInt32Int32_; }
+    }
+
+    public const int MapInt64Int64FieldNumber = 2;
+    private static readonly pbc::MapField<long, long>.Codec _map_mapInt64Int64_codec
+        = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForInt64(8), pb::FieldCodec.ForInt64(16), 18);
+    private readonly pbc::MapField<long, long> mapInt64Int64_ = new pbc::MapField<long, long>();
+    public pbc::MapField<long, long> MapInt64Int64 {
+      get { return mapInt64Int64_; }
+    }
+
+    public const int MapUint32Uint32FieldNumber = 3;
+    private static readonly pbc::MapField<uint, uint>.Codec _map_mapUint32Uint32_codec
+        = new pbc::MapField<uint, uint>.Codec(pb::FieldCodec.ForUInt32(8), pb::FieldCodec.ForUInt32(16), 26);
+    private readonly pbc::MapField<uint, uint> mapUint32Uint32_ = new pbc::MapField<uint, uint>();
+    public pbc::MapField<uint, uint> MapUint32Uint32 {
+      get { return mapUint32Uint32_; }
+    }
+
+    public const int MapUint64Uint64FieldNumber = 4;
+    private static readonly pbc::MapField<ulong, ulong>.Codec _map_mapUint64Uint64_codec
+        = new pbc::MapField<ulong, ulong>.Codec(pb::FieldCodec.ForUInt64(8), pb::FieldCodec.ForUInt64(16), 34);
+    private readonly pbc::MapField<ulong, ulong> mapUint64Uint64_ = new pbc::MapField<ulong, ulong>();
+    public pbc::MapField<ulong, ulong> MapUint64Uint64 {
+      get { return mapUint64Uint64_; }
+    }
+
+    public const int MapSint32Sint32FieldNumber = 5;
+    private static readonly pbc::MapField<int, int>.Codec _map_mapSint32Sint32_codec
+        = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForSInt32(8), pb::FieldCodec.ForSInt32(16), 42);
+    private readonly pbc::MapField<int, int> mapSint32Sint32_ = new pbc::MapField<int, int>();
+    public pbc::MapField<int, int> MapSint32Sint32 {
+      get { return mapSint32Sint32_; }
+    }
+
+    public const int MapSint64Sint64FieldNumber = 6;
+    private static readonly pbc::MapField<long, long>.Codec _map_mapSint64Sint64_codec
+        = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForSInt64(8), pb::FieldCodec.ForSInt64(16), 50);
+    private readonly pbc::MapField<long, long> mapSint64Sint64_ = new pbc::MapField<long, long>();
+    public pbc::MapField<long, long> MapSint64Sint64 {
+      get { return mapSint64Sint64_; }
+    }
+
+    public const int MapFixed32Fixed32FieldNumber = 7;
+    private static readonly pbc::MapField<uint, uint>.Codec _map_mapFixed32Fixed32_codec
+        = new pbc::MapField<uint, uint>.Codec(pb::FieldCodec.ForFixed32(13), pb::FieldCodec.ForFixed32(21), 58);
+    private readonly pbc::MapField<uint, uint> mapFixed32Fixed32_ = new pbc::MapField<uint, uint>();
+    public pbc::MapField<uint, uint> MapFixed32Fixed32 {
+      get { return mapFixed32Fixed32_; }
+    }
+
+    public const int MapFixed64Fixed64FieldNumber = 8;
+    private static readonly pbc::MapField<ulong, ulong>.Codec _map_mapFixed64Fixed64_codec
+        = new pbc::MapField<ulong, ulong>.Codec(pb::FieldCodec.ForFixed64(9), pb::FieldCodec.ForFixed64(17), 66);
+    private readonly pbc::MapField<ulong, ulong> mapFixed64Fixed64_ = new pbc::MapField<ulong, ulong>();
+    public pbc::MapField<ulong, ulong> MapFixed64Fixed64 {
+      get { return mapFixed64Fixed64_; }
+    }
+
+    public const int MapSfixed32Sfixed32FieldNumber = 9;
+    private static readonly pbc::MapField<int, int>.Codec _map_mapSfixed32Sfixed32_codec
+        = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForSFixed32(13), pb::FieldCodec.ForSFixed32(21), 74);
+    private readonly pbc::MapField<int, int> mapSfixed32Sfixed32_ = new pbc::MapField<int, int>();
+    public pbc::MapField<int, int> MapSfixed32Sfixed32 {
+      get { return mapSfixed32Sfixed32_; }
+    }
+
+    public const int MapSfixed64Sfixed64FieldNumber = 10;
+    private static readonly pbc::MapField<long, long>.Codec _map_mapSfixed64Sfixed64_codec
+        = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForSFixed64(9), pb::FieldCodec.ForSFixed64(17), 82);
+    private readonly pbc::MapField<long, long> mapSfixed64Sfixed64_ = new pbc::MapField<long, long>();
+    public pbc::MapField<long, long> MapSfixed64Sfixed64 {
+      get { return mapSfixed64Sfixed64_; }
+    }
+
+    public const int MapInt32FloatFieldNumber = 11;
+    private static readonly pbc::MapField<int, float>.Codec _map_mapInt32Float_codec
+        = new pbc::MapField<int, float>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForFloat(21), 90);
+    private readonly pbc::MapField<int, float> mapInt32Float_ = new pbc::MapField<int, float>();
+    public pbc::MapField<int, float> MapInt32Float {
+      get { return mapInt32Float_; }
+    }
+
+    public const int MapInt32DoubleFieldNumber = 12;
+    private static readonly pbc::MapField<int, double>.Codec _map_mapInt32Double_codec
+        = new pbc::MapField<int, double>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForDouble(17), 98);
+    private readonly pbc::MapField<int, double> mapInt32Double_ = new pbc::MapField<int, double>();
+    public pbc::MapField<int, double> MapInt32Double {
+      get { return mapInt32Double_; }
+    }
+
+    public const int MapBoolBoolFieldNumber = 13;
+    private static readonly pbc::MapField<bool, bool>.Codec _map_mapBoolBool_codec
+        = new pbc::MapField<bool, bool>.Codec(pb::FieldCodec.ForBool(8), pb::FieldCodec.ForBool(16), 106);
+    private readonly pbc::MapField<bool, bool> mapBoolBool_ = new pbc::MapField<bool, bool>();
+    public pbc::MapField<bool, bool> MapBoolBool {
+      get { return mapBoolBool_; }
+    }
+
+    public const int MapStringStringFieldNumber = 14;
+    private static readonly pbc::MapField<string, string>.Codec _map_mapStringString_codec
+        = new pbc::MapField<string, string>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForString(18), 114);
+    private readonly pbc::MapField<string, string> mapStringString_ = new pbc::MapField<string, string>();
+    public pbc::MapField<string, string> MapStringString {
+      get { return mapStringString_; }
+    }
+
+    public const int MapInt32BytesFieldNumber = 15;
+    private static readonly pbc::MapField<int, pb::ByteString>.Codec _map_mapInt32Bytes_codec
+        = new pbc::MapField<int, pb::ByteString>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForBytes(18), 122);
+    private readonly pbc::MapField<int, pb::ByteString> mapInt32Bytes_ = new pbc::MapField<int, pb::ByteString>();
+    public pbc::MapField<int, pb::ByteString> MapInt32Bytes {
+      get { return mapInt32Bytes_; }
+    }
+
+    public const int MapInt32EnumFieldNumber = 16;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum>.Codec _map_mapInt32Enum_codec
+        = new pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::Google.Protobuf.TestProtos.MapEnum) x), 130);
+    private readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum> mapInt32Enum_ = new pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum>();
+    public pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum> MapInt32Enum {
+      get { return mapInt32Enum_; }
+    }
+
+    public const int MapInt32ForeignMessageFieldNumber = 17;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage>.Codec _map_mapInt32ForeignMessage_codec
+        = new pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.ForeignMessage.Parser), 138);
+    private readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage> mapInt32ForeignMessage_ = new pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage>();
+    public pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage> MapInt32ForeignMessage {
+      get { return mapInt32ForeignMessage_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestMap);
+    }
+
+    public bool Equals(TestMap other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!MapInt32Int32.Equals(other.MapInt32Int32)) return false;
+      if (!MapInt64Int64.Equals(other.MapInt64Int64)) return false;
+      if (!MapUint32Uint32.Equals(other.MapUint32Uint32)) return false;
+      if (!MapUint64Uint64.Equals(other.MapUint64Uint64)) return false;
+      if (!MapSint32Sint32.Equals(other.MapSint32Sint32)) return false;
+      if (!MapSint64Sint64.Equals(other.MapSint64Sint64)) return false;
+      if (!MapFixed32Fixed32.Equals(other.MapFixed32Fixed32)) return false;
+      if (!MapFixed64Fixed64.Equals(other.MapFixed64Fixed64)) return false;
+      if (!MapSfixed32Sfixed32.Equals(other.MapSfixed32Sfixed32)) return false;
+      if (!MapSfixed64Sfixed64.Equals(other.MapSfixed64Sfixed64)) return false;
+      if (!MapInt32Float.Equals(other.MapInt32Float)) return false;
+      if (!MapInt32Double.Equals(other.MapInt32Double)) return false;
+      if (!MapBoolBool.Equals(other.MapBoolBool)) return false;
+      if (!MapStringString.Equals(other.MapStringString)) return false;
+      if (!MapInt32Bytes.Equals(other.MapInt32Bytes)) return false;
+      if (!MapInt32Enum.Equals(other.MapInt32Enum)) return false;
+      if (!MapInt32ForeignMessage.Equals(other.MapInt32ForeignMessage)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= MapInt32Int32.GetHashCode();
+      hash ^= MapInt64Int64.GetHashCode();
+      hash ^= MapUint32Uint32.GetHashCode();
+      hash ^= MapUint64Uint64.GetHashCode();
+      hash ^= MapSint32Sint32.GetHashCode();
+      hash ^= MapSint64Sint64.GetHashCode();
+      hash ^= MapFixed32Fixed32.GetHashCode();
+      hash ^= MapFixed64Fixed64.GetHashCode();
+      hash ^= MapSfixed32Sfixed32.GetHashCode();
+      hash ^= MapSfixed64Sfixed64.GetHashCode();
+      hash ^= MapInt32Float.GetHashCode();
+      hash ^= MapInt32Double.GetHashCode();
+      hash ^= MapBoolBool.GetHashCode();
+      hash ^= MapStringString.GetHashCode();
+      hash ^= MapInt32Bytes.GetHashCode();
+      hash ^= MapInt32Enum.GetHashCode();
+      hash ^= MapInt32ForeignMessage.GetHashCode();
+      return hash;
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      mapInt32Int32_.WriteTo(output, _map_mapInt32Int32_codec);
+      mapInt64Int64_.WriteTo(output, _map_mapInt64Int64_codec);
+      mapUint32Uint32_.WriteTo(output, _map_mapUint32Uint32_codec);
+      mapUint64Uint64_.WriteTo(output, _map_mapUint64Uint64_codec);
+      mapSint32Sint32_.WriteTo(output, _map_mapSint32Sint32_codec);
+      mapSint64Sint64_.WriteTo(output, _map_mapSint64Sint64_codec);
+      mapFixed32Fixed32_.WriteTo(output, _map_mapFixed32Fixed32_codec);
+      mapFixed64Fixed64_.WriteTo(output, _map_mapFixed64Fixed64_codec);
+      mapSfixed32Sfixed32_.WriteTo(output, _map_mapSfixed32Sfixed32_codec);
+      mapSfixed64Sfixed64_.WriteTo(output, _map_mapSfixed64Sfixed64_codec);
+      mapInt32Float_.WriteTo(output, _map_mapInt32Float_codec);
+      mapInt32Double_.WriteTo(output, _map_mapInt32Double_codec);
+      mapBoolBool_.WriteTo(output, _map_mapBoolBool_codec);
+      mapStringString_.WriteTo(output, _map_mapStringString_codec);
+      mapInt32Bytes_.WriteTo(output, _map_mapInt32Bytes_codec);
+      mapInt32Enum_.WriteTo(output, _map_mapInt32Enum_codec);
+      mapInt32ForeignMessage_.WriteTo(output, _map_mapInt32ForeignMessage_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += mapInt32Int32_.CalculateSize(_map_mapInt32Int32_codec);
+      size += mapInt64Int64_.CalculateSize(_map_mapInt64Int64_codec);
+      size += mapUint32Uint32_.CalculateSize(_map_mapUint32Uint32_codec);
+      size += mapUint64Uint64_.CalculateSize(_map_mapUint64Uint64_codec);
+      size += mapSint32Sint32_.CalculateSize(_map_mapSint32Sint32_codec);
+      size += mapSint64Sint64_.CalculateSize(_map_mapSint64Sint64_codec);
+      size += mapFixed32Fixed32_.CalculateSize(_map_mapFixed32Fixed32_codec);
+      size += mapFixed64Fixed64_.CalculateSize(_map_mapFixed64Fixed64_codec);
+      size += mapSfixed32Sfixed32_.CalculateSize(_map_mapSfixed32Sfixed32_codec);
+      size += mapSfixed64Sfixed64_.CalculateSize(_map_mapSfixed64Sfixed64_codec);
+      size += mapInt32Float_.CalculateSize(_map_mapInt32Float_codec);
+      size += mapInt32Double_.CalculateSize(_map_mapInt32Double_codec);
+      size += mapBoolBool_.CalculateSize(_map_mapBoolBool_codec);
+      size += mapStringString_.CalculateSize(_map_mapStringString_codec);
+      size += mapInt32Bytes_.CalculateSize(_map_mapInt32Bytes_codec);
+      size += mapInt32Enum_.CalculateSize(_map_mapInt32Enum_codec);
+      size += mapInt32ForeignMessage_.CalculateSize(_map_mapInt32ForeignMessage_codec);
+      return size;
+    }
+
+    public void MergeFrom(TestMap other) {
+      if (other == null) {
+        return;
+      }
+      mapInt32Int32_.Add(other.mapInt32Int32_);
+      mapInt64Int64_.Add(other.mapInt64Int64_);
+      mapUint32Uint32_.Add(other.mapUint32Uint32_);
+      mapUint64Uint64_.Add(other.mapUint64Uint64_);
+      mapSint32Sint32_.Add(other.mapSint32Sint32_);
+      mapSint64Sint64_.Add(other.mapSint64Sint64_);
+      mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_);
+      mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_);
+      mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_);
+      mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_);
+      mapInt32Float_.Add(other.mapInt32Float_);
+      mapInt32Double_.Add(other.mapInt32Double_);
+      mapBoolBool_.Add(other.mapBoolBool_);
+      mapStringString_.Add(other.mapStringString_);
+      mapInt32Bytes_.Add(other.mapInt32Bytes_);
+      mapInt32Enum_.Add(other.mapInt32Enum_);
+      mapInt32ForeignMessage_.Add(other.mapInt32ForeignMessage_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while (input.ReadTag(out tag)) {
+        switch(tag) {
+          case 0:
+            throw pb::InvalidProtocolBufferException.InvalidTag();
+          default:
+            if (pb::WireFormat.IsEndGroupTag(tag)) {
+              return;
+            }
+            break;
+          case 10: {
+            mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec);
+            break;
+          }
+          case 18: {
+            mapInt64Int64_.AddEntriesFrom(input, _map_mapInt64Int64_codec);
+            break;
+          }
+          case 26: {
+            mapUint32Uint32_.AddEntriesFrom(input, _map_mapUint32Uint32_codec);
+            break;
+          }
+          case 34: {
+            mapUint64Uint64_.AddEntriesFrom(input, _map_mapUint64Uint64_codec);
+            break;
+          }
+          case 42: {
+            mapSint32Sint32_.AddEntriesFrom(input, _map_mapSint32Sint32_codec);
+            break;
+          }
+          case 50: {
+            mapSint64Sint64_.AddEntriesFrom(input, _map_mapSint64Sint64_codec);
+            break;
+          }
+          case 58: {
+            mapFixed32Fixed32_.AddEntriesFrom(input, _map_mapFixed32Fixed32_codec);
+            break;
+          }
+          case 66: {
+            mapFixed64Fixed64_.AddEntriesFrom(input, _map_mapFixed64Fixed64_codec);
+            break;
+          }
+          case 74: {
+            mapSfixed32Sfixed32_.AddEntriesFrom(input, _map_mapSfixed32Sfixed32_codec);
+            break;
+          }
+          case 82: {
+            mapSfixed64Sfixed64_.AddEntriesFrom(input, _map_mapSfixed64Sfixed64_codec);
+            break;
+          }
+          case 90: {
+            mapInt32Float_.AddEntriesFrom(input, _map_mapInt32Float_codec);
+            break;
+          }
+          case 98: {
+            mapInt32Double_.AddEntriesFrom(input, _map_mapInt32Double_codec);
+            break;
+          }
+          case 106: {
+            mapBoolBool_.AddEntriesFrom(input, _map_mapBoolBool_codec);
+            break;
+          }
+          case 114: {
+            mapStringString_.AddEntriesFrom(input, _map_mapStringString_codec);
+            break;
+          }
+          case 122: {
+            mapInt32Bytes_.AddEntriesFrom(input, _map_mapInt32Bytes_codec);
+            break;
+          }
+          case 130: {
+            mapInt32Enum_.AddEntriesFrom(input, _map_mapInt32Enum_codec);
+            break;
+          }
+          case 138: {
+            mapInt32ForeignMessage_.AddEntriesFrom(input, _map_mapInt32ForeignMessage_codec);
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapInt32Int32Entry : pb::IMessage<MapInt32Int32Entry> {
+        private static readonly pb::MessageParser<MapInt32Int32Entry> _parser = new pb::MessageParser<MapInt32Int32Entry>(() => new MapInt32Int32Entry());
+        public static pb::MessageParser<MapInt32Int32Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32Int32Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapInt32Int32Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32Int32Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapInt32Int32Entry() { }
+
+        public MapInt32Int32Entry(MapInt32Int32Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapInt32Int32Entry Clone() {
+          return new MapInt32Int32Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private int key_;
+        public int Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private int value_;
+        public int Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapInt32Int32Entry);
+        }
+
+        public bool Equals(MapInt32Int32Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (Value != 0) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Key);
+          }
+          if (Value != 0) {
+            output.WriteRawTag(16);
+            output.WriteInt32(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Key);
+          }
+          if (Value != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapInt32Int32Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.Value != 0) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadInt32();
+                break;
+              }
+              case 16: {
+                Value = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapInt64Int64Entry : pb::IMessage<MapInt64Int64Entry> {
+        private static readonly pb::MessageParser<MapInt64Int64Entry> _parser = new pb::MessageParser<MapInt64Int64Entry>(() => new MapInt64Int64Entry());
+        public static pb::MessageParser<MapInt64Int64Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt64Int64Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapInt64Int64Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt64Int64Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapInt64Int64Entry() { }
+
+        public MapInt64Int64Entry(MapInt64Int64Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapInt64Int64Entry Clone() {
+          return new MapInt64Int64Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private long key_;
+        public long Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private long value_;
+        public long Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapInt64Int64Entry);
+        }
+
+        public bool Equals(MapInt64Int64Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0L) hash ^= Key.GetHashCode();
+          if (Value != 0L) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0L) {
+            output.WriteRawTag(8);
+            output.WriteInt64(Key);
+          }
+          if (Value != 0L) {
+            output.WriteRawTag(16);
+            output.WriteInt64(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0L) {
+            size += 1 + pb::CodedOutputStream.ComputeInt64Size(Key);
+          }
+          if (Value != 0L) {
+            size += 1 + pb::CodedOutputStream.ComputeInt64Size(Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapInt64Int64Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0L) {
+            Key = other.Key;
+          }
+          if (other.Value != 0L) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadInt64();
+                break;
+              }
+              case 16: {
+                Value = input.ReadInt64();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapUint32Uint32Entry : pb::IMessage<MapUint32Uint32Entry> {
+        private static readonly pb::MessageParser<MapUint32Uint32Entry> _parser = new pb::MessageParser<MapUint32Uint32Entry>(() => new MapUint32Uint32Entry());
+        public static pb::MessageParser<MapUint32Uint32Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapUint32Uint32Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapUint32Uint32Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapUint32Uint32Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapUint32Uint32Entry() { }
+
+        public MapUint32Uint32Entry(MapUint32Uint32Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapUint32Uint32Entry Clone() {
+          return new MapUint32Uint32Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private uint key_;
+        public uint Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private uint value_;
+        public uint Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapUint32Uint32Entry);
+        }
+
+        public bool Equals(MapUint32Uint32Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (Value != 0) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(8);
+            output.WriteUInt32(Key);
+          }
+          if (Value != 0) {
+            output.WriteRawTag(16);
+            output.WriteUInt32(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Key);
+          }
+          if (Value != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapUint32Uint32Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.Value != 0) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadUInt32();
+                break;
+              }
+              case 16: {
+                Value = input.ReadUInt32();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapUint64Uint64Entry : pb::IMessage<MapUint64Uint64Entry> {
+        private static readonly pb::MessageParser<MapUint64Uint64Entry> _parser = new pb::MessageParser<MapUint64Uint64Entry>(() => new MapUint64Uint64Entry());
+        public static pb::MessageParser<MapUint64Uint64Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapUint64Uint64Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapUint64Uint64Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapUint64Uint64Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapUint64Uint64Entry() { }
+
+        public MapUint64Uint64Entry(MapUint64Uint64Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapUint64Uint64Entry Clone() {
+          return new MapUint64Uint64Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private ulong key_;
+        public ulong Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private ulong value_;
+        public ulong Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapUint64Uint64Entry);
+        }
+
+        public bool Equals(MapUint64Uint64Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0UL) hash ^= Key.GetHashCode();
+          if (Value != 0UL) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0UL) {
+            output.WriteRawTag(8);
+            output.WriteUInt64(Key);
+          }
+          if (Value != 0UL) {
+            output.WriteRawTag(16);
+            output.WriteUInt64(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0UL) {
+            size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Key);
+          }
+          if (Value != 0UL) {
+            size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapUint64Uint64Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0UL) {
+            Key = other.Key;
+          }
+          if (other.Value != 0UL) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadUInt64();
+                break;
+              }
+              case 16: {
+                Value = input.ReadUInt64();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapSint32Sint32Entry : pb::IMessage<MapSint32Sint32Entry> {
+        private static readonly pb::MessageParser<MapSint32Sint32Entry> _parser = new pb::MessageParser<MapSint32Sint32Entry>(() => new MapSint32Sint32Entry());
+        public static pb::MessageParser<MapSint32Sint32Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapSint32Sint32Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapSint32Sint32Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapSint32Sint32Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapSint32Sint32Entry() { }
+
+        public MapSint32Sint32Entry(MapSint32Sint32Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapSint32Sint32Entry Clone() {
+          return new MapSint32Sint32Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private int key_;
+        public int Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private int value_;
+        public int Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapSint32Sint32Entry);
+        }
+
+        public bool Equals(MapSint32Sint32Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (Value != 0) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(8);
+            output.WriteSInt32(Key);
+          }
+          if (Value != 0) {
+            output.WriteRawTag(16);
+            output.WriteSInt32(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeSInt32Size(Key);
+          }
+          if (Value != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeSInt32Size(Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapSint32Sint32Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.Value != 0) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadSInt32();
+                break;
+              }
+              case 16: {
+                Value = input.ReadSInt32();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapSint64Sint64Entry : pb::IMessage<MapSint64Sint64Entry> {
+        private static readonly pb::MessageParser<MapSint64Sint64Entry> _parser = new pb::MessageParser<MapSint64Sint64Entry>(() => new MapSint64Sint64Entry());
+        public static pb::MessageParser<MapSint64Sint64Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapSint64Sint64Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapSint64Sint64Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapSint64Sint64Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapSint64Sint64Entry() { }
+
+        public MapSint64Sint64Entry(MapSint64Sint64Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapSint64Sint64Entry Clone() {
+          return new MapSint64Sint64Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private long key_;
+        public long Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private long value_;
+        public long Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapSint64Sint64Entry);
+        }
+
+        public bool Equals(MapSint64Sint64Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0L) hash ^= Key.GetHashCode();
+          if (Value != 0L) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0L) {
+            output.WriteRawTag(8);
+            output.WriteSInt64(Key);
+          }
+          if (Value != 0L) {
+            output.WriteRawTag(16);
+            output.WriteSInt64(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0L) {
+            size += 1 + pb::CodedOutputStream.ComputeSInt64Size(Key);
+          }
+          if (Value != 0L) {
+            size += 1 + pb::CodedOutputStream.ComputeSInt64Size(Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapSint64Sint64Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0L) {
+            Key = other.Key;
+          }
+          if (other.Value != 0L) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadSInt64();
+                break;
+              }
+              case 16: {
+                Value = input.ReadSInt64();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapFixed32Fixed32Entry : pb::IMessage<MapFixed32Fixed32Entry> {
+        private static readonly pb::MessageParser<MapFixed32Fixed32Entry> _parser = new pb::MessageParser<MapFixed32Fixed32Entry>(() => new MapFixed32Fixed32Entry());
+        public static pb::MessageParser<MapFixed32Fixed32Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 13, 21 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapFixed32Fixed32Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapFixed32Fixed32Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapFixed32Fixed32Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapFixed32Fixed32Entry() { }
+
+        public MapFixed32Fixed32Entry(MapFixed32Fixed32Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapFixed32Fixed32Entry Clone() {
+          return new MapFixed32Fixed32Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private uint key_;
+        public uint Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private uint value_;
+        public uint Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapFixed32Fixed32Entry);
+        }
+
+        public bool Equals(MapFixed32Fixed32Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (Value != 0) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(13);
+            output.WriteFixed32(Key);
+          }
+          if (Value != 0) {
+            output.WriteRawTag(21);
+            output.WriteFixed32(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + 4;
+          }
+          if (Value != 0) {
+            size += 1 + 4;
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapFixed32Fixed32Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.Value != 0) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 13: {
+                Key = input.ReadFixed32();
+                break;
+              }
+              case 21: {
+                Value = input.ReadFixed32();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapFixed64Fixed64Entry : pb::IMessage<MapFixed64Fixed64Entry> {
+        private static readonly pb::MessageParser<MapFixed64Fixed64Entry> _parser = new pb::MessageParser<MapFixed64Fixed64Entry>(() => new MapFixed64Fixed64Entry());
+        public static pb::MessageParser<MapFixed64Fixed64Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 9, 17 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapFixed64Fixed64Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapFixed64Fixed64Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapFixed64Fixed64Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapFixed64Fixed64Entry() { }
+
+        public MapFixed64Fixed64Entry(MapFixed64Fixed64Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapFixed64Fixed64Entry Clone() {
+          return new MapFixed64Fixed64Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private ulong key_;
+        public ulong Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private ulong value_;
+        public ulong Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapFixed64Fixed64Entry);
+        }
+
+        public bool Equals(MapFixed64Fixed64Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0UL) hash ^= Key.GetHashCode();
+          if (Value != 0UL) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0UL) {
+            output.WriteRawTag(9);
+            output.WriteFixed64(Key);
+          }
+          if (Value != 0UL) {
+            output.WriteRawTag(17);
+            output.WriteFixed64(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0UL) {
+            size += 1 + 8;
+          }
+          if (Value != 0UL) {
+            size += 1 + 8;
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapFixed64Fixed64Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0UL) {
+            Key = other.Key;
+          }
+          if (other.Value != 0UL) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 9: {
+                Key = input.ReadFixed64();
+                break;
+              }
+              case 17: {
+                Value = input.ReadFixed64();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapSfixed32Sfixed32Entry : pb::IMessage<MapSfixed32Sfixed32Entry> {
+        private static readonly pb::MessageParser<MapSfixed32Sfixed32Entry> _parser = new pb::MessageParser<MapSfixed32Sfixed32Entry>(() => new MapSfixed32Sfixed32Entry());
+        public static pb::MessageParser<MapSfixed32Sfixed32Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 13, 21 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapSfixed32Sfixed32Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapSfixed32Sfixed32Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapSfixed32Sfixed32Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapSfixed32Sfixed32Entry() { }
+
+        public MapSfixed32Sfixed32Entry(MapSfixed32Sfixed32Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapSfixed32Sfixed32Entry Clone() {
+          return new MapSfixed32Sfixed32Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private int key_;
+        public int Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private int value_;
+        public int Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapSfixed32Sfixed32Entry);
+        }
+
+        public bool Equals(MapSfixed32Sfixed32Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (Value != 0) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(13);
+            output.WriteSFixed32(Key);
+          }
+          if (Value != 0) {
+            output.WriteRawTag(21);
+            output.WriteSFixed32(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + 4;
+          }
+          if (Value != 0) {
+            size += 1 + 4;
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapSfixed32Sfixed32Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.Value != 0) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 13: {
+                Key = input.ReadSFixed32();
+                break;
+              }
+              case 21: {
+                Value = input.ReadSFixed32();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapSfixed64Sfixed64Entry : pb::IMessage<MapSfixed64Sfixed64Entry> {
+        private static readonly pb::MessageParser<MapSfixed64Sfixed64Entry> _parser = new pb::MessageParser<MapSfixed64Sfixed64Entry>(() => new MapSfixed64Sfixed64Entry());
+        public static pb::MessageParser<MapSfixed64Sfixed64Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 9, 17 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapSfixed64Sfixed64Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapSfixed64Sfixed64Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapSfixed64Sfixed64Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapSfixed64Sfixed64Entry() { }
+
+        public MapSfixed64Sfixed64Entry(MapSfixed64Sfixed64Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapSfixed64Sfixed64Entry Clone() {
+          return new MapSfixed64Sfixed64Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private long key_;
+        public long Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private long value_;
+        public long Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapSfixed64Sfixed64Entry);
+        }
+
+        public bool Equals(MapSfixed64Sfixed64Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0L) hash ^= Key.GetHashCode();
+          if (Value != 0L) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0L) {
+            output.WriteRawTag(9);
+            output.WriteSFixed64(Key);
+          }
+          if (Value != 0L) {
+            output.WriteRawTag(17);
+            output.WriteSFixed64(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0L) {
+            size += 1 + 8;
+          }
+          if (Value != 0L) {
+            size += 1 + 8;
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapSfixed64Sfixed64Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0L) {
+            Key = other.Key;
+          }
+          if (other.Value != 0L) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 9: {
+                Key = input.ReadSFixed64();
+                break;
+              }
+              case 17: {
+                Value = input.ReadSFixed64();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapInt32FloatEntry : pb::IMessage<MapInt32FloatEntry> {
+        private static readonly pb::MessageParser<MapInt32FloatEntry> _parser = new pb::MessageParser<MapInt32FloatEntry>(() => new MapInt32FloatEntry());
+        public static pb::MessageParser<MapInt32FloatEntry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 21 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32FloatEntry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapInt32FloatEntry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32FloatEntry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapInt32FloatEntry() { }
+
+        public MapInt32FloatEntry(MapInt32FloatEntry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapInt32FloatEntry Clone() {
+          return new MapInt32FloatEntry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private int key_;
+        public int Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private float value_;
+        public float Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapInt32FloatEntry);
+        }
+
+        public bool Equals(MapInt32FloatEntry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (Value != 0F) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Key);
+          }
+          if (Value != 0F) {
+            output.WriteRawTag(21);
+            output.WriteFloat(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Key);
+          }
+          if (Value != 0F) {
+            size += 1 + 4;
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapInt32FloatEntry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.Value != 0F) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadInt32();
+                break;
+              }
+              case 21: {
+                Value = input.ReadFloat();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapInt32DoubleEntry : pb::IMessage<MapInt32DoubleEntry> {
+        private static readonly pb::MessageParser<MapInt32DoubleEntry> _parser = new pb::MessageParser<MapInt32DoubleEntry>(() => new MapInt32DoubleEntry());
+        public static pb::MessageParser<MapInt32DoubleEntry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 17 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32DoubleEntry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapInt32DoubleEntry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32DoubleEntry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapInt32DoubleEntry() { }
+
+        public MapInt32DoubleEntry(MapInt32DoubleEntry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapInt32DoubleEntry Clone() {
+          return new MapInt32DoubleEntry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private int key_;
+        public int Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private double value_;
+        public double Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapInt32DoubleEntry);
+        }
+
+        public bool Equals(MapInt32DoubleEntry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (Value != 0D) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Key);
+          }
+          if (Value != 0D) {
+            output.WriteRawTag(17);
+            output.WriteDouble(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Key);
+          }
+          if (Value != 0D) {
+            size += 1 + 8;
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapInt32DoubleEntry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.Value != 0D) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadInt32();
+                break;
+              }
+              case 17: {
+                Value = input.ReadDouble();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapBoolBoolEntry : pb::IMessage<MapBoolBoolEntry> {
+        private static readonly pb::MessageParser<MapBoolBoolEntry> _parser = new pb::MessageParser<MapBoolBoolEntry>(() => new MapBoolBoolEntry());
+        public static pb::MessageParser<MapBoolBoolEntry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapBoolBoolEntry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapBoolBoolEntry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapBoolBoolEntry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapBoolBoolEntry() { }
+
+        public MapBoolBoolEntry(MapBoolBoolEntry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapBoolBoolEntry Clone() {
+          return new MapBoolBoolEntry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private bool key_;
+        public bool Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private bool value_;
+        public bool Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapBoolBoolEntry);
+        }
+
+        public bool Equals(MapBoolBoolEntry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != false) hash ^= Key.GetHashCode();
+          if (Value != false) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != false) {
+            output.WriteRawTag(8);
+            output.WriteBool(Key);
+          }
+          if (Value != false) {
+            output.WriteRawTag(16);
+            output.WriteBool(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != false) {
+            size += 1 + 1;
+          }
+          if (Value != false) {
+            size += 1 + 1;
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapBoolBoolEntry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != false) {
+            Key = other.Key;
+          }
+          if (other.Value != false) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadBool();
+                break;
+              }
+              case 16: {
+                Value = input.ReadBool();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapStringStringEntry : pb::IMessage<MapStringStringEntry> {
+        private static readonly pb::MessageParser<MapStringStringEntry> _parser = new pb::MessageParser<MapStringStringEntry>(() => new MapStringStringEntry());
+        public static pb::MessageParser<MapStringStringEntry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 10, 18 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapStringStringEntry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapStringStringEntry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapStringStringEntry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapStringStringEntry() { }
+
+        public MapStringStringEntry(MapStringStringEntry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapStringStringEntry Clone() {
+          return new MapStringStringEntry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private string key_ = "";
+        public string Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value ?? "";
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private string value_ = "";
+        public string Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value ?? "";
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapStringStringEntry);
+        }
+
+        public bool Equals(MapStringStringEntry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key.Length != 0) hash ^= Key.GetHashCode();
+          if (Value.Length != 0) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key.Length != 0) {
+            output.WriteRawTag(10);
+            output.WriteString(Key);
+          }
+          if (Value.Length != 0) {
+            output.WriteRawTag(18);
+            output.WriteString(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key.Length != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeStringSize(Key);
+          }
+          if (Value.Length != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeStringSize(Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapStringStringEntry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key.Length != 0) {
+            Key = other.Key;
+          }
+          if (other.Value.Length != 0) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 10: {
+                Key = input.ReadString();
+                break;
+              }
+              case 18: {
+                Value = input.ReadString();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapInt32BytesEntry : pb::IMessage<MapInt32BytesEntry> {
+        private static readonly pb::MessageParser<MapInt32BytesEntry> _parser = new pb::MessageParser<MapInt32BytesEntry>(() => new MapInt32BytesEntry());
+        public static pb::MessageParser<MapInt32BytesEntry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 18 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32BytesEntry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapInt32BytesEntry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32BytesEntry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapInt32BytesEntry() { }
+
+        public MapInt32BytesEntry(MapInt32BytesEntry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapInt32BytesEntry Clone() {
+          return new MapInt32BytesEntry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private int key_;
+        public int Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private pb::ByteString value_ = pb::ByteString.Empty;
+        public pb::ByteString Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value ?? pb::ByteString.Empty;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapInt32BytesEntry);
+        }
+
+        public bool Equals(MapInt32BytesEntry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (Value.Length != 0) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Key);
+          }
+          if (Value.Length != 0) {
+            output.WriteRawTag(18);
+            output.WriteBytes(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Key);
+          }
+          if (Value.Length != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeBytesSize(Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapInt32BytesEntry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.Value.Length != 0) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadInt32();
+                break;
+              }
+              case 18: {
+                Value = input.ReadBytes();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapInt32EnumEntry : pb::IMessage<MapInt32EnumEntry> {
+        private static readonly pb::MessageParser<MapInt32EnumEntry> _parser = new pb::MessageParser<MapInt32EnumEntry>(() => new MapInt32EnumEntry());
+        public static pb::MessageParser<MapInt32EnumEntry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32EnumEntry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapInt32EnumEntry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32EnumEntry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapInt32EnumEntry() { }
+
+        public MapInt32EnumEntry(MapInt32EnumEntry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapInt32EnumEntry Clone() {
+          return new MapInt32EnumEntry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private int key_;
+        public int Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private global::Google.Protobuf.TestProtos.MapEnum value_ = global::Google.Protobuf.TestProtos.MapEnum.MAP_ENUM_FOO;
+        public global::Google.Protobuf.TestProtos.MapEnum Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapInt32EnumEntry);
+        }
+
+        public bool Equals(MapInt32EnumEntry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (Value != global::Google.Protobuf.TestProtos.MapEnum.MAP_ENUM_FOO) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Key);
+          }
+          if (Value != global::Google.Protobuf.TestProtos.MapEnum.MAP_ENUM_FOO) {
+            output.WriteRawTag(16);
+            output.WriteEnum((int) Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Key);
+          }
+          if (Value != global::Google.Protobuf.TestProtos.MapEnum.MAP_ENUM_FOO) {
+            size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapInt32EnumEntry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.Value != global::Google.Protobuf.TestProtos.MapEnum.MAP_ENUM_FOO) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadInt32();
+                break;
+              }
+              case 16: {
+                value_ = (global::Google.Protobuf.TestProtos.MapEnum) input.ReadEnum();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapInt32ForeignMessageEntry : pb::IMessage<MapInt32ForeignMessageEntry> {
+        private static readonly pb::MessageParser<MapInt32ForeignMessageEntry> _parser = new pb::MessageParser<MapInt32ForeignMessageEntry>(() => new MapInt32ForeignMessageEntry());
+        public static pb::MessageParser<MapInt32ForeignMessageEntry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 18 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32ForeignMessageEntry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapInt32ForeignMessageEntry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMap_MapInt32ForeignMessageEntry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapInt32ForeignMessageEntry() { }
+
+        public MapInt32ForeignMessageEntry(MapInt32ForeignMessageEntry other) {
+          key_ = other.key_;
+          Value = other.value_ != null ? other.Value.Clone() : null;
+        }
+
+        public MapInt32ForeignMessageEntry Clone() {
+          return new MapInt32ForeignMessageEntry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+          if (value_ != null) Value.Freeze();
+        }
+
+        public const int KeyFieldNumber = 1;
+        private int key_;
+        public int Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private global::Google.Protobuf.TestProtos.ForeignMessage value_;
+        public global::Google.Protobuf.TestProtos.ForeignMessage Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapInt32ForeignMessageEntry);
+        }
+
+        public bool Equals(MapInt32ForeignMessageEntry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (!object.Equals(Value, other.Value)) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (value_ != null) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Key);
+          }
+          if (value_ != null) {
+            output.WriteRawTag(18);
+            output.WriteMessage(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Key);
+          }
+          if (value_ != null) {
+            size += 1 + pb::CodedOutputStream.ComputeMessageSize(Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapInt32ForeignMessageEntry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.value_ != null) {
+            if (value_ == null) {
+              value_ = new global::Google.Protobuf.TestProtos.ForeignMessage();
+            }
+            Value.MergeFrom(other.Value);
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadInt32();
+                break;
+              }
+              case 18: {
+                if (value_ == null) {
+                  value_ = new global::Google.Protobuf.TestProtos.ForeignMessage();
+                }
+                input.ReadMessage(value_);
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestMapSubmessage : pb::IMessage<TestMapSubmessage> {
+    private static readonly pb::MessageParser<TestMapSubmessage> _parser = new pb::MessageParser<TestMapSubmessage>(() => new TestMapSubmessage());
+    public static pb::MessageParser<TestMapSubmessage> Parser { get { return _parser; } }
+
+    private static readonly string[] _fieldNames = new string[] { "test_map" };
+    private static readonly uint[] _fieldTags = new uint[] { 10 };
+    public static pbd::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMapSubmessage__Descriptor; }
+    }
+
+    public pb::FieldAccess.FieldAccessorTable<TestMapSubmessage> Fields {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMapSubmessage__FieldAccessorTable; }
+    }
+
+    private bool _frozen = false;
+    public bool IsFrozen { get { return _frozen; } }
+
+    public TestMapSubmessage() { }
+
+    public TestMapSubmessage(TestMapSubmessage other) {
+      TestMap = other.testMap_ != null ? other.TestMap.Clone() : null;
+    }
+
+    public TestMapSubmessage Clone() {
+      return new TestMapSubmessage(this);
+    }
+
+    public void Freeze() {
+      if (IsFrozen) {
+        return;
+      }
+      _frozen = true;
+      if (testMap_ != null) TestMap.Freeze();
+    }
+
+    public const int TestMapFieldNumber = 1;
+    private global::Google.Protobuf.TestProtos.TestMap testMap_;
+    public global::Google.Protobuf.TestProtos.TestMap TestMap {
+      get { return testMap_; }
+      set {
+        pb::Freezable.CheckMutable(this);
+        testMap_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestMapSubmessage);
+    }
+
+    public bool Equals(TestMapSubmessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(TestMap, other.TestMap)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (testMap_ != null) hash ^= TestMap.GetHashCode();
+      return hash;
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (testMap_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(TestMap);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (testMap_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(TestMap);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestMapSubmessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.testMap_ != null) {
+        if (testMap_ == null) {
+          testMap_ = new global::Google.Protobuf.TestProtos.TestMap();
+        }
+        TestMap.MergeFrom(other.TestMap);
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while (input.ReadTag(out tag)) {
+        switch(tag) {
+          case 0:
+            throw pb::InvalidProtocolBufferException.InvalidTag();
+          default:
+            if (pb::WireFormat.IsEndGroupTag(tag)) {
+              return;
+            }
+            break;
+          case 10: {
+            if (testMap_ == null) {
+              testMap_ = new global::Google.Protobuf.TestProtos.TestMap();
+            }
+            input.ReadMessage(testMap_);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestMessageMap : pb::IMessage<TestMessageMap> {
+    private static readonly pb::MessageParser<TestMessageMap> _parser = new pb::MessageParser<TestMessageMap>(() => new TestMessageMap());
+    public static pb::MessageParser<TestMessageMap> Parser { get { return _parser; } }
+
+    private static readonly string[] _fieldNames = new string[] { "map_int32_message" };
+    private static readonly uint[] _fieldTags = new uint[] { 10 };
+    public static pbd::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMessageMap__Descriptor; }
+    }
+
+    public pb::FieldAccess.FieldAccessorTable<TestMessageMap> Fields {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMessageMap__FieldAccessorTable; }
+    }
+
+    private bool _frozen = false;
+    public bool IsFrozen { get { return _frozen; } }
+
+    public TestMessageMap() { }
+
+    public TestMessageMap(TestMessageMap other) {
+      mapInt32Message_ = other.mapInt32Message_.Clone();
+    }
+
+    public TestMessageMap Clone() {
+      return new TestMessageMap(this);
+    }
+
+    public void Freeze() {
+      if (IsFrozen) {
+        return;
+      }
+      _frozen = true;
+      mapInt32Message_.Freeze();
+    }
+
+    public const int MapInt32MessageFieldNumber = 1;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.TestAllTypes>.Codec _map_mapInt32Message_codec
+        = new pbc::MapField<int, global::Google.Protobuf.TestProtos.TestAllTypes>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.TestAllTypes.Parser), 10);
+    private readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.TestAllTypes> mapInt32Message_ = new pbc::MapField<int, global::Google.Protobuf.TestProtos.TestAllTypes>();
+    public pbc::MapField<int, global::Google.Protobuf.TestProtos.TestAllTypes> MapInt32Message {
+      get { return mapInt32Message_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestMessageMap);
+    }
+
+    public bool Equals(TestMessageMap other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!MapInt32Message.Equals(other.MapInt32Message)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= MapInt32Message.GetHashCode();
+      return hash;
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      mapInt32Message_.WriteTo(output, _map_mapInt32Message_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += mapInt32Message_.CalculateSize(_map_mapInt32Message_codec);
+      return size;
+    }
+
+    public void MergeFrom(TestMessageMap other) {
+      if (other == null) {
+        return;
+      }
+      mapInt32Message_.Add(other.mapInt32Message_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while (input.ReadTag(out tag)) {
+        switch(tag) {
+          case 0:
+            throw pb::InvalidProtocolBufferException.InvalidTag();
+          default:
+            if (pb::WireFormat.IsEndGroupTag(tag)) {
+              return;
+            }
+            break;
+          case 10: {
+            mapInt32Message_.AddEntriesFrom(input, _map_mapInt32Message_codec);
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapInt32MessageEntry : pb::IMessage<MapInt32MessageEntry> {
+        private static readonly pb::MessageParser<MapInt32MessageEntry> _parser = new pb::MessageParser<MapInt32MessageEntry>(() => new MapInt32MessageEntry());
+        public static pb::MessageParser<MapInt32MessageEntry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 18 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMessageMap_MapInt32MessageEntry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapInt32MessageEntry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestMessageMap_MapInt32MessageEntry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapInt32MessageEntry() { }
+
+        public MapInt32MessageEntry(MapInt32MessageEntry other) {
+          key_ = other.key_;
+          Value = other.value_ != null ? other.Value.Clone() : null;
+        }
+
+        public MapInt32MessageEntry Clone() {
+          return new MapInt32MessageEntry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+          if (value_ != null) Value.Freeze();
+        }
+
+        public const int KeyFieldNumber = 1;
+        private int key_;
+        public int Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private global::Google.Protobuf.TestProtos.TestAllTypes value_;
+        public global::Google.Protobuf.TestProtos.TestAllTypes Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapInt32MessageEntry);
+        }
+
+        public bool Equals(MapInt32MessageEntry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (!object.Equals(Value, other.Value)) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (value_ != null) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Key);
+          }
+          if (value_ != null) {
+            output.WriteRawTag(18);
+            output.WriteMessage(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Key);
+          }
+          if (value_ != null) {
+            size += 1 + pb::CodedOutputStream.ComputeMessageSize(Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapInt32MessageEntry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.value_ != null) {
+            if (value_ == null) {
+              value_ = new global::Google.Protobuf.TestProtos.TestAllTypes();
+            }
+            Value.MergeFrom(other.Value);
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadInt32();
+                break;
+              }
+              case 18: {
+                if (value_ == null) {
+                  value_ = new global::Google.Protobuf.TestProtos.TestAllTypes();
+                }
+                input.ReadMessage(value_);
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestSameTypeMap : pb::IMessage<TestSameTypeMap> {
+    private static readonly pb::MessageParser<TestSameTypeMap> _parser = new pb::MessageParser<TestSameTypeMap>(() => new TestSameTypeMap());
+    public static pb::MessageParser<TestSameTypeMap> Parser { get { return _parser; } }
+
+    private static readonly string[] _fieldNames = new string[] { "map1", "map2" };
+    private static readonly uint[] _fieldTags = new uint[] { 10, 18 };
+    public static pbd::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestSameTypeMap__Descriptor; }
+    }
+
+    public pb::FieldAccess.FieldAccessorTable<TestSameTypeMap> Fields {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestSameTypeMap__FieldAccessorTable; }
+    }
+
+    private bool _frozen = false;
+    public bool IsFrozen { get { return _frozen; } }
+
+    public TestSameTypeMap() { }
+
+    public TestSameTypeMap(TestSameTypeMap other) {
+      map1_ = other.map1_.Clone();
+      map2_ = other.map2_.Clone();
+    }
+
+    public TestSameTypeMap Clone() {
+      return new TestSameTypeMap(this);
+    }
+
+    public void Freeze() {
+      if (IsFrozen) {
+        return;
+      }
+      _frozen = true;
+      map1_.Freeze();
+      map2_.Freeze();
+    }
+
+    public const int Map1FieldNumber = 1;
+    private static readonly pbc::MapField<int, int>.Codec _map_map1_codec
+        = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForInt32(16), 10);
+    private readonly pbc::MapField<int, int> map1_ = new pbc::MapField<int, int>();
+    public pbc::MapField<int, int> Map1 {
+      get { return map1_; }
+    }
+
+    public const int Map2FieldNumber = 2;
+    private static readonly pbc::MapField<int, int>.Codec _map_map2_codec
+        = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForInt32(16), 18);
+    private readonly pbc::MapField<int, int> map2_ = new pbc::MapField<int, int>();
+    public pbc::MapField<int, int> Map2 {
+      get { return map2_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestSameTypeMap);
+    }
+
+    public bool Equals(TestSameTypeMap other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!Map1.Equals(other.Map1)) return false;
+      if (!Map2.Equals(other.Map2)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= Map1.GetHashCode();
+      hash ^= Map2.GetHashCode();
+      return hash;
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      map1_.WriteTo(output, _map_map1_codec);
+      map2_.WriteTo(output, _map_map2_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += map1_.CalculateSize(_map_map1_codec);
+      size += map2_.CalculateSize(_map_map2_codec);
+      return size;
+    }
+
+    public void MergeFrom(TestSameTypeMap other) {
+      if (other == null) {
+        return;
+      }
+      map1_.Add(other.map1_);
+      map2_.Add(other.map2_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while (input.ReadTag(out tag)) {
+        switch(tag) {
+          case 0:
+            throw pb::InvalidProtocolBufferException.InvalidTag();
+          default:
+            if (pb::WireFormat.IsEndGroupTag(tag)) {
+              return;
+            }
+            break;
+          case 10: {
+            map1_.AddEntriesFrom(input, _map_map1_codec);
+            break;
+          }
+          case 18: {
+            map2_.AddEntriesFrom(input, _map_map2_codec);
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class Map1Entry : pb::IMessage<Map1Entry> {
+        private static readonly pb::MessageParser<Map1Entry> _parser = new pb::MessageParser<Map1Entry>(() => new Map1Entry());
+        public static pb::MessageParser<Map1Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestSameTypeMap_Map1Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<Map1Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestSameTypeMap_Map1Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public Map1Entry() { }
+
+        public Map1Entry(Map1Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public Map1Entry Clone() {
+          return new Map1Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private int key_;
+        public int Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private int value_;
+        public int Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as Map1Entry);
+        }
+
+        public bool Equals(Map1Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (Value != 0) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Key);
+          }
+          if (Value != 0) {
+            output.WriteRawTag(16);
+            output.WriteInt32(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Key);
+          }
+          if (Value != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(Map1Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.Value != 0) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadInt32();
+                break;
+              }
+              case 16: {
+                Value = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class Map2Entry : pb::IMessage<Map2Entry> {
+        private static readonly pb::MessageParser<Map2Entry> _parser = new pb::MessageParser<Map2Entry>(() => new Map2Entry());
+        public static pb::MessageParser<Map2Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestSameTypeMap_Map2Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<Map2Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestSameTypeMap_Map2Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public Map2Entry() { }
+
+        public Map2Entry(Map2Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public Map2Entry Clone() {
+          return new Map2Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private int key_;
+        public int Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private int value_;
+        public int Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as Map2Entry);
+        }
+
+        public bool Equals(Map2Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (Value != 0) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Key);
+          }
+          if (Value != 0) {
+            output.WriteRawTag(16);
+            output.WriteInt32(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Key);
+          }
+          if (Value != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(Map2Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.Value != 0) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadInt32();
+                break;
+              }
+              case 16: {
+                Value = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestArenaMap : pb::IMessage<TestArenaMap> {
+    private static readonly pb::MessageParser<TestArenaMap> _parser = new pb::MessageParser<TestArenaMap>(() => new TestArenaMap());
+    public static pb::MessageParser<TestArenaMap> Parser { get { return _parser; } }
+
+    private static readonly string[] _fieldNames = new string[] { "map_bool_bool", "map_fixed32_fixed32", "map_fixed64_fixed64", "map_int32_double", "map_int32_enum", "map_int32_float", "map_int32_foreign_message", "map_int32_int32", "map_int64_int64", "map_sfixed32_sfixed32", "map_sfixed64_sfixed64", "map_sint32_sint32", "map_sint64_sint64", "map_uint32_uint32", "map_uint64_uint64" };
+    private static readonly uint[] _fieldTags = new uint[] { 106, 58, 66, 98, 114, 90, 122, 10, 18, 74, 82, 42, 50, 26, 34 };
+    public static pbd::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap__Descriptor; }
+    }
+
+    public pb::FieldAccess.FieldAccessorTable<TestArenaMap> Fields {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap__FieldAccessorTable; }
+    }
+
+    private bool _frozen = false;
+    public bool IsFrozen { get { return _frozen; } }
+
+    public TestArenaMap() { }
+
+    public TestArenaMap(TestArenaMap other) {
+      mapInt32Int32_ = other.mapInt32Int32_.Clone();
+      mapInt64Int64_ = other.mapInt64Int64_.Clone();
+      mapUint32Uint32_ = other.mapUint32Uint32_.Clone();
+      mapUint64Uint64_ = other.mapUint64Uint64_.Clone();
+      mapSint32Sint32_ = other.mapSint32Sint32_.Clone();
+      mapSint64Sint64_ = other.mapSint64Sint64_.Clone();
+      mapFixed32Fixed32_ = other.mapFixed32Fixed32_.Clone();
+      mapFixed64Fixed64_ = other.mapFixed64Fixed64_.Clone();
+      mapSfixed32Sfixed32_ = other.mapSfixed32Sfixed32_.Clone();
+      mapSfixed64Sfixed64_ = other.mapSfixed64Sfixed64_.Clone();
+      mapInt32Float_ = other.mapInt32Float_.Clone();
+      mapInt32Double_ = other.mapInt32Double_.Clone();
+      mapBoolBool_ = other.mapBoolBool_.Clone();
+      mapInt32Enum_ = other.mapInt32Enum_.Clone();
+      mapInt32ForeignMessage_ = other.mapInt32ForeignMessage_.Clone();
+    }
+
+    public TestArenaMap Clone() {
+      return new TestArenaMap(this);
+    }
+
+    public void Freeze() {
+      if (IsFrozen) {
+        return;
+      }
+      _frozen = true;
+      mapInt32Int32_.Freeze();
+      mapInt64Int64_.Freeze();
+      mapUint32Uint32_.Freeze();
+      mapUint64Uint64_.Freeze();
+      mapSint32Sint32_.Freeze();
+      mapSint64Sint64_.Freeze();
+      mapFixed32Fixed32_.Freeze();
+      mapFixed64Fixed64_.Freeze();
+      mapSfixed32Sfixed32_.Freeze();
+      mapSfixed64Sfixed64_.Freeze();
+      mapInt32Float_.Freeze();
+      mapInt32Double_.Freeze();
+      mapBoolBool_.Freeze();
+      mapInt32Enum_.Freeze();
+      mapInt32ForeignMessage_.Freeze();
+    }
+
+    public const int MapInt32Int32FieldNumber = 1;
+    private static readonly pbc::MapField<int, int>.Codec _map_mapInt32Int32_codec
+        = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForInt32(16), 10);
+    private readonly pbc::MapField<int, int> mapInt32Int32_ = new pbc::MapField<int, int>();
+    public pbc::MapField<int, int> MapInt32Int32 {
+      get { return mapInt32Int32_; }
+    }
+
+    public const int MapInt64Int64FieldNumber = 2;
+    private static readonly pbc::MapField<long, long>.Codec _map_mapInt64Int64_codec
+        = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForInt64(8), pb::FieldCodec.ForInt64(16), 18);
+    private readonly pbc::MapField<long, long> mapInt64Int64_ = new pbc::MapField<long, long>();
+    public pbc::MapField<long, long> MapInt64Int64 {
+      get { return mapInt64Int64_; }
+    }
+
+    public const int MapUint32Uint32FieldNumber = 3;
+    private static readonly pbc::MapField<uint, uint>.Codec _map_mapUint32Uint32_codec
+        = new pbc::MapField<uint, uint>.Codec(pb::FieldCodec.ForUInt32(8), pb::FieldCodec.ForUInt32(16), 26);
+    private readonly pbc::MapField<uint, uint> mapUint32Uint32_ = new pbc::MapField<uint, uint>();
+    public pbc::MapField<uint, uint> MapUint32Uint32 {
+      get { return mapUint32Uint32_; }
+    }
+
+    public const int MapUint64Uint64FieldNumber = 4;
+    private static readonly pbc::MapField<ulong, ulong>.Codec _map_mapUint64Uint64_codec
+        = new pbc::MapField<ulong, ulong>.Codec(pb::FieldCodec.ForUInt64(8), pb::FieldCodec.ForUInt64(16), 34);
+    private readonly pbc::MapField<ulong, ulong> mapUint64Uint64_ = new pbc::MapField<ulong, ulong>();
+    public pbc::MapField<ulong, ulong> MapUint64Uint64 {
+      get { return mapUint64Uint64_; }
+    }
+
+    public const int MapSint32Sint32FieldNumber = 5;
+    private static readonly pbc::MapField<int, int>.Codec _map_mapSint32Sint32_codec
+        = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForSInt32(8), pb::FieldCodec.ForSInt32(16), 42);
+    private readonly pbc::MapField<int, int> mapSint32Sint32_ = new pbc::MapField<int, int>();
+    public pbc::MapField<int, int> MapSint32Sint32 {
+      get { return mapSint32Sint32_; }
+    }
+
+    public const int MapSint64Sint64FieldNumber = 6;
+    private static readonly pbc::MapField<long, long>.Codec _map_mapSint64Sint64_codec
+        = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForSInt64(8), pb::FieldCodec.ForSInt64(16), 50);
+    private readonly pbc::MapField<long, long> mapSint64Sint64_ = new pbc::MapField<long, long>();
+    public pbc::MapField<long, long> MapSint64Sint64 {
+      get { return mapSint64Sint64_; }
+    }
+
+    public const int MapFixed32Fixed32FieldNumber = 7;
+    private static readonly pbc::MapField<uint, uint>.Codec _map_mapFixed32Fixed32_codec
+        = new pbc::MapField<uint, uint>.Codec(pb::FieldCodec.ForFixed32(13), pb::FieldCodec.ForFixed32(21), 58);
+    private readonly pbc::MapField<uint, uint> mapFixed32Fixed32_ = new pbc::MapField<uint, uint>();
+    public pbc::MapField<uint, uint> MapFixed32Fixed32 {
+      get { return mapFixed32Fixed32_; }
+    }
+
+    public const int MapFixed64Fixed64FieldNumber = 8;
+    private static readonly pbc::MapField<ulong, ulong>.Codec _map_mapFixed64Fixed64_codec
+        = new pbc::MapField<ulong, ulong>.Codec(pb::FieldCodec.ForFixed64(9), pb::FieldCodec.ForFixed64(17), 66);
+    private readonly pbc::MapField<ulong, ulong> mapFixed64Fixed64_ = new pbc::MapField<ulong, ulong>();
+    public pbc::MapField<ulong, ulong> MapFixed64Fixed64 {
+      get { return mapFixed64Fixed64_; }
+    }
+
+    public const int MapSfixed32Sfixed32FieldNumber = 9;
+    private static readonly pbc::MapField<int, int>.Codec _map_mapSfixed32Sfixed32_codec
+        = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForSFixed32(13), pb::FieldCodec.ForSFixed32(21), 74);
+    private readonly pbc::MapField<int, int> mapSfixed32Sfixed32_ = new pbc::MapField<int, int>();
+    public pbc::MapField<int, int> MapSfixed32Sfixed32 {
+      get { return mapSfixed32Sfixed32_; }
+    }
+
+    public const int MapSfixed64Sfixed64FieldNumber = 10;
+    private static readonly pbc::MapField<long, long>.Codec _map_mapSfixed64Sfixed64_codec
+        = new pbc::MapField<long, long>.Codec(pb::FieldCodec.ForSFixed64(9), pb::FieldCodec.ForSFixed64(17), 82);
+    private readonly pbc::MapField<long, long> mapSfixed64Sfixed64_ = new pbc::MapField<long, long>();
+    public pbc::MapField<long, long> MapSfixed64Sfixed64 {
+      get { return mapSfixed64Sfixed64_; }
+    }
+
+    public const int MapInt32FloatFieldNumber = 11;
+    private static readonly pbc::MapField<int, float>.Codec _map_mapInt32Float_codec
+        = new pbc::MapField<int, float>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForFloat(21), 90);
+    private readonly pbc::MapField<int, float> mapInt32Float_ = new pbc::MapField<int, float>();
+    public pbc::MapField<int, float> MapInt32Float {
+      get { return mapInt32Float_; }
+    }
+
+    public const int MapInt32DoubleFieldNumber = 12;
+    private static readonly pbc::MapField<int, double>.Codec _map_mapInt32Double_codec
+        = new pbc::MapField<int, double>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForDouble(17), 98);
+    private readonly pbc::MapField<int, double> mapInt32Double_ = new pbc::MapField<int, double>();
+    public pbc::MapField<int, double> MapInt32Double {
+      get { return mapInt32Double_; }
+    }
+
+    public const int MapBoolBoolFieldNumber = 13;
+    private static readonly pbc::MapField<bool, bool>.Codec _map_mapBoolBool_codec
+        = new pbc::MapField<bool, bool>.Codec(pb::FieldCodec.ForBool(8), pb::FieldCodec.ForBool(16), 106);
+    private readonly pbc::MapField<bool, bool> mapBoolBool_ = new pbc::MapField<bool, bool>();
+    public pbc::MapField<bool, bool> MapBoolBool {
+      get { return mapBoolBool_; }
+    }
+
+    public const int MapInt32EnumFieldNumber = 14;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum>.Codec _map_mapInt32Enum_codec
+        = new pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::Google.Protobuf.TestProtos.MapEnum) x), 114);
+    private readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum> mapInt32Enum_ = new pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum>();
+    public pbc::MapField<int, global::Google.Protobuf.TestProtos.MapEnum> MapInt32Enum {
+      get { return mapInt32Enum_; }
+    }
+
+    public const int MapInt32ForeignMessageFieldNumber = 15;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage>.Codec _map_mapInt32ForeignMessage_codec
+        = new pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.ForeignMessage.Parser), 122);
+    private readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage> mapInt32ForeignMessage_ = new pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage>();
+    public pbc::MapField<int, global::Google.Protobuf.TestProtos.ForeignMessage> MapInt32ForeignMessage {
+      get { return mapInt32ForeignMessage_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestArenaMap);
+    }
+
+    public bool Equals(TestArenaMap other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!MapInt32Int32.Equals(other.MapInt32Int32)) return false;
+      if (!MapInt64Int64.Equals(other.MapInt64Int64)) return false;
+      if (!MapUint32Uint32.Equals(other.MapUint32Uint32)) return false;
+      if (!MapUint64Uint64.Equals(other.MapUint64Uint64)) return false;
+      if (!MapSint32Sint32.Equals(other.MapSint32Sint32)) return false;
+      if (!MapSint64Sint64.Equals(other.MapSint64Sint64)) return false;
+      if (!MapFixed32Fixed32.Equals(other.MapFixed32Fixed32)) return false;
+      if (!MapFixed64Fixed64.Equals(other.MapFixed64Fixed64)) return false;
+      if (!MapSfixed32Sfixed32.Equals(other.MapSfixed32Sfixed32)) return false;
+      if (!MapSfixed64Sfixed64.Equals(other.MapSfixed64Sfixed64)) return false;
+      if (!MapInt32Float.Equals(other.MapInt32Float)) return false;
+      if (!MapInt32Double.Equals(other.MapInt32Double)) return false;
+      if (!MapBoolBool.Equals(other.MapBoolBool)) return false;
+      if (!MapInt32Enum.Equals(other.MapInt32Enum)) return false;
+      if (!MapInt32ForeignMessage.Equals(other.MapInt32ForeignMessage)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= MapInt32Int32.GetHashCode();
+      hash ^= MapInt64Int64.GetHashCode();
+      hash ^= MapUint32Uint32.GetHashCode();
+      hash ^= MapUint64Uint64.GetHashCode();
+      hash ^= MapSint32Sint32.GetHashCode();
+      hash ^= MapSint64Sint64.GetHashCode();
+      hash ^= MapFixed32Fixed32.GetHashCode();
+      hash ^= MapFixed64Fixed64.GetHashCode();
+      hash ^= MapSfixed32Sfixed32.GetHashCode();
+      hash ^= MapSfixed64Sfixed64.GetHashCode();
+      hash ^= MapInt32Float.GetHashCode();
+      hash ^= MapInt32Double.GetHashCode();
+      hash ^= MapBoolBool.GetHashCode();
+      hash ^= MapInt32Enum.GetHashCode();
+      hash ^= MapInt32ForeignMessage.GetHashCode();
+      return hash;
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      mapInt32Int32_.WriteTo(output, _map_mapInt32Int32_codec);
+      mapInt64Int64_.WriteTo(output, _map_mapInt64Int64_codec);
+      mapUint32Uint32_.WriteTo(output, _map_mapUint32Uint32_codec);
+      mapUint64Uint64_.WriteTo(output, _map_mapUint64Uint64_codec);
+      mapSint32Sint32_.WriteTo(output, _map_mapSint32Sint32_codec);
+      mapSint64Sint64_.WriteTo(output, _map_mapSint64Sint64_codec);
+      mapFixed32Fixed32_.WriteTo(output, _map_mapFixed32Fixed32_codec);
+      mapFixed64Fixed64_.WriteTo(output, _map_mapFixed64Fixed64_codec);
+      mapSfixed32Sfixed32_.WriteTo(output, _map_mapSfixed32Sfixed32_codec);
+      mapSfixed64Sfixed64_.WriteTo(output, _map_mapSfixed64Sfixed64_codec);
+      mapInt32Float_.WriteTo(output, _map_mapInt32Float_codec);
+      mapInt32Double_.WriteTo(output, _map_mapInt32Double_codec);
+      mapBoolBool_.WriteTo(output, _map_mapBoolBool_codec);
+      mapInt32Enum_.WriteTo(output, _map_mapInt32Enum_codec);
+      mapInt32ForeignMessage_.WriteTo(output, _map_mapInt32ForeignMessage_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += mapInt32Int32_.CalculateSize(_map_mapInt32Int32_codec);
+      size += mapInt64Int64_.CalculateSize(_map_mapInt64Int64_codec);
+      size += mapUint32Uint32_.CalculateSize(_map_mapUint32Uint32_codec);
+      size += mapUint64Uint64_.CalculateSize(_map_mapUint64Uint64_codec);
+      size += mapSint32Sint32_.CalculateSize(_map_mapSint32Sint32_codec);
+      size += mapSint64Sint64_.CalculateSize(_map_mapSint64Sint64_codec);
+      size += mapFixed32Fixed32_.CalculateSize(_map_mapFixed32Fixed32_codec);
+      size += mapFixed64Fixed64_.CalculateSize(_map_mapFixed64Fixed64_codec);
+      size += mapSfixed32Sfixed32_.CalculateSize(_map_mapSfixed32Sfixed32_codec);
+      size += mapSfixed64Sfixed64_.CalculateSize(_map_mapSfixed64Sfixed64_codec);
+      size += mapInt32Float_.CalculateSize(_map_mapInt32Float_codec);
+      size += mapInt32Double_.CalculateSize(_map_mapInt32Double_codec);
+      size += mapBoolBool_.CalculateSize(_map_mapBoolBool_codec);
+      size += mapInt32Enum_.CalculateSize(_map_mapInt32Enum_codec);
+      size += mapInt32ForeignMessage_.CalculateSize(_map_mapInt32ForeignMessage_codec);
+      return size;
+    }
+
+    public void MergeFrom(TestArenaMap other) {
+      if (other == null) {
+        return;
+      }
+      mapInt32Int32_.Add(other.mapInt32Int32_);
+      mapInt64Int64_.Add(other.mapInt64Int64_);
+      mapUint32Uint32_.Add(other.mapUint32Uint32_);
+      mapUint64Uint64_.Add(other.mapUint64Uint64_);
+      mapSint32Sint32_.Add(other.mapSint32Sint32_);
+      mapSint64Sint64_.Add(other.mapSint64Sint64_);
+      mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_);
+      mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_);
+      mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_);
+      mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_);
+      mapInt32Float_.Add(other.mapInt32Float_);
+      mapInt32Double_.Add(other.mapInt32Double_);
+      mapBoolBool_.Add(other.mapBoolBool_);
+      mapInt32Enum_.Add(other.mapInt32Enum_);
+      mapInt32ForeignMessage_.Add(other.mapInt32ForeignMessage_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while (input.ReadTag(out tag)) {
+        switch(tag) {
+          case 0:
+            throw pb::InvalidProtocolBufferException.InvalidTag();
+          default:
+            if (pb::WireFormat.IsEndGroupTag(tag)) {
+              return;
+            }
+            break;
+          case 10: {
+            mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec);
+            break;
+          }
+          case 18: {
+            mapInt64Int64_.AddEntriesFrom(input, _map_mapInt64Int64_codec);
+            break;
+          }
+          case 26: {
+            mapUint32Uint32_.AddEntriesFrom(input, _map_mapUint32Uint32_codec);
+            break;
+          }
+          case 34: {
+            mapUint64Uint64_.AddEntriesFrom(input, _map_mapUint64Uint64_codec);
+            break;
+          }
+          case 42: {
+            mapSint32Sint32_.AddEntriesFrom(input, _map_mapSint32Sint32_codec);
+            break;
+          }
+          case 50: {
+            mapSint64Sint64_.AddEntriesFrom(input, _map_mapSint64Sint64_codec);
+            break;
+          }
+          case 58: {
+            mapFixed32Fixed32_.AddEntriesFrom(input, _map_mapFixed32Fixed32_codec);
+            break;
+          }
+          case 66: {
+            mapFixed64Fixed64_.AddEntriesFrom(input, _map_mapFixed64Fixed64_codec);
+            break;
+          }
+          case 74: {
+            mapSfixed32Sfixed32_.AddEntriesFrom(input, _map_mapSfixed32Sfixed32_codec);
+            break;
+          }
+          case 82: {
+            mapSfixed64Sfixed64_.AddEntriesFrom(input, _map_mapSfixed64Sfixed64_codec);
+            break;
+          }
+          case 90: {
+            mapInt32Float_.AddEntriesFrom(input, _map_mapInt32Float_codec);
+            break;
+          }
+          case 98: {
+            mapInt32Double_.AddEntriesFrom(input, _map_mapInt32Double_codec);
+            break;
+          }
+          case 106: {
+            mapBoolBool_.AddEntriesFrom(input, _map_mapBoolBool_codec);
+            break;
+          }
+          case 114: {
+            mapInt32Enum_.AddEntriesFrom(input, _map_mapInt32Enum_codec);
+            break;
+          }
+          case 122: {
+            mapInt32ForeignMessage_.AddEntriesFrom(input, _map_mapInt32ForeignMessage_codec);
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapInt32Int32Entry : pb::IMessage<MapInt32Int32Entry> {
+        private static readonly pb::MessageParser<MapInt32Int32Entry> _parser = new pb::MessageParser<MapInt32Int32Entry>(() => new MapInt32Int32Entry());
+        public static pb::MessageParser<MapInt32Int32Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt32Int32Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapInt32Int32Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt32Int32Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapInt32Int32Entry() { }
+
+        public MapInt32Int32Entry(MapInt32Int32Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapInt32Int32Entry Clone() {
+          return new MapInt32Int32Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private int key_;
+        public int Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private int value_;
+        public int Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapInt32Int32Entry);
+        }
+
+        public bool Equals(MapInt32Int32Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (Value != 0) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Key);
+          }
+          if (Value != 0) {
+            output.WriteRawTag(16);
+            output.WriteInt32(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Key);
+          }
+          if (Value != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapInt32Int32Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.Value != 0) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadInt32();
+                break;
+              }
+              case 16: {
+                Value = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapInt64Int64Entry : pb::IMessage<MapInt64Int64Entry> {
+        private static readonly pb::MessageParser<MapInt64Int64Entry> _parser = new pb::MessageParser<MapInt64Int64Entry>(() => new MapInt64Int64Entry());
+        public static pb::MessageParser<MapInt64Int64Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt64Int64Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapInt64Int64Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt64Int64Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapInt64Int64Entry() { }
+
+        public MapInt64Int64Entry(MapInt64Int64Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapInt64Int64Entry Clone() {
+          return new MapInt64Int64Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private long key_;
+        public long Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private long value_;
+        public long Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapInt64Int64Entry);
+        }
+
+        public bool Equals(MapInt64Int64Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0L) hash ^= Key.GetHashCode();
+          if (Value != 0L) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0L) {
+            output.WriteRawTag(8);
+            output.WriteInt64(Key);
+          }
+          if (Value != 0L) {
+            output.WriteRawTag(16);
+            output.WriteInt64(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0L) {
+            size += 1 + pb::CodedOutputStream.ComputeInt64Size(Key);
+          }
+          if (Value != 0L) {
+            size += 1 + pb::CodedOutputStream.ComputeInt64Size(Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapInt64Int64Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0L) {
+            Key = other.Key;
+          }
+          if (other.Value != 0L) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadInt64();
+                break;
+              }
+              case 16: {
+                Value = input.ReadInt64();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapUint32Uint32Entry : pb::IMessage<MapUint32Uint32Entry> {
+        private static readonly pb::MessageParser<MapUint32Uint32Entry> _parser = new pb::MessageParser<MapUint32Uint32Entry>(() => new MapUint32Uint32Entry());
+        public static pb::MessageParser<MapUint32Uint32Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapUint32Uint32Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapUint32Uint32Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapUint32Uint32Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapUint32Uint32Entry() { }
+
+        public MapUint32Uint32Entry(MapUint32Uint32Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapUint32Uint32Entry Clone() {
+          return new MapUint32Uint32Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private uint key_;
+        public uint Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private uint value_;
+        public uint Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapUint32Uint32Entry);
+        }
+
+        public bool Equals(MapUint32Uint32Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (Value != 0) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(8);
+            output.WriteUInt32(Key);
+          }
+          if (Value != 0) {
+            output.WriteRawTag(16);
+            output.WriteUInt32(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Key);
+          }
+          if (Value != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapUint32Uint32Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.Value != 0) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadUInt32();
+                break;
+              }
+              case 16: {
+                Value = input.ReadUInt32();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapUint64Uint64Entry : pb::IMessage<MapUint64Uint64Entry> {
+        private static readonly pb::MessageParser<MapUint64Uint64Entry> _parser = new pb::MessageParser<MapUint64Uint64Entry>(() => new MapUint64Uint64Entry());
+        public static pb::MessageParser<MapUint64Uint64Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapUint64Uint64Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapUint64Uint64Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapUint64Uint64Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapUint64Uint64Entry() { }
+
+        public MapUint64Uint64Entry(MapUint64Uint64Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapUint64Uint64Entry Clone() {
+          return new MapUint64Uint64Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private ulong key_;
+        public ulong Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private ulong value_;
+        public ulong Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapUint64Uint64Entry);
+        }
+
+        public bool Equals(MapUint64Uint64Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0UL) hash ^= Key.GetHashCode();
+          if (Value != 0UL) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0UL) {
+            output.WriteRawTag(8);
+            output.WriteUInt64(Key);
+          }
+          if (Value != 0UL) {
+            output.WriteRawTag(16);
+            output.WriteUInt64(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0UL) {
+            size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Key);
+          }
+          if (Value != 0UL) {
+            size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapUint64Uint64Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0UL) {
+            Key = other.Key;
+          }
+          if (other.Value != 0UL) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadUInt64();
+                break;
+              }
+              case 16: {
+                Value = input.ReadUInt64();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapSint32Sint32Entry : pb::IMessage<MapSint32Sint32Entry> {
+        private static readonly pb::MessageParser<MapSint32Sint32Entry> _parser = new pb::MessageParser<MapSint32Sint32Entry>(() => new MapSint32Sint32Entry());
+        public static pb::MessageParser<MapSint32Sint32Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapSint32Sint32Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapSint32Sint32Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapSint32Sint32Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapSint32Sint32Entry() { }
+
+        public MapSint32Sint32Entry(MapSint32Sint32Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapSint32Sint32Entry Clone() {
+          return new MapSint32Sint32Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private int key_;
+        public int Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private int value_;
+        public int Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapSint32Sint32Entry);
+        }
+
+        public bool Equals(MapSint32Sint32Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (Value != 0) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(8);
+            output.WriteSInt32(Key);
+          }
+          if (Value != 0) {
+            output.WriteRawTag(16);
+            output.WriteSInt32(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeSInt32Size(Key);
+          }
+          if (Value != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeSInt32Size(Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapSint32Sint32Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.Value != 0) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadSInt32();
+                break;
+              }
+              case 16: {
+                Value = input.ReadSInt32();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapSint64Sint64Entry : pb::IMessage<MapSint64Sint64Entry> {
+        private static readonly pb::MessageParser<MapSint64Sint64Entry> _parser = new pb::MessageParser<MapSint64Sint64Entry>(() => new MapSint64Sint64Entry());
+        public static pb::MessageParser<MapSint64Sint64Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapSint64Sint64Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapSint64Sint64Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapSint64Sint64Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapSint64Sint64Entry() { }
+
+        public MapSint64Sint64Entry(MapSint64Sint64Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapSint64Sint64Entry Clone() {
+          return new MapSint64Sint64Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private long key_;
+        public long Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private long value_;
+        public long Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapSint64Sint64Entry);
+        }
+
+        public bool Equals(MapSint64Sint64Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0L) hash ^= Key.GetHashCode();
+          if (Value != 0L) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0L) {
+            output.WriteRawTag(8);
+            output.WriteSInt64(Key);
+          }
+          if (Value != 0L) {
+            output.WriteRawTag(16);
+            output.WriteSInt64(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0L) {
+            size += 1 + pb::CodedOutputStream.ComputeSInt64Size(Key);
+          }
+          if (Value != 0L) {
+            size += 1 + pb::CodedOutputStream.ComputeSInt64Size(Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapSint64Sint64Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0L) {
+            Key = other.Key;
+          }
+          if (other.Value != 0L) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadSInt64();
+                break;
+              }
+              case 16: {
+                Value = input.ReadSInt64();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapFixed32Fixed32Entry : pb::IMessage<MapFixed32Fixed32Entry> {
+        private static readonly pb::MessageParser<MapFixed32Fixed32Entry> _parser = new pb::MessageParser<MapFixed32Fixed32Entry>(() => new MapFixed32Fixed32Entry());
+        public static pb::MessageParser<MapFixed32Fixed32Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 13, 21 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapFixed32Fixed32Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapFixed32Fixed32Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapFixed32Fixed32Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapFixed32Fixed32Entry() { }
+
+        public MapFixed32Fixed32Entry(MapFixed32Fixed32Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapFixed32Fixed32Entry Clone() {
+          return new MapFixed32Fixed32Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private uint key_;
+        public uint Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private uint value_;
+        public uint Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapFixed32Fixed32Entry);
+        }
+
+        public bool Equals(MapFixed32Fixed32Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (Value != 0) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(13);
+            output.WriteFixed32(Key);
+          }
+          if (Value != 0) {
+            output.WriteRawTag(21);
+            output.WriteFixed32(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + 4;
+          }
+          if (Value != 0) {
+            size += 1 + 4;
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapFixed32Fixed32Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.Value != 0) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 13: {
+                Key = input.ReadFixed32();
+                break;
+              }
+              case 21: {
+                Value = input.ReadFixed32();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapFixed64Fixed64Entry : pb::IMessage<MapFixed64Fixed64Entry> {
+        private static readonly pb::MessageParser<MapFixed64Fixed64Entry> _parser = new pb::MessageParser<MapFixed64Fixed64Entry>(() => new MapFixed64Fixed64Entry());
+        public static pb::MessageParser<MapFixed64Fixed64Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 9, 17 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapFixed64Fixed64Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapFixed64Fixed64Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapFixed64Fixed64Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapFixed64Fixed64Entry() { }
+
+        public MapFixed64Fixed64Entry(MapFixed64Fixed64Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapFixed64Fixed64Entry Clone() {
+          return new MapFixed64Fixed64Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private ulong key_;
+        public ulong Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private ulong value_;
+        public ulong Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapFixed64Fixed64Entry);
+        }
+
+        public bool Equals(MapFixed64Fixed64Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0UL) hash ^= Key.GetHashCode();
+          if (Value != 0UL) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0UL) {
+            output.WriteRawTag(9);
+            output.WriteFixed64(Key);
+          }
+          if (Value != 0UL) {
+            output.WriteRawTag(17);
+            output.WriteFixed64(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0UL) {
+            size += 1 + 8;
+          }
+          if (Value != 0UL) {
+            size += 1 + 8;
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapFixed64Fixed64Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0UL) {
+            Key = other.Key;
+          }
+          if (other.Value != 0UL) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 9: {
+                Key = input.ReadFixed64();
+                break;
+              }
+              case 17: {
+                Value = input.ReadFixed64();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapSfixed32Sfixed32Entry : pb::IMessage<MapSfixed32Sfixed32Entry> {
+        private static readonly pb::MessageParser<MapSfixed32Sfixed32Entry> _parser = new pb::MessageParser<MapSfixed32Sfixed32Entry>(() => new MapSfixed32Sfixed32Entry());
+        public static pb::MessageParser<MapSfixed32Sfixed32Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 13, 21 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapSfixed32Sfixed32Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapSfixed32Sfixed32Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapSfixed32Sfixed32Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapSfixed32Sfixed32Entry() { }
+
+        public MapSfixed32Sfixed32Entry(MapSfixed32Sfixed32Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapSfixed32Sfixed32Entry Clone() {
+          return new MapSfixed32Sfixed32Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private int key_;
+        public int Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private int value_;
+        public int Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapSfixed32Sfixed32Entry);
+        }
+
+        public bool Equals(MapSfixed32Sfixed32Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (Value != 0) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(13);
+            output.WriteSFixed32(Key);
+          }
+          if (Value != 0) {
+            output.WriteRawTag(21);
+            output.WriteSFixed32(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + 4;
+          }
+          if (Value != 0) {
+            size += 1 + 4;
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapSfixed32Sfixed32Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.Value != 0) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 13: {
+                Key = input.ReadSFixed32();
+                break;
+              }
+              case 21: {
+                Value = input.ReadSFixed32();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapSfixed64Sfixed64Entry : pb::IMessage<MapSfixed64Sfixed64Entry> {
+        private static readonly pb::MessageParser<MapSfixed64Sfixed64Entry> _parser = new pb::MessageParser<MapSfixed64Sfixed64Entry>(() => new MapSfixed64Sfixed64Entry());
+        public static pb::MessageParser<MapSfixed64Sfixed64Entry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 9, 17 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapSfixed64Sfixed64Entry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapSfixed64Sfixed64Entry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapSfixed64Sfixed64Entry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapSfixed64Sfixed64Entry() { }
+
+        public MapSfixed64Sfixed64Entry(MapSfixed64Sfixed64Entry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapSfixed64Sfixed64Entry Clone() {
+          return new MapSfixed64Sfixed64Entry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private long key_;
+        public long Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private long value_;
+        public long Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapSfixed64Sfixed64Entry);
+        }
+
+        public bool Equals(MapSfixed64Sfixed64Entry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0L) hash ^= Key.GetHashCode();
+          if (Value != 0L) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0L) {
+            output.WriteRawTag(9);
+            output.WriteSFixed64(Key);
+          }
+          if (Value != 0L) {
+            output.WriteRawTag(17);
+            output.WriteSFixed64(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0L) {
+            size += 1 + 8;
+          }
+          if (Value != 0L) {
+            size += 1 + 8;
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapSfixed64Sfixed64Entry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0L) {
+            Key = other.Key;
+          }
+          if (other.Value != 0L) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 9: {
+                Key = input.ReadSFixed64();
+                break;
+              }
+              case 17: {
+                Value = input.ReadSFixed64();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapInt32FloatEntry : pb::IMessage<MapInt32FloatEntry> {
+        private static readonly pb::MessageParser<MapInt32FloatEntry> _parser = new pb::MessageParser<MapInt32FloatEntry>(() => new MapInt32FloatEntry());
+        public static pb::MessageParser<MapInt32FloatEntry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 21 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt32FloatEntry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapInt32FloatEntry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt32FloatEntry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapInt32FloatEntry() { }
+
+        public MapInt32FloatEntry(MapInt32FloatEntry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapInt32FloatEntry Clone() {
+          return new MapInt32FloatEntry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private int key_;
+        public int Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private float value_;
+        public float Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapInt32FloatEntry);
+        }
+
+        public bool Equals(MapInt32FloatEntry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (Value != 0F) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Key);
+          }
+          if (Value != 0F) {
+            output.WriteRawTag(21);
+            output.WriteFloat(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Key);
+          }
+          if (Value != 0F) {
+            size += 1 + 4;
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapInt32FloatEntry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.Value != 0F) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadInt32();
+                break;
+              }
+              case 21: {
+                Value = input.ReadFloat();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapInt32DoubleEntry : pb::IMessage<MapInt32DoubleEntry> {
+        private static readonly pb::MessageParser<MapInt32DoubleEntry> _parser = new pb::MessageParser<MapInt32DoubleEntry>(() => new MapInt32DoubleEntry());
+        public static pb::MessageParser<MapInt32DoubleEntry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 17 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt32DoubleEntry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapInt32DoubleEntry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt32DoubleEntry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapInt32DoubleEntry() { }
+
+        public MapInt32DoubleEntry(MapInt32DoubleEntry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapInt32DoubleEntry Clone() {
+          return new MapInt32DoubleEntry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private int key_;
+        public int Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private double value_;
+        public double Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapInt32DoubleEntry);
+        }
+
+        public bool Equals(MapInt32DoubleEntry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (Value != 0D) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Key);
+          }
+          if (Value != 0D) {
+            output.WriteRawTag(17);
+            output.WriteDouble(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Key);
+          }
+          if (Value != 0D) {
+            size += 1 + 8;
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapInt32DoubleEntry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.Value != 0D) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadInt32();
+                break;
+              }
+              case 17: {
+                Value = input.ReadDouble();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapBoolBoolEntry : pb::IMessage<MapBoolBoolEntry> {
+        private static readonly pb::MessageParser<MapBoolBoolEntry> _parser = new pb::MessageParser<MapBoolBoolEntry>(() => new MapBoolBoolEntry());
+        public static pb::MessageParser<MapBoolBoolEntry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapBoolBoolEntry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapBoolBoolEntry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapBoolBoolEntry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapBoolBoolEntry() { }
+
+        public MapBoolBoolEntry(MapBoolBoolEntry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapBoolBoolEntry Clone() {
+          return new MapBoolBoolEntry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private bool key_;
+        public bool Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private bool value_;
+        public bool Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapBoolBoolEntry);
+        }
+
+        public bool Equals(MapBoolBoolEntry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != false) hash ^= Key.GetHashCode();
+          if (Value != false) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != false) {
+            output.WriteRawTag(8);
+            output.WriteBool(Key);
+          }
+          if (Value != false) {
+            output.WriteRawTag(16);
+            output.WriteBool(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != false) {
+            size += 1 + 1;
+          }
+          if (Value != false) {
+            size += 1 + 1;
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapBoolBoolEntry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != false) {
+            Key = other.Key;
+          }
+          if (other.Value != false) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadBool();
+                break;
+              }
+              case 16: {
+                Value = input.ReadBool();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapInt32EnumEntry : pb::IMessage<MapInt32EnumEntry> {
+        private static readonly pb::MessageParser<MapInt32EnumEntry> _parser = new pb::MessageParser<MapInt32EnumEntry>(() => new MapInt32EnumEntry());
+        public static pb::MessageParser<MapInt32EnumEntry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt32EnumEntry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapInt32EnumEntry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt32EnumEntry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapInt32EnumEntry() { }
+
+        public MapInt32EnumEntry(MapInt32EnumEntry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public MapInt32EnumEntry Clone() {
+          return new MapInt32EnumEntry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private int key_;
+        public int Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private global::Google.Protobuf.TestProtos.MapEnum value_ = global::Google.Protobuf.TestProtos.MapEnum.MAP_ENUM_FOO;
+        public global::Google.Protobuf.TestProtos.MapEnum Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapInt32EnumEntry);
+        }
+
+        public bool Equals(MapInt32EnumEntry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (Value != global::Google.Protobuf.TestProtos.MapEnum.MAP_ENUM_FOO) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Key);
+          }
+          if (Value != global::Google.Protobuf.TestProtos.MapEnum.MAP_ENUM_FOO) {
+            output.WriteRawTag(16);
+            output.WriteEnum((int) Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Key);
+          }
+          if (Value != global::Google.Protobuf.TestProtos.MapEnum.MAP_ENUM_FOO) {
+            size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapInt32EnumEntry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.Value != global::Google.Protobuf.TestProtos.MapEnum.MAP_ENUM_FOO) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadInt32();
+                break;
+              }
+              case 16: {
+                value_ = (global::Google.Protobuf.TestProtos.MapEnum) input.ReadEnum();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class MapInt32ForeignMessageEntry : pb::IMessage<MapInt32ForeignMessageEntry> {
+        private static readonly pb::MessageParser<MapInt32ForeignMessageEntry> _parser = new pb::MessageParser<MapInt32ForeignMessageEntry>(() => new MapInt32ForeignMessageEntry());
+        public static pb::MessageParser<MapInt32ForeignMessageEntry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 18 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt32ForeignMessageEntry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<MapInt32ForeignMessageEntry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_TestArenaMap_MapInt32ForeignMessageEntry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public MapInt32ForeignMessageEntry() { }
+
+        public MapInt32ForeignMessageEntry(MapInt32ForeignMessageEntry other) {
+          key_ = other.key_;
+          Value = other.value_ != null ? other.Value.Clone() : null;
+        }
+
+        public MapInt32ForeignMessageEntry Clone() {
+          return new MapInt32ForeignMessageEntry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+          if (value_ != null) Value.Freeze();
+        }
+
+        public const int KeyFieldNumber = 1;
+        private int key_;
+        public int Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private global::Google.Protobuf.TestProtos.ForeignMessage value_;
+        public global::Google.Protobuf.TestProtos.ForeignMessage Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as MapInt32ForeignMessageEntry);
+        }
+
+        public bool Equals(MapInt32ForeignMessageEntry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (!object.Equals(Value, other.Value)) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (value_ != null) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Key);
+          }
+          if (value_ != null) {
+            output.WriteRawTag(18);
+            output.WriteMessage(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Key);
+          }
+          if (value_ != null) {
+            size += 1 + pb::CodedOutputStream.ComputeMessageSize(Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(MapInt32ForeignMessageEntry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.value_ != null) {
+            if (value_ == null) {
+              value_ = new global::Google.Protobuf.TestProtos.ForeignMessage();
+            }
+            Value.MergeFrom(other.Value);
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadInt32();
+                break;
+              }
+              case 18: {
+                if (value_ == null) {
+                  value_ = new global::Google.Protobuf.TestProtos.ForeignMessage();
+                }
+                input.ReadMessage(value_);
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class MessageContainingEnumCalledType : pb::IMessage<MessageContainingEnumCalledType> {
+    private static readonly pb::MessageParser<MessageContainingEnumCalledType> _parser = new pb::MessageParser<MessageContainingEnumCalledType>(() => new MessageContainingEnumCalledType());
+    public static pb::MessageParser<MessageContainingEnumCalledType> Parser { get { return _parser; } }
+
+    private static readonly string[] _fieldNames = new string[] { "type" };
+    private static readonly uint[] _fieldTags = new uint[] { 10 };
+    public static pbd::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_MessageContainingEnumCalledType__Descriptor; }
+    }
+
+    public pb::FieldAccess.FieldAccessorTable<MessageContainingEnumCalledType> Fields {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_MessageContainingEnumCalledType__FieldAccessorTable; }
+    }
+
+    private bool _frozen = false;
+    public bool IsFrozen { get { return _frozen; } }
+
+    public MessageContainingEnumCalledType() { }
+
+    public MessageContainingEnumCalledType(MessageContainingEnumCalledType other) {
+      type_ = other.type_.Clone();
+    }
+
+    public MessageContainingEnumCalledType Clone() {
+      return new MessageContainingEnumCalledType(this);
+    }
+
+    public void Freeze() {
+      if (IsFrozen) {
+        return;
+      }
+      _frozen = true;
+      type_.Freeze();
+    }
+
+    public const int TypeFieldNumber = 1;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType>.Codec _map_type_codec
+        = new pbc::MapField<int, global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Parser), 10);
+    private readonly pbc::MapField<int, global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType> type_ = new pbc::MapField<int, global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType>();
+    public pbc::MapField<int, global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType> Type {
+      get { return type_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as MessageContainingEnumCalledType);
+    }
+
+    public bool Equals(MessageContainingEnumCalledType other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!Type.Equals(other.Type)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= Type.GetHashCode();
+      return hash;
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      type_.WriteTo(output, _map_type_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += type_.CalculateSize(_map_type_codec);
+      return size;
+    }
+
+    public void MergeFrom(MessageContainingEnumCalledType other) {
+      if (other == null) {
+        return;
+      }
+      type_.Add(other.type_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while (input.ReadTag(out tag)) {
+        switch(tag) {
+          case 0:
+            throw pb::InvalidProtocolBufferException.InvalidTag();
+          default:
+            if (pb::WireFormat.IsEndGroupTag(tag)) {
+              return;
+            }
+            break;
+          case 10: {
+            type_.AddEntriesFrom(input, _map_type_codec);
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      public enum Type {
+        TYPE_FOO = 0,
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class TypeEntry : pb::IMessage<TypeEntry> {
+        private static readonly pb::MessageParser<TypeEntry> _parser = new pb::MessageParser<TypeEntry>(() => new TypeEntry());
+        public static pb::MessageParser<TypeEntry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 18 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_MessageContainingEnumCalledType_TypeEntry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<TypeEntry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_MessageContainingEnumCalledType_TypeEntry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public TypeEntry() { }
+
+        public TypeEntry(TypeEntry other) {
+          key_ = other.key_;
+          Value = other.value_ != null ? other.Value.Clone() : null;
+        }
+
+        public TypeEntry Clone() {
+          return new TypeEntry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+          if (value_ != null) Value.Freeze();
+        }
+
+        public const int KeyFieldNumber = 1;
+        private int key_;
+        public int Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType value_;
+        public global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as TypeEntry);
+        }
+
+        public bool Equals(TypeEntry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (!object.Equals(Value, other.Value)) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (value_ != null) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Key);
+          }
+          if (value_ != null) {
+            output.WriteRawTag(18);
+            output.WriteMessage(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Key);
+          }
+          if (value_ != null) {
+            size += 1 + pb::CodedOutputStream.ComputeMessageSize(Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(TypeEntry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.value_ != null) {
+            if (value_ == null) {
+              value_ = new global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType();
+            }
+            Value.MergeFrom(other.Value);
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadInt32();
+                break;
+              }
+              case 18: {
+                if (value_ == null) {
+                  value_ = new global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType();
+                }
+                input.ReadMessage(value_);
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class MessageContainingMapCalledEntry : pb::IMessage<MessageContainingMapCalledEntry> {
+    private static readonly pb::MessageParser<MessageContainingMapCalledEntry> _parser = new pb::MessageParser<MessageContainingMapCalledEntry>(() => new MessageContainingMapCalledEntry());
+    public static pb::MessageParser<MessageContainingMapCalledEntry> Parser { get { return _parser; } }
+
+    private static readonly string[] _fieldNames = new string[] { "entry" };
+    private static readonly uint[] _fieldTags = new uint[] { 10 };
+    public static pbd::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_MessageContainingMapCalledEntry__Descriptor; }
+    }
+
+    public pb::FieldAccess.FieldAccessorTable<MessageContainingMapCalledEntry> Fields {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_MessageContainingMapCalledEntry__FieldAccessorTable; }
+    }
+
+    private bool _frozen = false;
+    public bool IsFrozen { get { return _frozen; } }
+
+    public MessageContainingMapCalledEntry() { }
+
+    public MessageContainingMapCalledEntry(MessageContainingMapCalledEntry other) {
+      entry_ = other.entry_.Clone();
+    }
+
+    public MessageContainingMapCalledEntry Clone() {
+      return new MessageContainingMapCalledEntry(this);
+    }
+
+    public void Freeze() {
+      if (IsFrozen) {
+        return;
+      }
+      _frozen = true;
+      entry_.Freeze();
+    }
+
+    public const int EntryFieldNumber = 1;
+    private static readonly pbc::MapField<int, int>.Codec _map_entry_codec
+        = new pbc::MapField<int, int>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForInt32(16), 10);
+    private readonly pbc::MapField<int, int> entry_ = new pbc::MapField<int, int>();
+    public pbc::MapField<int, int> Entry {
+      get { return entry_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as MessageContainingMapCalledEntry);
+    }
+
+    public bool Equals(MessageContainingMapCalledEntry other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!Entry.Equals(other.Entry)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= Entry.GetHashCode();
+      return hash;
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      entry_.WriteTo(output, _map_entry_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += entry_.CalculateSize(_map_entry_codec);
+      return size;
+    }
+
+    public void MergeFrom(MessageContainingMapCalledEntry other) {
+      if (other == null) {
+        return;
+      }
+      entry_.Add(other.entry_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while (input.ReadTag(out tag)) {
+        switch(tag) {
+          case 0:
+            throw pb::InvalidProtocolBufferException.InvalidTag();
+          default:
+            if (pb::WireFormat.IsEndGroupTag(tag)) {
+              return;
+            }
+            break;
+          case 10: {
+            entry_.AddEntriesFrom(input, _map_entry_codec);
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class EntryEntry : pb::IMessage<EntryEntry> {
+        private static readonly pb::MessageParser<EntryEntry> _parser = new pb::MessageParser<EntryEntry>(() => new EntryEntry());
+        public static pb::MessageParser<EntryEntry> Parser { get { return _parser; } }
+
+        private static readonly string[] _fieldNames = new string[] { "key", "value" };
+        private static readonly uint[] _fieldTags = new uint[] { 8, 16 };
+        public static pbd::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_MessageContainingMapCalledEntry_EntryEntry__Descriptor; }
+        }
+
+        public pb::FieldAccess.FieldAccessorTable<EntryEntry> Fields {
+          get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.internal__static_protobuf_unittest_MessageContainingMapCalledEntry_EntryEntry__FieldAccessorTable; }
+        }
+
+        private bool _frozen = false;
+        public bool IsFrozen { get { return _frozen; } }
+
+        public EntryEntry() { }
+
+        public EntryEntry(EntryEntry other) {
+          key_ = other.key_;
+          value_ = other.value_;
+        }
+
+        public EntryEntry Clone() {
+          return new EntryEntry(this);
+        }
+
+        public void Freeze() {
+          if (IsFrozen) {
+            return;
+          }
+          _frozen = true;
+        }
+
+        public const int KeyFieldNumber = 1;
+        private int key_;
+        public int Key {
+          get { return key_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            key_ = value;
+          }
+        }
+
+        public const int ValueFieldNumber = 2;
+        private int value_;
+        public int Value {
+          get { return value_; }
+          set {
+            pb::Freezable.CheckMutable(this);
+            value_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as EntryEntry);
+        }
+
+        public bool Equals(EntryEntry other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Key != other.Key) return false;
+          if (Value != other.Value) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Key != 0) hash ^= Key.GetHashCode();
+          if (Value != 0) hash ^= Value.GetHashCode();
+          return hash;
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Key != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Key);
+          }
+          if (Value != 0) {
+            output.WriteRawTag(16);
+            output.WriteInt32(Value);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Key != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Key);
+          }
+          if (Value != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Value);
+          }
+          return size;
+        }
+
+        public void MergeFrom(EntryEntry other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Key != 0) {
+            Key = other.Key;
+          }
+          if (other.Value != 0) {
+            Value = other.Value;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while (input.ReadTag(out tag)) {
+            switch(tag) {
+              case 0:
+                throw pb::InvalidProtocolBufferException.InvalidTag();
+              default:
+                if (pb::WireFormat.IsEndGroupTag(tag)) {
+                  return;
+                }
+                break;
+              case 8: {
+                Key = input.ReadInt32();
+                break;
+              }
+              case 16: {
+                Value = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code

+ 2 - 1
csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs

@@ -120,7 +120,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (D != 0) hash ^= D.GetHashCode();
       return hash;
     }
@@ -139,6 +139,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(ImportMessage other) {
       if (other == null) {
         return;

+ 2 - 1
csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportPublicProto3.cs

@@ -105,7 +105,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (E != 0) hash ^= E.GetHashCode();
       return hash;
     }
@@ -124,6 +124,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(PublicImportMessage other) {
       if (other == null) {
         return;

+ 8 - 4
csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs

@@ -168,7 +168,7 @@ namespace UnitTest.Issues.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) hash ^= Value.GetHashCode();
       hash ^= values_.GetHashCode();
       hash ^= packedValues_.GetHashCode();
@@ -212,6 +212,7 @@ namespace UnitTest.Issues.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(NegativeEnumMessage other) {
       if (other == null) {
         return;
@@ -303,7 +304,7 @@ namespace UnitTest.Issues.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       return hash;
     }
 
@@ -314,6 +315,7 @@ namespace UnitTest.Issues.TestProtos {
       int size = 0;
       return size;
     }
+
     public void MergeFrom(DeprecatedChild other) {
       if (other == null) {
         return;
@@ -456,7 +458,7 @@ namespace UnitTest.Issues.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (PrimitiveValue != 0) hash ^= PrimitiveValue.GetHashCode();
       hash ^= primitiveArray_.GetHashCode();
       if (messageValue_ != null) hash ^= MessageValue.GetHashCode();
@@ -527,6 +529,7 @@ namespace UnitTest.Issues.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(DeprecatedFieldsMessage other) {
       if (other == null) {
         return;
@@ -655,7 +658,7 @@ namespace UnitTest.Issues.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Item != 0) hash ^= Item.GetHashCode();
       return hash;
     }
@@ -674,6 +677,7 @@ namespace UnitTest.Issues.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(ItemField other) {
       if (other == null) {
         return;

+ 70 - 35
csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs

@@ -995,7 +995,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (SingleInt32 != 0) hash ^= SingleInt32.GetHashCode();
       if (SingleInt64 != 0L) hash ^= SingleInt64.GetHashCode();
       if (SingleUint32 != 0) hash ^= SingleUint32.GetHashCode();
@@ -1472,6 +1472,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(TestAllTypes other) {
       if (other == null) {
         return;
@@ -1905,7 +1906,7 @@ namespace Google.Protobuf.TestProtos {
         }
 
         public override int GetHashCode() {
-          int hash = 0;
+          int hash = 1;
           if (Bb != 0) hash ^= Bb.GetHashCode();
           return hash;
         }
@@ -1924,6 +1925,7 @@ namespace Google.Protobuf.TestProtos {
           }
           return size;
         }
+
         public void MergeFrom(NestedMessage other) {
           if (other == null) {
             return;
@@ -2043,7 +2045,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (child_ != null) hash ^= Child.GetHashCode();
       if (payload_ != null) hash ^= Payload.GetHashCode();
       hash ^= repeatedChild_.GetHashCode();
@@ -2080,6 +2082,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(NestedTestAllTypes other) {
       if (other == null) {
         return;
@@ -2196,7 +2199,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (DeprecatedInt32 != 0) hash ^= DeprecatedInt32.GetHashCode();
       return hash;
     }
@@ -2215,6 +2218,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(TestDeprecatedFields other) {
       if (other == null) {
         return;
@@ -2306,7 +2310,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (C != 0) hash ^= C.GetHashCode();
       return hash;
     }
@@ -2325,6 +2329,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(ForeignMessage other) {
       if (other == null) {
         return;
@@ -2404,7 +2409,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       return hash;
     }
 
@@ -2415,6 +2420,7 @@ namespace Google.Protobuf.TestProtos {
       int size = 0;
       return size;
     }
+
     public void MergeFrom(TestReservedFields other) {
       if (other == null) {
         return;
@@ -2500,7 +2506,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (foreignNested_ != null) hash ^= ForeignNested.GetHashCode();
       return hash;
     }
@@ -2519,6 +2525,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(TestForeignNested other) {
       if (other == null) {
         return;
@@ -2628,7 +2635,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (A != 0) hash ^= A.GetHashCode();
       if (Bb != 0) hash ^= Bb.GetHashCode();
       return hash;
@@ -2655,6 +2662,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(TestReallyLargeTagNumber other) {
       if (other == null) {
         return;
@@ -2766,7 +2774,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (a_ != null) hash ^= A.GetHashCode();
       if (I != 0) hash ^= I.GetHashCode();
       return hash;
@@ -2793,6 +2801,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(TestRecursiveMessage other) {
       if (other == null) {
         return;
@@ -2898,7 +2907,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (bb_ != null) hash ^= Bb.GetHashCode();
       return hash;
     }
@@ -2917,6 +2926,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(TestMutualRecursionA other) {
       if (other == null) {
         return;
@@ -3027,7 +3037,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (a_ != null) hash ^= A.GetHashCode();
       if (OptionalInt32 != 0) hash ^= OptionalInt32.GetHashCode();
       return hash;
@@ -3054,6 +3064,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(TestMutualRecursionB other) {
       if (other == null) {
         return;
@@ -3231,7 +3242,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (PrimitiveField != 0) hash ^= PrimitiveField.GetHashCode();
       if (StringField.Length != 0) hash ^= StringField.GetHashCode();
       if (EnumField != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) hash ^= EnumField.GetHashCode();
@@ -3322,6 +3333,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(TestCamelCaseFieldNames other) {
       if (other == null) {
         return;
@@ -3499,7 +3511,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (MyString.Length != 0) hash ^= MyString.GetHashCode();
       if (MyInt != 0L) hash ^= MyInt.GetHashCode();
       if (MyFloat != 0F) hash ^= MyFloat.GetHashCode();
@@ -3542,6 +3554,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(TestFieldOrderings other) {
       if (other == null) {
         return;
@@ -3673,7 +3686,7 @@ namespace Google.Protobuf.TestProtos {
         }
 
         public override int GetHashCode() {
-          int hash = 0;
+          int hash = 1;
           if (Oo != 0L) hash ^= Oo.GetHashCode();
           if (Bb != 0) hash ^= Bb.GetHashCode();
           return hash;
@@ -3700,6 +3713,7 @@ namespace Google.Protobuf.TestProtos {
           }
           return size;
         }
+
         public void MergeFrom(NestedMessage other) {
           if (other == null) {
             return;
@@ -3803,7 +3817,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.TEST_SPARSE_ENUM_UNSPECIFIED) hash ^= SparseEnum.GetHashCode();
       return hash;
     }
@@ -3822,6 +3836,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(SparseEnumMessage other) {
       if (other == null) {
         return;
@@ -3913,7 +3928,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Data.Length != 0) hash ^= Data.GetHashCode();
       return hash;
     }
@@ -3932,6 +3947,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(OneString other) {
       if (other == null) {
         return;
@@ -4020,7 +4036,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       hash ^= data_.GetHashCode();
       return hash;
     }
@@ -4043,6 +4059,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(MoreString other) {
       if (other == null) {
         return;
@@ -4132,7 +4149,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Data.Length != 0) hash ^= Data.GetHashCode();
       return hash;
     }
@@ -4151,6 +4168,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(OneBytes other) {
       if (other == null) {
         return;
@@ -4242,7 +4260,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Data.Length != 0) hash ^= Data.GetHashCode();
       return hash;
     }
@@ -4261,6 +4279,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(MoreBytes other) {
       if (other == null) {
         return;
@@ -4352,7 +4371,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Data != 0) hash ^= Data.GetHashCode();
       return hash;
     }
@@ -4371,6 +4390,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(Int32Message other) {
       if (other == null) {
         return;
@@ -4462,7 +4482,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Data != 0) hash ^= Data.GetHashCode();
       return hash;
     }
@@ -4481,6 +4501,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(Uint32Message other) {
       if (other == null) {
         return;
@@ -4572,7 +4593,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Data != 0L) hash ^= Data.GetHashCode();
       return hash;
     }
@@ -4591,6 +4612,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(Int64Message other) {
       if (other == null) {
         return;
@@ -4682,7 +4704,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Data != 0UL) hash ^= Data.GetHashCode();
       return hash;
     }
@@ -4701,6 +4723,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(Uint64Message other) {
       if (other == null) {
         return;
@@ -4792,7 +4815,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Data != false) hash ^= Data.GetHashCode();
       return hash;
     }
@@ -4811,6 +4834,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(BoolMessage other) {
       if (other == null) {
         return;
@@ -4954,7 +4978,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (fooCase_ == FooOneofCase.FooInt) hash ^= FooInt.GetHashCode();
       if (fooCase_ == FooOneofCase.FooString) hash ^= FooString.GetHashCode();
       if (fooCase_ == FooOneofCase.FooMessage) hash ^= FooMessage.GetHashCode();
@@ -4989,6 +5013,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(TestOneof other) {
       if (other == null) {
         return;
@@ -5216,7 +5241,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       hash ^= packedInt32_.GetHashCode();
       hash ^= packedInt64_.GetHashCode();
       hash ^= packedUint32_.GetHashCode();
@@ -5395,6 +5420,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(TestPackedTypes other) {
       if (other == null) {
         return;
@@ -5677,7 +5703,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       hash ^= unpackedInt32_.GetHashCode();
       hash ^= unpackedInt64_.GetHashCode();
       hash ^= unpackedUint32_.GetHashCode();
@@ -5842,6 +5868,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(TestUnpackedTypes other) {
       if (other == null) {
         return;
@@ -6052,7 +6079,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       hash ^= repeatedFixed32_.GetHashCode();
       hash ^= repeatedInt32_.GetHashCode();
       hash ^= repeatedFixed64_.GetHashCode();
@@ -6135,6 +6162,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(TestRepeatedScalarDifferentTagSizes other) {
       if (other == null) {
         return;
@@ -6255,7 +6283,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (A.Length != 0) hash ^= A.GetHashCode();
       return hash;
     }
@@ -6274,6 +6302,7 @@ namespace Google.Protobuf.TestProtos {
       }
       return size;
     }
+
     public void MergeFrom(TestCommentInjectionMessage other) {
       if (other == null) {
         return;
@@ -6353,7 +6382,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       return hash;
     }
 
@@ -6364,6 +6393,7 @@ namespace Google.Protobuf.TestProtos {
       int size = 0;
       return size;
     }
+
     public void MergeFrom(FooRequest other) {
       if (other == null) {
         return;
@@ -6436,7 +6466,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       return hash;
     }
 
@@ -6447,6 +6477,7 @@ namespace Google.Protobuf.TestProtos {
       int size = 0;
       return size;
     }
+
     public void MergeFrom(FooResponse other) {
       if (other == null) {
         return;
@@ -6519,7 +6550,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       return hash;
     }
 
@@ -6530,6 +6561,7 @@ namespace Google.Protobuf.TestProtos {
       int size = 0;
       return size;
     }
+
     public void MergeFrom(FooClientMessage other) {
       if (other == null) {
         return;
@@ -6602,7 +6634,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       return hash;
     }
 
@@ -6613,6 +6645,7 @@ namespace Google.Protobuf.TestProtos {
       int size = 0;
       return size;
     }
+
     public void MergeFrom(FooServerMessage other) {
       if (other == null) {
         return;
@@ -6685,7 +6718,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       return hash;
     }
 
@@ -6696,6 +6729,7 @@ namespace Google.Protobuf.TestProtos {
       int size = 0;
       return size;
     }
+
     public void MergeFrom(BarRequest other) {
       if (other == null) {
         return;
@@ -6768,7 +6802,7 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       return hash;
     }
 
@@ -6779,6 +6813,7 @@ namespace Google.Protobuf.TestProtos {
       int size = 0;
       return size;
     }
+
     public void MergeFrom(BarResponse other) {
       if (other == null) {
         return;

+ 10 - 18
csharp/src/ProtocolBuffers/CodedInputStream.cs

@@ -456,14 +456,16 @@ namespace Google.Protobuf
         }
 
         /// <summary>
-        /// Returns true if the next tag is also part of the same unpacked array.
+        /// Peeks at the next tag in the stream. If it matches <paramref name="tag"/>,
+        /// the tag is consumed and the method returns <c>true</c>; otherwise, the
+        /// stream is left in the original position and the method returns <c>false</c>.
         /// </summary>
-        private bool ContinueArray(uint currentTag)
+        public bool MaybeConsumeTag(uint tag)
         {
             uint next;
             if (PeekNextTag(out next))
             {
-                if (next == currentTag)
+                if (next == tag)
                 {
                     hasNextTag = false;
                     return true;
@@ -486,17 +488,7 @@ namespace Google.Protobuf
                 }
                 return true;
             }
-
-            uint next;
-            if (PeekNextTag(out next))
-            {
-                if (next == currentTag)
-                {
-                    hasNextTag = false;
-                    return true;
-                }
-            }
-            return false;
+            return MaybeConsumeTag(currentTag);
         }
 
         /// <summary>
@@ -512,7 +504,7 @@ namespace Google.Protobuf
             do
             {
                 list.Add(ReadString());
-            } while (ContinueArray(fieldTag));
+            } while (MaybeConsumeTag(fieldTag));
         }
 
         public void ReadBytesArray(ICollection<ByteString> list)
@@ -521,7 +513,7 @@ namespace Google.Protobuf
             do
             {
                 list.Add(ReadBytes());
-            } while (ContinueArray(fieldTag));
+            } while (MaybeConsumeTag(fieldTag));
         }
 
         public void ReadBoolArray(ICollection<bool> list)
@@ -729,7 +721,7 @@ namespace Google.Protobuf
                 do
                 {
                     list.Add((T)(object) ReadEnum());
-                } while (ContinueArray(fieldTag));
+                } while (MaybeConsumeTag(fieldTag));
             }
         }
 
@@ -742,7 +734,7 @@ namespace Google.Protobuf
                 T message = messageParser.CreateTemplate();
                 ReadMessage(message);
                 list.Add(message);
-            } while (ContinueArray(fieldTag));
+            } while (MaybeConsumeTag(fieldTag));
         }
         #endregion
 

+ 8 - 0
csharp/src/ProtocolBuffers/CodedOutputStream.cs

@@ -475,6 +475,14 @@ namespace Google.Protobuf
             WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type));
         }
 
+        /// <summary>
+        /// Writes an already-encoded tag.
+        /// </summary>
+        public void WriteTag(uint tag)
+        {
+            WriteRawVarint32(tag);
+        }
+
         /// <summary>
         /// Writes the given single-byte tag directly to the stream.
         /// </summary>

+ 433 - 0
csharp/src/ProtocolBuffers/Collections/MapField.cs

@@ -0,0 +1,433 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Google.Protobuf.Collections
+{
+    /// <summary>
+    /// Representation of a map field in a Protocol Buffer message.
+    /// </summary>
+    /// <remarks>
+    /// This implementation preserves insertion order for simplicity of testing
+    /// code using maps fields. Overwriting an existing entry does not change the
+    /// position of that entry within the map. Equality is not order-sensitive.
+    /// For string keys, the equality comparison is provided by <see cref="StringComparer.Ordinal"/>.
+    /// </remarks>
+    /// <typeparam name="TKey">Key type in the map. Must be a type supported by Protocol Buffer map keys.</typeparam>
+    /// <typeparam name="TValue">Value type in the map. Must be a type supported by Protocol Buffers.</typeparam>
+    public sealed class MapField<TKey, TValue> : IDeepCloneable<MapField<TKey, TValue>>, IFreezable, IDictionary<TKey, TValue>, IEquatable<MapField<TKey, TValue>>
+    {
+        // TODO: Don't create the map/list until we have an entry. (Assume many maps will be empty.)
+        private bool frozen;
+        private readonly Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>> map =
+            new Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>();
+        private readonly LinkedList<KeyValuePair<TKey, TValue>> list = new LinkedList<KeyValuePair<TKey, TValue>>();
+
+        public MapField<TKey, TValue> Clone()
+        {
+            var clone = new MapField<TKey, TValue>();
+            // Keys are never cloneable. Values might be.
+            if (typeof(IDeepCloneable<TValue>).IsAssignableFrom(typeof(TValue)))
+            {
+                foreach (var pair in list)
+                {
+                    clone.Add(pair.Key, pair.Value == null ? pair.Value : ((IDeepCloneable<TValue>) pair.Value).Clone());
+                }
+            }
+            else
+            {
+                // Nothing is cloneable, so we don't need to worry.
+                clone.Add(this);
+            }
+            return clone;
+        }
+
+        public void Add(TKey key, TValue value)
+        {
+            // Validation of arguments happens in ContainsKey and the indexer
+            if (ContainsKey(key))
+            {
+                throw new ArgumentException("Key already exists in map", "key");
+            }
+            this[key] = value;
+        }
+
+        public bool ContainsKey(TKey key)
+        {
+            ThrowHelper.ThrowIfNull(key, "key");
+            return map.ContainsKey(key);
+        }
+
+        public bool Remove(TKey key)
+        {
+            this.CheckMutable();
+            ThrowHelper.ThrowIfNull(key, "key");
+            LinkedListNode<KeyValuePair<TKey, TValue>> node;
+            if (map.TryGetValue(key, out node))
+            {
+                map.Remove(key);
+                node.List.Remove(node);
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+        public bool TryGetValue(TKey key, out TValue value)
+        {
+            LinkedListNode<KeyValuePair<TKey, TValue>> node;
+            if (map.TryGetValue(key, out node))
+            {
+                value = node.Value.Value;
+                return true;
+            }
+            else
+            {
+                value = default(TValue);
+                return false;
+            }
+        }
+
+        public TValue this[TKey key]
+        {
+            get
+            {
+                ThrowHelper.ThrowIfNull(key, "key");
+                TValue value;
+                if (TryGetValue(key, out value))
+                {
+                    return value;
+                }
+                throw new KeyNotFoundException();
+            }
+            set
+            {
+                ThrowHelper.ThrowIfNull(key, "key");
+                if (value == null && (typeof(TValue) == typeof(ByteString) || typeof(TValue) == typeof(string)))
+                {
+                    ThrowHelper.ThrowIfNull(value, "value");
+                }
+                this.CheckMutable();
+                LinkedListNode<KeyValuePair<TKey, TValue>> node;
+                var pair = new KeyValuePair<TKey, TValue>(key, value);
+                if (map.TryGetValue(key, out node))
+                {
+                    node.Value = pair;
+                }
+                else
+                {
+                    node = list.AddLast(pair);
+                    map[key] = node;
+                }
+            }
+        }
+
+        // TODO: Make these views?
+        public ICollection<TKey> Keys { get { return list.Select(t => t.Key).ToList(); } }
+        public ICollection<TValue> Values { get { return list.Select(t => t.Value).ToList(); } }
+
+        public void Add(IDictionary<TKey, TValue> entries)
+        {
+            ThrowHelper.ThrowIfNull(entries, "entries");
+            foreach (var pair in entries)
+            {
+                Add(pair.Key, pair.Value);
+            }
+        }
+
+        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
+        {
+            return list.GetEnumerator();
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+
+        void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
+        {
+            Add(item.Key, item.Value);
+        }
+
+        public void Clear()
+        {
+            this.CheckMutable();
+            list.Clear();
+            map.Clear();
+        }
+
+        bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
+        {
+            TValue value;
+            return TryGetValue(item.Key, out value)
+                && EqualityComparer<TValue>.Default.Equals(item.Value, value);
+        }
+
+        void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
+        {
+            list.CopyTo(array, arrayIndex);
+        }
+
+        bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
+        {
+            this.CheckMutable();
+            if (item.Key == null)
+            {
+                throw new ArgumentException("Key is null", "item");
+            }
+            LinkedListNode<KeyValuePair<TKey, TValue>> node;
+            if (map.TryGetValue(item.Key, out node) &&
+                EqualityComparer<TValue>.Default.Equals(item.Value, node.Value.Value))
+            {
+                map.Remove(item.Key);
+                node.List.Remove(node);
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+        public int Count { get { return list.Count; } }
+        public bool IsReadOnly { get { return frozen; } }
+
+        public void Freeze()
+        {
+            if (IsFrozen)
+            {
+                return;
+            }
+            frozen = true;
+            // Only values can be frozen, as all the key types are simple.
+            // Everything can be done in-place, as we're just freezing objects.
+            if (typeof(IFreezable).IsAssignableFrom(typeof(TValue)))
+            {
+                for (var node = list.First; node != null; node = node.Next)
+                {
+                    var pair = node.Value;
+                    IFreezable freezableValue = pair.Value as IFreezable;
+                    if (freezableValue != null)
+                    {
+                        freezableValue.Freeze();
+                    }
+                }
+            }
+        }
+
+        public bool IsFrozen { get { return frozen; } }
+
+        public override bool Equals(object other)
+        {
+            return Equals(other as MapField<TKey, TValue>);
+        }
+
+        public override int GetHashCode()
+        {
+            var valueComparer = EqualityComparer<TValue>.Default;
+            int hash = 0;
+            foreach (var pair in list)
+            {
+                hash ^= pair.Key.GetHashCode() * 31 + valueComparer.GetHashCode(pair.Value);
+            }
+            return hash;
+        }
+
+        public bool Equals(MapField<TKey, TValue> other)
+        {
+            if (other == null)
+            {
+                return false;
+            }
+            if (other == this)
+            {
+                return true;
+            }
+            if (other.Count != this.Count)
+            {
+                return false;
+            }
+            var valueComparer = EqualityComparer<TValue>.Default;
+            foreach (var pair in this)
+            {
+                TValue value;
+                if (!other.TryGetValue(pair.Key, out value))
+                {
+                    return false;
+                }
+                if (!valueComparer.Equals(value, pair.Value))
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// Adds entries to the map from the given stream.
+        /// </summary>
+        /// <remarks>
+        /// It is assumed that the stream is initially positioned after the tag specified by the codec.
+        /// This method will continue reading entries from the stream until the end is reached, or
+        /// a different tag is encountered.
+        /// </remarks>
+        /// <param name="input">Stream to read from</param>
+        /// <param name="codec">Codec describing how the key/value pairs are encoded</param>
+        public void AddEntriesFrom(CodedInputStream input, Codec codec)            
+        {
+            var adapter = new Codec.MessageAdapter(codec);
+            do
+            {
+                adapter.Reset();
+                input.ReadMessage(adapter);
+                this[adapter.Key] = adapter.Value;
+            } while (input.MaybeConsumeTag(codec.MapTag));
+        }        
+
+        public void WriteTo(CodedOutputStream output, Codec codec)
+        {
+            var message = new Codec.MessageAdapter(codec);
+            foreach (var entry in list)
+            {
+                message.Key = entry.Key;
+                message.Value = entry.Value;
+                output.WriteTag(codec.MapTag);
+                output.WriteMessage(message);
+            }
+        }
+
+        public int CalculateSize(Codec codec)
+        {
+            var message = new Codec.MessageAdapter(codec);
+            int size = 0;
+            foreach (var entry in list)
+            {
+                message.Key = entry.Key;
+                message.Value = entry.Value;
+                size += CodedOutputStream.ComputeRawVarint32Size(codec.MapTag);
+                size += CodedOutputStream.ComputeMessageSize(message);
+            }
+            return size;
+        }
+
+        /// <summary>
+        /// A codec for a specific map field. This contains all the information required to encoded and
+        /// decode the nested messages.
+        /// </summary>
+        public sealed class Codec
+        {
+            private readonly FieldCodec<TKey> keyCodec;
+            private readonly FieldCodec<TValue> valueCodec;
+            private readonly uint mapTag;
+
+            public Codec(FieldCodec<TKey> keyCodec, FieldCodec<TValue> valueCodec, uint mapTag)
+            {
+                this.keyCodec = keyCodec;
+                this.valueCodec = valueCodec;
+                this.mapTag = mapTag;
+            }
+
+            /// <summary>
+            /// The tag used in the enclosing message to indicate map entries.
+            /// </summary>
+            internal uint MapTag { get { return mapTag; } }
+
+            /// <summary>
+            /// A mutable message class, used for parsing and serializing. This
+            /// delegates the work to a codec, but implements the <see cref="IMessage"/> interface
+            /// for interop with <see cref="CodedInputStream"/> and <see cref="CodedOutputStream"/>.
+            /// This is nested inside Codec as it's tightly coupled to the associated codec,
+            /// and it's simpler if it has direct access to all its fields.
+            /// </summary>
+            internal class MessageAdapter : IMessage
+            {
+                private readonly Codec codec;
+                internal TKey Key { get; set; }
+                internal TValue Value { get; set; }
+
+                internal MessageAdapter(Codec codec)
+                {
+                    this.codec = codec;
+                }
+
+                internal void Reset()
+                {
+                    Key = codec.keyCodec.DefaultValue;
+                    Value = codec.valueCodec.DefaultValue;
+                }
+
+                public void MergeFrom(CodedInputStream input)
+                {
+                    uint tag;
+                    while (input.ReadTag(out tag))
+                    {
+                        if (tag == 0)
+                        {
+                            throw InvalidProtocolBufferException.InvalidTag();
+                        }
+                        if (tag == codec.keyCodec.Tag)
+                        {
+                            Key = codec.keyCodec.Read(input);
+                        }
+                        else if (tag == codec.valueCodec.Tag)
+                        {
+                            Value = codec.valueCodec.Read(input);
+                        }
+                        else if (WireFormat.IsEndGroupTag(tag))
+                        {
+                            // TODO(jonskeet): Do we need this? (Given that we don't support groups...)
+                            return;
+                        }
+                    }
+                }
+
+                public void WriteTo(CodedOutputStream output)
+                {
+                    codec.keyCodec.Write(output, Key);
+                    codec.valueCodec.Write(output, Value);
+                }
+
+                public int CalculateSize()
+                {
+                    return codec.keyCodec.CalculateSize(Key) + codec.valueCodec.CalculateSize(Value);
+                }
+            }
+        }
+    }
+}

+ 1 - 1
csharp/src/ProtocolBuffers/Collections/RepeatedField.cs

@@ -193,7 +193,7 @@ namespace Google.Protobuf.Collections
 
         public override int GetHashCode()
         {
-            int hash = 23;
+            int hash = 0;
             for (int i = 0; i < count; i++)
             {
                 hash = hash * 31 + array[i].GetHashCode();

+ 44 - 22
csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs

@@ -335,7 +335,7 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       hash ^= file_.GetHashCode();
       return hash;
     }
@@ -356,6 +356,7 @@ namespace Google.Protobuf.DescriptorProtos {
       }
       return size;
     }
+
     public void MergeFrom(FileDescriptorSet other) {
       if (other == null) {
         return;
@@ -558,7 +559,7 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
       if (Package.Length != 0) hash ^= Package.GetHashCode();
       hash ^= dependency_.GetHashCode();
@@ -685,6 +686,7 @@ namespace Google.Protobuf.DescriptorProtos {
       }
       return size;
     }
+
     public void MergeFrom(FileDescriptorProto other) {
       if (other == null) {
         return;
@@ -938,7 +940,7 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
       hash ^= field_.GetHashCode();
       hash ^= extension_.GetHashCode();
@@ -1047,6 +1049,7 @@ namespace Google.Protobuf.DescriptorProtos {
       }
       return size;
     }
+
     public void MergeFrom(DescriptorProto other) {
       if (other == null) {
         return;
@@ -1204,7 +1207,7 @@ namespace Google.Protobuf.DescriptorProtos {
         }
 
         public override int GetHashCode() {
-          int hash = 0;
+          int hash = 1;
           if (Start != 0) hash ^= Start.GetHashCode();
           if (End != 0) hash ^= End.GetHashCode();
           return hash;
@@ -1231,6 +1234,7 @@ namespace Google.Protobuf.DescriptorProtos {
           }
           return size;
         }
+
         public void MergeFrom(ExtensionRange other) {
           if (other == null) {
             return;
@@ -1341,7 +1345,7 @@ namespace Google.Protobuf.DescriptorProtos {
         }
 
         public override int GetHashCode() {
-          int hash = 0;
+          int hash = 1;
           if (Start != 0) hash ^= Start.GetHashCode();
           if (End != 0) hash ^= End.GetHashCode();
           return hash;
@@ -1368,6 +1372,7 @@ namespace Google.Protobuf.DescriptorProtos {
           }
           return size;
         }
+
         public void MergeFrom(ReservedRange other) {
           if (other == null) {
             return;
@@ -1568,7 +1573,7 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
       if (Number != 0) hash ^= Number.GetHashCode();
       if (Label != global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Label.LABEL_OPTIONAL) hash ^= Label.GetHashCode();
@@ -1651,6 +1656,7 @@ namespace Google.Protobuf.DescriptorProtos {
       }
       return size;
     }
+
     public void MergeFrom(FieldDescriptorProto other) {
       if (other == null) {
         return;
@@ -1837,7 +1843,7 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
       return hash;
     }
@@ -1856,6 +1862,7 @@ namespace Google.Protobuf.DescriptorProtos {
       }
       return size;
     }
+
     public void MergeFrom(OneofDescriptorProto other) {
       if (other == null) {
         return;
@@ -1969,7 +1976,7 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
       hash ^= value_.GetHashCode();
       if (options_ != null) hash ^= Options.GetHashCode();
@@ -2006,6 +2013,7 @@ namespace Google.Protobuf.DescriptorProtos {
       }
       return size;
     }
+
     public void MergeFrom(EnumDescriptorProto other) {
       if (other == null) {
         return;
@@ -2140,7 +2148,7 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
       if (Number != 0) hash ^= Number.GetHashCode();
       if (options_ != null) hash ^= Options.GetHashCode();
@@ -2175,6 +2183,7 @@ namespace Google.Protobuf.DescriptorProtos {
       }
       return size;
     }
+
     public void MergeFrom(EnumValueDescriptorProto other) {
       if (other == null) {
         return;
@@ -2308,7 +2317,7 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
       hash ^= method_.GetHashCode();
       if (options_ != null) hash ^= Options.GetHashCode();
@@ -2345,6 +2354,7 @@ namespace Google.Protobuf.DescriptorProtos {
       }
       return size;
     }
+
     public void MergeFrom(ServiceDescriptorProto other) {
       if (other == null) {
         return;
@@ -2515,7 +2525,7 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
       if (InputType.Length != 0) hash ^= InputType.GetHashCode();
       if (OutputType.Length != 0) hash ^= OutputType.GetHashCode();
@@ -2574,6 +2584,7 @@ namespace Google.Protobuf.DescriptorProtos {
       }
       return size;
     }
+
     public void MergeFrom(MethodDescriptorProto other) {
       if (other == null) {
         return;
@@ -2871,7 +2882,7 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (JavaPackage.Length != 0) hash ^= JavaPackage.GetHashCode();
       if (JavaOuterClassname.Length != 0) hash ^= JavaOuterClassname.GetHashCode();
       if (JavaMultipleFiles != false) hash ^= JavaMultipleFiles.GetHashCode();
@@ -3004,6 +3015,7 @@ namespace Google.Protobuf.DescriptorProtos {
       }
       return size;
     }
+
     public void MergeFrom(FileOptions other) {
       if (other == null) {
         return;
@@ -3248,7 +3260,7 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (MessageSetWireFormat != false) hash ^= MessageSetWireFormat.GetHashCode();
       if (NoStandardDescriptorAccessor != false) hash ^= NoStandardDescriptorAccessor.GetHashCode();
       if (Deprecated != false) hash ^= Deprecated.GetHashCode();
@@ -3301,6 +3313,7 @@ namespace Google.Protobuf.DescriptorProtos {
       }
       return size;
     }
+
     public void MergeFrom(MessageOptions other) {
       if (other == null) {
         return;
@@ -3487,7 +3500,7 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Ctype != global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.CType.STRING) hash ^= Ctype.GetHashCode();
       if (Packed != false) hash ^= Packed.GetHashCode();
       if (Jstype != global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.JSType.JS_NORMAL) hash ^= Jstype.GetHashCode();
@@ -3556,6 +3569,7 @@ namespace Google.Protobuf.DescriptorProtos {
       }
       return size;
     }
+
     public void MergeFrom(FieldOptions other) {
       if (other == null) {
         return;
@@ -3726,7 +3740,7 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (AllowAlias != false) hash ^= AllowAlias.GetHashCode();
       if (Deprecated != false) hash ^= Deprecated.GetHashCode();
       hash ^= uninterpretedOption_.GetHashCode();
@@ -3763,6 +3777,7 @@ namespace Google.Protobuf.DescriptorProtos {
       }
       return size;
     }
+
     public void MergeFrom(EnumOptions other) {
       if (other == null) {
         return;
@@ -3875,7 +3890,7 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Deprecated != false) hash ^= Deprecated.GetHashCode();
       hash ^= uninterpretedOption_.GetHashCode();
       return hash;
@@ -3904,6 +3919,7 @@ namespace Google.Protobuf.DescriptorProtos {
       }
       return size;
     }
+
     public void MergeFrom(EnumValueOptions other) {
       if (other == null) {
         return;
@@ -4009,7 +4025,7 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Deprecated != false) hash ^= Deprecated.GetHashCode();
       hash ^= uninterpretedOption_.GetHashCode();
       return hash;
@@ -4038,6 +4054,7 @@ namespace Google.Protobuf.DescriptorProtos {
       }
       return size;
     }
+
     public void MergeFrom(ServiceOptions other) {
       if (other == null) {
         return;
@@ -4143,7 +4160,7 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       if (Deprecated != false) hash ^= Deprecated.GetHashCode();
       hash ^= uninterpretedOption_.GetHashCode();
       return hash;
@@ -4172,6 +4189,7 @@ namespace Google.Protobuf.DescriptorProtos {
       }
       return size;
     }
+
     public void MergeFrom(MethodOptions other) {
       if (other == null) {
         return;
@@ -4337,7 +4355,7 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       hash ^= name_.GetHashCode();
       if (IdentifierValue.Length != 0) hash ^= IdentifierValue.GetHashCode();
       if (PositiveIntValue != 0UL) hash ^= PositiveIntValue.GetHashCode();
@@ -4406,6 +4424,7 @@ namespace Google.Protobuf.DescriptorProtos {
       }
       return size;
     }
+
     public void MergeFrom(UninterpretedOption other) {
       if (other == null) {
         return;
@@ -4550,7 +4569,7 @@ namespace Google.Protobuf.DescriptorProtos {
         }
 
         public override int GetHashCode() {
-          int hash = 0;
+          int hash = 1;
           if (NamePart_.Length != 0) hash ^= NamePart_.GetHashCode();
           if (IsExtension != false) hash ^= IsExtension.GetHashCode();
           return hash;
@@ -4577,6 +4596,7 @@ namespace Google.Protobuf.DescriptorProtos {
           }
           return size;
         }
+
         public void MergeFrom(NamePart other) {
           if (other == null) {
             return;
@@ -4677,7 +4697,7 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public override int GetHashCode() {
-      int hash = 0;
+      int hash = 1;
       hash ^= location_.GetHashCode();
       return hash;
     }
@@ -4698,6 +4718,7 @@ namespace Google.Protobuf.DescriptorProtos {
       }
       return size;
     }
+
     public void MergeFrom(SourceCodeInfo other) {
       if (other == null) {
         return;
@@ -4827,7 +4848,7 @@ namespace Google.Protobuf.DescriptorProtos {
         }
 
         public override int GetHashCode() {
-          int hash = 0;
+          int hash = 1;
           hash ^= path_.GetHashCode();
           hash ^= span_.GetHashCode();
           if (LeadingComments.Length != 0) hash ^= LeadingComments.GetHashCode();
@@ -4892,6 +4913,7 @@ namespace Google.Protobuf.DescriptorProtos {
           }
           return size;
         }
+
         public void MergeFrom(Location other) {
           if (other == null) {
             return;

+ 188 - 0
csharp/src/ProtocolBuffers/FieldCodec.cs

@@ -0,0 +1,188 @@
+using System;
+using System.Collections.Generic;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Factory methods for <see cref="FieldCodec{T}"/>.
+    /// </summary>
+    public static class FieldCodec
+    {
+        public static FieldCodec<string> ForString(uint tag)
+        {
+            return new FieldCodec<string>(input => input.ReadString(), (output, value) => output.WriteString(value), CodedOutputStream.ComputeStringSize, tag); 
+        }
+
+        public static FieldCodec<ByteString> ForBytes(uint tag)
+        {
+            return new FieldCodec<ByteString>(input => input.ReadBytes(), (output, value) => output.WriteBytes(value), CodedOutputStream.ComputeBytesSize, tag);
+        }
+
+        public static FieldCodec<bool> ForBool(uint tag)
+        {
+            return new FieldCodec<bool>(input => input.ReadBool(), (output, value) => output.WriteBool(value), CodedOutputStream.ComputeBoolSize, tag);
+        }
+
+        public static FieldCodec<int> ForInt32(uint tag)
+        {
+            return new FieldCodec<int>(input => input.ReadInt32(), (output, value) => output.WriteInt32(value), CodedOutputStream.ComputeInt32Size, tag);
+        }
+
+        public static FieldCodec<int> ForSInt32(uint tag)
+        {
+            return new FieldCodec<int>(input => input.ReadSInt32(), (output, value) => output.WriteSInt32(value), CodedOutputStream.ComputeSInt32Size, tag);
+        }
+
+        public static FieldCodec<uint> ForFixed32(uint tag)
+        {
+            return new FieldCodec<uint>(input => input.ReadFixed32(), (output, value) => output.WriteFixed32(value), CodedOutputStream.ComputeFixed32Size, tag);
+        }
+
+        public static FieldCodec<int> ForSFixed32(uint tag)
+        {
+            return new FieldCodec<int>(input => input.ReadSFixed32(), (output, value) => output.WriteSFixed32(value), CodedOutputStream.ComputeSFixed32Size, tag);
+        }
+
+        public static FieldCodec<uint> ForUInt32(uint tag)
+        {
+            return new FieldCodec<uint>(input => input.ReadUInt32(), (output, value) => output.WriteUInt32(value), CodedOutputStream.ComputeUInt32Size, tag);
+        }
+
+        public static FieldCodec<long> ForInt64(uint tag)
+        {
+            return new FieldCodec<long>(input => input.ReadInt64(), (output, value) => output.WriteInt64(value), CodedOutputStream.ComputeInt64Size, tag);
+        }
+
+        public static FieldCodec<long> ForSInt64(uint tag)
+        {
+            return new FieldCodec<long>(input => input.ReadSInt64(), (output, value) => output.WriteSInt64(value), CodedOutputStream.ComputeSInt64Size, tag);
+        }
+
+        public static FieldCodec<ulong> ForFixed64(uint tag)
+        {
+            return new FieldCodec<ulong>(input => input.ReadFixed64(), (output, value) => output.WriteFixed64(value), CodedOutputStream.ComputeFixed64Size, tag);
+        }
+
+        public static FieldCodec<long> ForSFixed64(uint tag)
+        {
+            return new FieldCodec<long>(input => input.ReadSFixed64(), (output, value) => output.WriteSFixed64(value), CodedOutputStream.ComputeSFixed64Size, tag);
+        }
+
+        public static FieldCodec<ulong> ForUInt64(uint tag)
+        {
+            return new FieldCodec<ulong>(input => input.ReadUInt64(), (output, value) => output.WriteUInt64(value), CodedOutputStream.ComputeUInt64Size, tag);
+        }
+
+        public static FieldCodec<float> ForFloat(uint tag)
+        {
+            return new FieldCodec<float>(input => input.ReadFloat(), (output, value) => output.WriteFloat(value), CodedOutputStream.ComputeFloatSize, tag);
+        }
+
+        public static FieldCodec<double> ForDouble(uint tag)
+        {
+            return new FieldCodec<double>(input => input.ReadDouble(), (output, value) => output.WriteDouble(value), CodedOutputStream.ComputeDoubleSize, tag);
+        }
+
+        // Enums are tricky. We can probably use expression trees to build these delegates automatically,
+        // but it's easy to generate the code fdor it.
+        public static FieldCodec<T> ForEnum<T>(uint tag, Func<T, int> toInt32, Func<int, T> fromInt32)
+        {
+            return new FieldCodec<T>(input => fromInt32(
+                input.ReadEnum()),
+                (output, value) => output.WriteEnum(toInt32(value)),
+                value => CodedOutputStream.ComputeEnumSize(toInt32(value)), tag);
+        }
+
+        public static FieldCodec<T> ForMessage<T>(uint tag, MessageParser<T> parser) where T : IMessage<T>
+        {
+            return new FieldCodec<T>(input => { T message = parser.CreateTemplate(); input.ReadMessage(message); return message; },
+                (output, value) => output.WriteMessage(value), message => CodedOutputStream.ComputeMessageSize(message), tag);
+        }
+    }
+
+    /// <summary>
+    /// An encode/decode pair for a single field. This effectively encapsulates
+    /// all the information needed to read or write the field value from/to a coded
+    /// stream.
+    /// </summary>
+    /// <remarks>
+    /// This never writes default values to the stream, and is not currently designed
+    /// to play well with packed arrays.
+    /// </remarks>
+    public sealed class FieldCodec<T>
+    {
+        private static readonly Func<T, bool> IsDefault;
+        private static readonly T Default;
+
+        static FieldCodec()
+        {
+            if (typeof(T) == typeof(string))
+            {
+                Default = (T)(object)"";
+                IsDefault = CreateDefaultValueCheck<string>(x => x.Length == 0);
+            }
+            else if (typeof(T) == typeof(ByteString))
+            {
+                Default = (T)(object)ByteString.Empty;
+                IsDefault = CreateDefaultValueCheck<ByteString>(x => x.Length == 0);
+            }
+            else if (!typeof(T).IsValueType)
+            {
+                // Default default
+                IsDefault = CreateDefaultValueCheck<T>(x => x == null);
+            }
+            else
+            {
+                // Default default
+                IsDefault = CreateDefaultValueCheck<T>(x => EqualityComparer<T>.Default.Equals(x, default(T)));
+            }
+        }
+
+        private static Func<T, bool> CreateDefaultValueCheck<TTmp>(Func<TTmp, bool> check)
+        {
+            return (Func<T, bool>)(object)check;
+        }
+
+        private readonly Func<CodedInputStream, T> reader;
+        private readonly Action<CodedOutputStream, T> writer;
+        private readonly Func<T, int> sizeComputer;
+        private readonly uint tag;
+        private readonly int tagSize;
+
+        internal FieldCodec(
+            Func<CodedInputStream, T> reader,
+            Action<CodedOutputStream, T> writer,
+            Func<T, int> sizeComputer,
+            uint tag)
+        {
+            this.reader = reader;
+            this.writer = writer;
+            this.sizeComputer = sizeComputer;
+            this.tag = tag;
+            tagSize = CodedOutputStream.ComputeRawVarint32Size(tag);
+        }
+
+        public uint Tag { get { return tag; } }
+
+        public T DefaultValue { get { return Default; } }
+
+        public void Write(CodedOutputStream output, T value)
+        {
+            if (!IsDefault(value))
+            {
+                output.WriteTag(tag);
+                writer(output, value);
+            }
+        }
+
+        public T Read(CodedInputStream input)
+        {
+            return reader(input);
+        }
+
+        public int CalculateSize(T value)
+        {
+            return IsDefault(value) ? 0 : sizeComputer(value) + CodedOutputStream.ComputeRawVarint32Size(tag);
+        }        
+    }
+}

+ 2 - 0
csharp/src/ProtocolBuffers/ProtocolBuffers.csproj

@@ -60,6 +60,7 @@
     <Compile Include="CodedOutputStream.cs" />
     <Compile Include="Collections\Dictionaries.cs" />
     <Compile Include="Collections\Lists.cs" />
+    <Compile Include="Collections\MapField.cs" />
     <Compile Include="Collections\ReadOnlyDictionary.cs" />
     <Compile Include="Collections\RepeatedField.cs" />
     <Compile Include="Collections\RepeatedFieldExtensions.cs" />
@@ -84,6 +85,7 @@
     <Compile Include="Descriptors\MethodDescriptor.cs" />
     <Compile Include="Descriptors\PackageDescriptor.cs" />
     <Compile Include="Descriptors\ServiceDescriptor.cs" />
+    <Compile Include="FieldCodec.cs" />
     <Compile Include="FrameworkPortability.cs" />
     <Compile Include="Freezable.cs" />
     <Compile Include="MessageExtensions.cs" />

+ 2 - 0
src/Makefile.am

@@ -425,6 +425,8 @@ libprotoc_la_SOURCES =                                         \
   google/protobuf/compiler/csharp/csharp_generator.cc          \
   google/protobuf/compiler/csharp/csharp_helpers.cc            \
   google/protobuf/compiler/csharp/csharp_helpers.h             \
+  google/protobuf/compiler/csharp/csharp_map_field.cc          \
+  google/protobuf/compiler/csharp/csharp_map_field.h           \
   google/protobuf/compiler/csharp/csharp_message.cc            \
   google/protobuf/compiler/csharp/csharp_message.h             \
   google/protobuf/compiler/csharp/csharp_message_field.cc      \

+ 6 - 0
src/google/protobuf/compiler/csharp/csharp_enum_field.cc

@@ -74,6 +74,12 @@ void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
     "}\n");
 }
 
+void EnumFieldGenerator::GenerateCodecCode(io::Printer* printer) {
+    printer->Print(
+        variables_,
+        "pb::FieldCodec.ForEnum($tag$, x => (int) x, x => ($type_name$) x)");
+}
+
 EnumOneofFieldGenerator::EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
 						 int fieldOrdinal)
   : PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal) {

+ 1 - 0
src/google/protobuf/compiler/csharp/csharp_enum_field.h

@@ -46,6 +46,7 @@ class EnumFieldGenerator : public PrimitiveFieldGenerator {
   EnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
   ~EnumFieldGenerator();
 
+  virtual void GenerateCodecCode(io::Printer* printer);
   virtual void GenerateParsingCode(io::Printer* printer);
   virtual void GenerateSerializationCode(io::Printer* printer);
   virtual void GenerateSerializedSizeCode(io::Printer* printer);

+ 13 - 3
src/google/protobuf/compiler/csharp/csharp_field_base.cc

@@ -65,6 +65,7 @@ void FieldGeneratorBase::SetCommonFieldVariables(
     tag_bytes += ", " + SimpleItoa(tag_array[i]);
   }
 
+  (*variables)["tag"] = SimpleItoa(tag);
   (*variables)["tag_size"] = SimpleItoa(tag_size);
   (*variables)["tag_bytes"] = tag_bytes;
 
@@ -112,6 +113,11 @@ void FieldGeneratorBase::GenerateFreezingCode(io::Printer* printer) {
   // special handling for freezing, so default to not generating any code.
 }
 
+void FieldGeneratorBase::GenerateCodecCode(io::Printer* printer) {
+    // No-op: expect this to be overridden by appropriate types.
+    // Could fail if we get called here though...
+}
+
 void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) {
   if (descriptor_->options().deprecated())
   {
@@ -151,12 +157,16 @@ std::string FieldGeneratorBase::name() {
 }
 
 std::string FieldGeneratorBase::type_name() {
-  switch (descriptor_->type()) {
+  return type_name(descriptor_);
+}
+
+std::string FieldGeneratorBase::type_name(const FieldDescriptor* descriptor) {
+  switch (descriptor->type()) {
     case FieldDescriptor::TYPE_ENUM:
-      return GetClassName(descriptor_->enum_type());
+      return GetClassName(descriptor->enum_type());
     case FieldDescriptor::TYPE_MESSAGE:
     case FieldDescriptor::TYPE_GROUP:
-      return GetClassName(descriptor_->message_type());
+      return GetClassName(descriptor->message_type());
     case FieldDescriptor::TYPE_DOUBLE:
       return "double";
     case FieldDescriptor::TYPE_FLOAT:

+ 2 - 0
src/google/protobuf/compiler/csharp/csharp_field_base.h

@@ -49,6 +49,7 @@ class FieldGeneratorBase : public SourceGeneratorBase {
 
   virtual void GenerateCloningCode(io::Printer* printer) = 0;
   virtual void GenerateFreezingCode(io::Printer* printer);
+  virtual void GenerateCodecCode(io::Printer* printer);
   virtual void GenerateMembers(io::Printer* printer) = 0;
   virtual void GenerateMergingCode(io::Printer* printer) = 0;
   virtual void GenerateParsingCode(io::Printer* printer) = 0;
@@ -76,6 +77,7 @@ class FieldGeneratorBase : public SourceGeneratorBase {
   std::string property_name();
   std::string name();
   std::string type_name();
+  std::string type_name(const FieldDescriptor* descriptor);
   bool has_default_value();
   bool is_nullable_type();
   std::string default_value();

+ 6 - 1
src/google/protobuf/compiler/csharp/csharp_helpers.cc

@@ -46,6 +46,7 @@
 
 #include <google/protobuf/compiler/csharp/csharp_field_base.h>
 #include <google/protobuf/compiler/csharp/csharp_enum_field.h>
+#include <google/protobuf/compiler/csharp/csharp_map_field.h>
 #include <google/protobuf/compiler/csharp/csharp_message_field.h>
 #include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
 #include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h>
@@ -355,7 +356,11 @@ FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
     case FieldDescriptor::TYPE_GROUP:
     case FieldDescriptor::TYPE_MESSAGE:
       if (descriptor->is_repeated()) {
-        return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal);
+        if (descriptor->is_map()) {
+          return new MapFieldGenerator(descriptor, fieldOrdinal);
+        } else {
+          return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal);
+        }
       } else {
 	if (descriptor->containing_oneof()) {
 	  return new MessageOneofFieldGenerator(descriptor, fieldOrdinal);

+ 141 - 0
src/google/protobuf/compiler/csharp/csharp_map_field.cc

@@ -0,0 +1,141 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <sstream>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/strutil.h>
+
+#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include <google/protobuf/compiler/csharp/csharp_map_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
+                                             int fieldOrdinal)
+    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+}
+
+MapFieldGenerator::~MapFieldGenerator() {
+}
+
+void MapFieldGenerator::GenerateMembers(io::Printer* printer) {   
+  const FieldDescriptor* key_descriptor =
+      descriptor_->message_type()->FindFieldByName("key");
+  const FieldDescriptor* value_descriptor =
+      descriptor_->message_type()->FindFieldByName("value");
+  variables_["key_type_name"] = type_name(key_descriptor);
+  variables_["value_type_name"] = type_name(value_descriptor);
+  scoped_ptr<FieldGeneratorBase> key_generator(CreateFieldGenerator(key_descriptor, 1));  
+  scoped_ptr<FieldGeneratorBase> value_generator(CreateFieldGenerator(value_descriptor, 2));
+
+  printer->Print(
+    variables_,
+    "private static readonly pbc::MapField<$key_type_name$, $value_type_name$>.Codec _map_$name$_codec\n"
+    "    = new pbc::MapField<$key_type_name$, $value_type_name$>.Codec(");
+  key_generator->GenerateCodecCode(printer);
+  printer->Print(", ");
+  value_generator->GenerateCodecCode(printer);
+  printer->Print(
+    variables_,
+    ", $tag$);\n"
+    "private readonly pbc::MapField<$key_type_name$, $value_type_name$> $name$_ = new pbc::MapField<$key_type_name$, $value_type_name$>();\n");
+  AddDeprecatedFlag(printer);
+  printer->Print(
+    variables_,
+    "public pbc::MapField<$key_type_name$, $value_type_name$> $property_name$ {\n"
+    "  get { return $name$_; }\n"
+    "}\n");
+}
+
+void MapFieldGenerator::GenerateMergingCode(io::Printer* printer) {
+  printer->Print(
+      variables_,
+      "$name$_.Add(other.$name$_);\n");
+}
+
+void MapFieldGenerator::GenerateParsingCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "$name$_.AddEntriesFrom(input, _map_$name$_codec);\n");
+}
+
+void MapFieldGenerator::GenerateSerializationCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "$name$_.WriteTo(output, _map_$name$_codec);\n");
+}
+
+void MapFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "size += $name$_.CalculateSize(_map_$name$_codec);\n");
+}
+
+void MapFieldGenerator::WriteHash(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "hash ^= $property_name$.GetHashCode();\n");
+}
+void MapFieldGenerator::WriteEquals(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "if (!$property_name$.Equals(other.$property_name$)) return false;\n");
+}
+void MapFieldGenerator::WriteToString(io::Printer* printer) {
+    /*
+  variables_["field_name"] = GetFieldName(descriptor_);
+  printer->Print(
+    variables_,
+    "PrintField(\"$field_name$\", has$property_name$, $name$_, writer);\n");*/
+}
+
+void MapFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+  printer->Print(variables_,
+    "$name$_ = other.$name$_.Clone();\n");
+}
+
+void MapFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
+  printer->Print(variables_,
+    "$name$_.Freeze();\n");
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google

+ 71 - 0
src/google/protobuf/compiler/csharp/csharp_map_field.h

@@ -0,0 +1,71 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__
+
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+class MapFieldGenerator : public FieldGeneratorBase {
+ public:
+  MapFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  ~MapFieldGenerator();
+
+  virtual void GenerateCloningCode(io::Printer* printer);
+  virtual void GenerateFreezingCode(io::Printer* printer);
+  virtual void GenerateMembers(io::Printer* printer);
+  virtual void GenerateMergingCode(io::Printer* printer);
+  virtual void GenerateParsingCode(io::Printer* printer);
+  virtual void GenerateSerializationCode(io::Printer* printer);
+  virtual void GenerateSerializedSizeCode(io::Printer* printer);
+
+  virtual void WriteHash(io::Printer* printer);
+  virtual void WriteEquals(io::Printer* printer);
+  virtual void WriteToString(io::Printer* printer);
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
+};
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__
+

+ 3 - 6
src/google/protobuf/compiler/csharp/csharp_message.cc

@@ -268,8 +268,6 @@ void MessageGenerator::Generate(io::Printer* printer) {
       "}\n\n");
   }
 
-  // TODO(jonskeet): Map properties
-
   // Standard methods
   GenerateFrameworkMethods(printer);
   GenerateMessageSerializationMethods(printer);
@@ -299,7 +297,6 @@ void MessageGenerator::Generate(io::Printer* printer) {
   printer->Outdent();
   printer->Print("}\n");
   printer->Print("\n");
-
 }
 
 void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
@@ -408,9 +405,10 @@ void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
         "}\n\n");
 
     // GetHashCode
+    // Start with a non-zero value to easily distinguish between null and "empty" messages.
     printer->Print(
         "public override int GetHashCode() {\n"
-        "  int hash = 0;\n");
+        "  int hash = 1;\n");
     printer->Indent();
     for (int i = 0; i < descriptor_->field_count(); i++) {
         scoped_ptr<FieldGeneratorBase> generator(
@@ -451,7 +449,7 @@ void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer)
   }
   printer->Print("return size;\n");
   printer->Outdent();
-  printer->Print("}\n");
+  printer->Print("}\n\n");
 }
 
 void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
@@ -469,7 +467,6 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
     "if (other == null) {\n"
     "  return;\n"
     "}\n");
-  // TODO(jonskeet): Maps?
   // Merge non-oneof fields
   for (int i = 0; i < descriptor_->field_count(); i++) {
     if (!descriptor_->field(i)->containing_oneof()) {      

+ 6 - 0
src/google/protobuf/compiler/csharp/csharp_message_field.cc

@@ -138,6 +138,12 @@ void MessageFieldGenerator::GenerateFreezingCode(io::Printer* printer) {
     "if ($has_property_check$) $property_name$.Freeze();\n");
 }
 
+void MessageFieldGenerator::GenerateCodecCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "pb::FieldCodec.ForMessage($tag$, $type_name$.Parser)");
+}
+
 MessageOneofFieldGenerator::MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
 						       int fieldOrdinal)
     : MessageFieldGenerator(descriptor, fieldOrdinal) {

+ 1 - 0
src/google/protobuf/compiler/csharp/csharp_message_field.h

@@ -46,6 +46,7 @@ class MessageFieldGenerator : public FieldGeneratorBase {
   MessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
   ~MessageFieldGenerator();
 
+  virtual void GenerateCodecCode(io::Printer* printer);
   virtual void GenerateCloningCode(io::Printer* printer);
   virtual void GenerateFreezingCode(io::Printer* printer);
   virtual void GenerateMembers(io::Printer* printer);

+ 7 - 1
src/google/protobuf/compiler/csharp/csharp_primitive_field.cc

@@ -129,7 +129,7 @@ void PrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) {
       "size += $tag_size$ + $fixed_size$;\n",
       "fixed_size", SimpleItoa(fixedSize),
       "tag_size", variables_["tag_size"]);
-  }    
+  }
   printer->Outdent();
   printer->Print("}\n");
 }
@@ -155,6 +155,12 @@ void PrimitiveFieldGenerator::GenerateCloningCode(io::Printer* printer) {
     "$name$_ = other.$name$_;\n");
 }
 
+void PrimitiveFieldGenerator::GenerateCodecCode(io::Printer* printer) {
+  printer->Print(
+    variables_,
+    "pb::FieldCodec.For$capitalized_type_name$($tag$)");
+}
+
 PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
     const FieldDescriptor* descriptor, int fieldOrdinal)
     : PrimitiveFieldGenerator(descriptor, fieldOrdinal) {

+ 1 - 0
src/google/protobuf/compiler/csharp/csharp_primitive_field.h

@@ -46,6 +46,7 @@ class PrimitiveFieldGenerator : public FieldGeneratorBase {
   PrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
   ~PrimitiveFieldGenerator();
 
+  virtual void GenerateCodecCode(io::Printer* printer);
   virtual void GenerateCloningCode(io::Printer* printer);
   virtual void GenerateMembers(io::Printer* printer);
   virtual void GenerateMergingCode(io::Printer* printer);

+ 120 - 0
src/google/protobuf/map_unittest_proto3.proto

@@ -0,0 +1,120 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This file is mostly equivalent to map_unittest.proto, but imports
+// unittest_proto3.proto instead of unittest.proto, so that it only
+// uses proto3 messages. This makes it suitable for testing
+// implementations which only support proto3.
+// The TestRequiredMessageMap message has been removed as there are no
+// required fields in proto3.
+syntax = "proto3";
+
+option cc_enable_arenas = true;
+option csharp_namespace = "Google.Protobuf.TestProtos";
+
+import "google/protobuf/unittest_proto3.proto";
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+// In map_test_util.h we do "using namespace unittest = protobuf_unittest".
+package protobuf_unittest;
+
+// Tests maps.
+message TestMap {
+  map<int32   , int32   > map_int32_int32       = 1;
+  map<int64   , int64   > map_int64_int64       = 2;
+  map<uint32  , uint32  > map_uint32_uint32     = 3;
+  map<uint64  , uint64  > map_uint64_uint64     = 4;
+  map<sint32  , sint32  > map_sint32_sint32     = 5;
+  map<sint64  , sint64  > map_sint64_sint64     = 6;
+  map<fixed32 , fixed32 > map_fixed32_fixed32   = 7;
+  map<fixed64 , fixed64 > map_fixed64_fixed64   = 8;
+  map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
+  map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
+  map<int32   , float   > map_int32_float       = 11;
+  map<int32   , double  > map_int32_double      = 12;
+  map<bool    , bool    > map_bool_bool         = 13;
+  map<string  , string  > map_string_string     = 14;
+  map<int32   , bytes   > map_int32_bytes       = 15;
+  map<int32   , MapEnum > map_int32_enum        = 16;
+  map<int32   , ForeignMessage> map_int32_foreign_message = 17;
+}
+
+message TestMapSubmessage {
+  TestMap test_map = 1;
+}
+
+message TestMessageMap {
+  map<int32, TestAllTypes> map_int32_message = 1;
+}
+
+// Two map fields share the same entry default instance.
+message TestSameTypeMap {
+  map<int32, int32> map1 = 1;
+  map<int32, int32> map2 = 2;
+}
+
+enum MapEnum {
+  MAP_ENUM_FOO = 0;
+  MAP_ENUM_BAR = 1;
+  MAP_ENUM_BAZ = 2;
+}
+
+message TestArenaMap {
+  map<int32   , int32   > map_int32_int32       = 1;
+  map<int64   , int64   > map_int64_int64       = 2;
+  map<uint32  , uint32  > map_uint32_uint32     = 3;
+  map<uint64  , uint64  > map_uint64_uint64     = 4;
+  map<sint32  , sint32  > map_sint32_sint32     = 5;
+  map<sint64  , sint64  > map_sint64_sint64     = 6;
+  map<fixed32 , fixed32 > map_fixed32_fixed32   = 7;
+  map<fixed64 , fixed64 > map_fixed64_fixed64   = 8;
+  map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
+  map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
+  map<int32   , float   > map_int32_float       = 11;
+  map<int32   , double  > map_int32_double      = 12;
+  map<bool    , bool    > map_bool_bool         = 13;
+  map<int32   , MapEnum > map_int32_enum        = 14;
+  map<int32   , ForeignMessage> map_int32_foreign_message = 15;
+}
+
+// Previously, message containing enum called Type cannot be used as value of
+// map field.
+message MessageContainingEnumCalledType {
+  enum Type {
+    TYPE_FOO = 0;
+  }
+  map<int32, MessageContainingEnumCalledType> type = 1;
+}
+
+// Previously, message cannot contain map field called "entry".
+message MessageContainingMapCalledEntry {
+  map<int32, int32> entry = 1;
+}