Prechádzať zdrojové kódy

Merge remote-tracking branch 'upstream/master' into py2_py3_straddle

Conflicts:
	python/google/protobuf/descriptor_pool.py
	python/google/protobuf/internal/api_implementation_default_test.py
	python/google/protobuf/internal/cpp_message.py
	python/google/protobuf/internal/descriptor_database_test.py
	python/google/protobuf/internal/descriptor_pool_test.py
	python/google/protobuf/internal/descriptor_python_test.py
	python/google/protobuf/internal/descriptor_test.py
	python/google/protobuf/internal/generator_test.py
	python/google/protobuf/internal/message_factory_python_test.py
	python/google/protobuf/internal/message_factory_test.py
	python/google/protobuf/internal/message_test.py
	python/google/protobuf/internal/proto_builder_test.py
	python/google/protobuf/internal/python_message.py
	python/google/protobuf/internal/reflection_test.py
	python/google/protobuf/internal/service_reflection_test.py
	python/google/protobuf/internal/symbol_database_test.py
	python/google/protobuf/internal/text_encoding_test.py
	python/google/protobuf/internal/text_format_test.py
	python/google/protobuf/internal/unknown_fields_test.py
	python/google/protobuf/internal/wire_format_test.py
	python/google/protobuf/pyext/descriptor_cpp2_test.py
	python/google/protobuf/pyext/message_factory_cpp2_test.py
	python/google/protobuf/pyext/reflection_cpp2_generated_test.py
	python/setup.py
	ruby/lib/google/protobuf/message_exts.rb
Dan O'Reilly 10 rokov pred
rodič
commit
e47cdd5a55
100 zmenil súbory, kde vykonal 27174 pridanie a 577 odobranie
  1. 44 2
      .gitignore
  2. 53 1
      .travis.yml
  3. 0 486
      Android.mk
  4. 422 0
      BUILD
  5. 182 0
      CHANGES.txt
  6. 0 2
      LICENSE
  7. 389 58
      Makefile.am
  8. 24 0
      Protobuf.podspec
  9. 20 4
      README.md
  10. 16 0
      WORKSPACE
  11. 29 0
      appveyor.bat
  12. 32 0
      appveyor.yml
  13. 7 16
      autogen.sh
  14. 2 0
      benchmarks/google_size.proto
  15. 2 0
      benchmarks/google_speed.proto
  16. 91 0
      cmake/CMakeLists.txt
  17. 139 0
      cmake/README.md
  18. 120 0
      cmake/extract_includes.bat.in
  19. 30 0
      cmake/libprotobuf-lite.cmake
  20. 60 0
      cmake/libprotobuf.cmake
  21. 95 0
      cmake/libprotoc.cmake
  22. 6 0
      cmake/protoc.cmake
  23. 182 0
      cmake/tests.cmake
  24. 14 8
      configure.ac
  25. 120 0
      conformance/ConformanceJava.java
  26. 78 0
      conformance/Makefile.am
  27. 45 0
      conformance/README.md
  28. 212 0
      conformance/conformance.proto
  29. 194 0
      conformance/conformance_cpp.cc
  30. 114 0
      conformance/conformance_ruby.rb
  31. 534 0
      conformance/conformance_test.cc
  32. 158 0
      conformance/conformance_test.h
  33. 252 0
      conformance/conformance_test_runner.cc
  34. 21 0
      conformance/failure_list_cpp.txt
  35. 0 0
      conformance/failure_list_csharp.txt
  36. 17 0
      conformance/failure_list_ruby.txt
  37. 35 0
      csharp/.gitignore
  38. 148 0
      csharp/CHANGES.txt
  39. 49 0
      csharp/README.md
  40. 13 0
      csharp/build_packages.bat
  41. 17 0
      csharp/buildall.sh
  42. 73 0
      csharp/generate_protos.sh
  43. BIN
      csharp/keys/Google.Protobuf.public.snk
  44. 5 0
      csharp/keys/README.md
  45. 119 0
      csharp/protos/unittest_issues.proto
  46. 132 0
      csharp/src/AddressBook/AddPerson.cs
  47. 75 0
      csharp/src/AddressBook/AddressBook.csproj
  48. 454 0
      csharp/src/AddressBook/Addressbook.cs
  49. 99 0
      csharp/src/AddressBook/ListPeople.cs
  50. 95 0
      csharp/src/AddressBook/Program.cs
  51. 18 0
      csharp/src/AddressBook/Properties/AssemblyInfo.cs
  52. 70 0
      csharp/src/AddressBook/SampleUsage.cs
  53. 3 0
      csharp/src/AddressBook/app.config
  54. 6 0
      csharp/src/Google.Protobuf.Conformance/App.config
  55. 2380 0
      csharp/src/Google.Protobuf.Conformance/Conformance.cs
  56. 61 0
      csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj
  57. 126 0
      csharp/src/Google.Protobuf.Conformance/Program.cs
  58. 48 0
      csharp/src/Google.Protobuf.Conformance/Properties/AssemblyInfo.cs
  59. 68 0
      csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj
  60. 72 0
      csharp/src/Google.Protobuf.JsonDump/Program.cs
  61. 19 0
      csharp/src/Google.Protobuf.JsonDump/Properties/AssemblyInfo.cs
  62. 3 0
      csharp/src/Google.Protobuf.JsonDump/app.config
  63. 171 0
      csharp/src/Google.Protobuf.Test/ByteStringTest.cs
  64. 53 0
      csharp/src/Google.Protobuf.Test/CodedInputStreamExtensions.cs
  65. 530 0
      csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
  66. 391 0
      csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
  67. 570 0
      csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs
  68. 603 0
      csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs
  69. 98 0
      csharp/src/Google.Protobuf.Test/Compatibility/PropertyInfoExtensionsTest.cs
  70. 133 0
      csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs
  71. 55 0
      csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs
  72. 64 0
      csharp/src/Google.Protobuf.Test/EqualityTester.cs
  73. 195 0
      csharp/src/Google.Protobuf.Test/FieldCodecTest.cs
  74. 655 0
      csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
  75. 137 0
      csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
  76. 63 0
      csharp/src/Google.Protobuf.Test/IssuesTest.cs
  77. 420 0
      csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs
  78. 6 0
      csharp/src/Google.Protobuf.Test/Properties/AppManifest.xml
  79. 20 0
      csharp/src/Google.Protobuf.Test/Properties/AssemblyInfo.cs
  80. 255 0
      csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs
  81. 218 0
      csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs
  82. 42 0
      csharp/src/Google.Protobuf.Test/SampleEnum.cs
  83. 99 0
      csharp/src/Google.Protobuf.Test/SampleMessages.cs
  84. 62 0
      csharp/src/Google.Protobuf.Test/TestCornerCases.cs
  85. 1417 0
      csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs
  86. 158 0
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs
  87. 144 0
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs
  88. 1355 0
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs
  89. 5830 0
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs
  90. 2283 0
      csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs
  91. 104 0
      csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs
  92. 84 0
      csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs
  93. 349 0
      csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs
  94. 5 0
      csharp/src/Google.Protobuf.Test/packages.config
  95. 56 0
      csharp/src/Google.Protobuf.sln
  96. 79 0
      csharp/src/Google.Protobuf/ByteArray.cs
  97. 345 0
      csharp/src/Google.Protobuf/ByteString.cs
  98. 1221 0
      csharp/src/Google.Protobuf/CodedInputStream.cs
  99. 304 0
      csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs
  100. 708 0
      csharp/src/Google.Protobuf/CodedOutputStream.cs

+ 44 - 2
.gitignore

@@ -16,14 +16,15 @@ m4/ltoptions.m4
 m4/ltsugar.m4
 m4/ltsugar.m4
 m4/ltversion.m4
 m4/ltversion.m4
 m4/lt~obsolete.m4
 m4/lt~obsolete.m4
+autom4te.cache
 
 
 # downloaded files
 # downloaded files
-gtest
+gmock
 
 
 # in-tree configure-generated files
 # in-tree configure-generated files
 Makefile
 Makefile
 src/Makefile
 src/Makefile
-config.h
+/config.h
 config.log
 config.log
 config.status
 config.status
 
 
@@ -38,17 +39,22 @@ stamp-h1
 *.lo
 *.lo
 *.la
 *.la
 src/.libs
 src/.libs
+*.so
 
 
 .dirstamp
 .dirstamp
 
 
+any_test.pb.*
 map*unittest.pb.*
 map*unittest.pb.*
 unittest*.pb.*
 unittest*.pb.*
 cpp_test*.pb.*
 cpp_test*.pb.*
+src/google/protobuf/util/**/*.pb.cc
+src/google/protobuf/util/**/*.pb.h
 
 
 *.pyc
 *.pyc
 *.so
 *.so
 *.egg-info
 *.egg-info
 *_pb2.py
 *_pb2.py
+python/*.egg
 python/.eggs/
 python/.eggs/
 python/.tox
 python/.tox
 python/build/
 python/build/
@@ -63,3 +69,39 @@ src/test_plugin
 src/testzip.*
 src/testzip.*
 src/zcg*zip
 src/zcg*zip
 ar-lib
 ar-lib
+
+test-driver
+compile
+
+src/**/*.log
+src/**/*.trs
+
+# JavaBuild output.
+java/target
+javanano/target
+
+# Windows native output.
+cmake/build
+
+# NuGet packages: we want the repository configuration, but not the
+# packages themselves.
+/csharp/src/packages/*/
+
+# Directories created by opening the Objective C Xcode projects.
+objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/xcuserdata/
+objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/xcshareddata/ProtocolBuffers_OSX.xccheckout
+objectivec/ProtocolBuffers_OSX.xcodeproj/xcuserdata/
+objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/xcuserdata/
+objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/xcshareddata/ProtocolBuffers_iOS.xccheckout
+objectivec/ProtocolBuffers_iOS.xcodeproj/xcuserdata/
+# OS X's Finder creates these for state about opened windows/etc.
+**/.DS_Store
+
+# Comformance test output
+conformance/.libs/
+conformance/com/
+conformance/conformance-cpp
+conformance/conformance-test-runner
+conformance/conformance.pb.cc
+conformance/conformance.pb.h
+conformance/protoc_middleman

+ 53 - 1
.travis.yml

@@ -1,4 +1,56 @@
+sudo: required
+# Note: travis currently does not support listing more than one language so
+# this cheats and claims to only be cpp.  If they add multiple language
+# support, this should probably get updated to install steps and/or
+# rvm/gemfile/jdk/etc. entries rather than manually doing the work.
 language: cpp
 language: cpp
-script: ./autogen.sh && ./configure && make distcheck
+os:
+  - linux
+  - osx
+script:
+  - ./travis.sh $CONFIG
+env:
+  - CONFIG=cpp
+  - CONFIG=cpp_distcheck
+  - CONFIG=csharp
+  - CONFIG=java_jdk6
+  - CONFIG=java_jdk7
+  - CONFIG=java_oracle7
+  - CONFIG=javanano_jdk6
+  - CONFIG=javanano_jdk7
+  - CONFIG=javanano_oracle7
+  - CONFIG=python
+  - CONFIG=python_cpp
+  - CONFIG=ruby19
+  - CONFIG=ruby20
+  - CONFIG=ruby21
+  - CONFIG=ruby22
+  - CONFIG=jruby
+matrix:
+  exclude:
+    # It's nontrivial to programmatically install a new JDK from the command
+    # line on OS X, so we rely on testing on Linux for Java code.
+    - os: osx
+      env: CONFIG=java_jdk6
+    - os: osx
+      env: CONFIG=java_jdk7
+    - os: osx
+      env: CONFIG=java_oracle7
+    - os: osx
+      env: CONFIG=javanano_jdk6
+    - os: osx
+      env: CONFIG=javanano_jdk7
+    - os: osx
+      env: CONFIG=javanano_oracle7
+    # Requires installing mono, currently travis.sh is doing that with apt-get
+    # which doesn't work on OS X.
+    - os: osx
+      env: CONFIG=csharp
+  allow_failures:
+    # These currently do not work on OS X but are being worked on by @haberman.
+    - os: osx
+      env: CONFIG=ruby22
+    - os: osx
+      env: CONFIG=jruby
 notifications:
 notifications:
   email: false
   email: false

+ 0 - 486
Android.mk

@@ -1,486 +0,0 @@
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-#
-
-LOCAL_PATH := $(call my-dir)
-
-IGNORED_WARNINGS := -Wno-sign-compare -Wno-unused-parameter -Wno-sign-promo
-
-CC_LITE_SRC_FILES := \
-    src/google/protobuf/stubs/common.cc                              \
-    src/google/protobuf/stubs/once.cc                                \
-    src/google/protobuf/stubs/hash.cc                                \
-    src/google/protobuf/stubs/hash.h                                 \
-    src/google/protobuf/stubs/map-util.h                             \
-    src/google/protobuf/stubs/stl_util-inl.h                         \
-    src/google/protobuf/extension_set.cc                             \
-    src/google/protobuf/generated_message_util.cc                    \
-    src/google/protobuf/message_lite.cc                              \
-    src/google/protobuf/repeated_field.cc                            \
-    src/google/protobuf/wire_format_lite.cc                          \
-    src/google/protobuf/io/coded_stream.cc                           \
-    src/google/protobuf/io/coded_stream_inl.h                        \
-    src/google/protobuf/io/zero_copy_stream.cc                       \
-    src/google/protobuf/io/zero_copy_stream_impl_lite.cc
-
-JAVA_LITE_SRC_FILES := \
-    java/src/main/java/com/google/protobuf/UninitializedMessageException.java \
-    java/src/main/java/com/google/protobuf/MessageLite.java \
-    java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \
-    java/src/main/java/com/google/protobuf/CodedOutputStream.java \
-    java/src/main/java/com/google/protobuf/ByteString.java \
-    java/src/main/java/com/google/protobuf/CodedInputStream.java \
-    java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java \
-    java/src/main/java/com/google/protobuf/AbstractMessageLite.java \
-    java/src/main/java/com/google/protobuf/FieldSet.java \
-    java/src/main/java/com/google/protobuf/Internal.java \
-    java/src/main/java/com/google/protobuf/WireFormat.java \
-    java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
-
-COMPILER_SRC_FILES :=  \
-    src/google/protobuf/descriptor.cc \
-    src/google/protobuf/descriptor.pb.cc \
-    src/google/protobuf/descriptor_database.cc \
-    src/google/protobuf/dynamic_message.cc \
-    src/google/protobuf/extension_set.cc \
-    src/google/protobuf/extension_set_heavy.cc \
-    src/google/protobuf/generated_message_reflection.cc \
-    src/google/protobuf/generated_message_util.cc \
-    src/google/protobuf/message.cc \
-    src/google/protobuf/message_lite.cc \
-    src/google/protobuf/reflection_ops.cc \
-    src/google/protobuf/repeated_field.cc \
-    src/google/protobuf/service.cc \
-    src/google/protobuf/text_format.cc \
-    src/google/protobuf/unknown_field_set.cc \
-    src/google/protobuf/wire_format.cc \
-    src/google/protobuf/wire_format_lite.cc \
-    src/google/protobuf/compiler/code_generator.cc \
-    src/google/protobuf/compiler/command_line_interface.cc \
-    src/google/protobuf/compiler/importer.cc \
-    src/google/protobuf/compiler/main.cc \
-    src/google/protobuf/compiler/parser.cc \
-    src/google/protobuf/compiler/plugin.cc \
-    src/google/protobuf/compiler/plugin.pb.cc \
-    src/google/protobuf/compiler/subprocess.cc \
-    src/google/protobuf/compiler/zip_writer.cc \
-    src/google/protobuf/compiler/cpp/cpp_enum.cc \
-    src/google/protobuf/compiler/cpp/cpp_enum_field.cc \
-    src/google/protobuf/compiler/cpp/cpp_extension.cc \
-    src/google/protobuf/compiler/cpp/cpp_field.cc \
-    src/google/protobuf/compiler/cpp/cpp_file.cc \
-    src/google/protobuf/compiler/cpp/cpp_generator.cc \
-    src/google/protobuf/compiler/cpp/cpp_helpers.cc \
-    src/google/protobuf/compiler/cpp/cpp_message.cc \
-    src/google/protobuf/compiler/cpp/cpp_message_field.cc \
-    src/google/protobuf/compiler/cpp/cpp_primitive_field.cc \
-    src/google/protobuf/compiler/cpp/cpp_service.cc \
-    src/google/protobuf/compiler/cpp/cpp_string_field.cc \
-    src/google/protobuf/compiler/java/java_enum.cc \
-    src/google/protobuf/compiler/java/java_enum_field.cc \
-    src/google/protobuf/compiler/java/java_extension.cc \
-    src/google/protobuf/compiler/java/java_field.cc \
-    src/google/protobuf/compiler/java/java_file.cc \
-    src/google/protobuf/compiler/java/java_generator.cc \
-    src/google/protobuf/compiler/java/java_helpers.cc \
-    src/google/protobuf/compiler/java/java_message.cc \
-    src/google/protobuf/compiler/java/java_message_field.cc \
-    src/google/protobuf/compiler/java/java_primitive_field.cc \
-    src/google/protobuf/compiler/java/java_service.cc \
-    src/google/protobuf/compiler/javamicro/javamicro_enum.cc \
-    src/google/protobuf/compiler/javamicro/javamicro_enum_field.cc \
-    src/google/protobuf/compiler/javamicro/javamicro_field.cc \
-    src/google/protobuf/compiler/javamicro/javamicro_file.cc \
-    src/google/protobuf/compiler/javamicro/javamicro_generator.cc \
-    src/google/protobuf/compiler/javamicro/javamicro_helpers.cc \
-    src/google/protobuf/compiler/javamicro/javamicro_message.cc \
-    src/google/protobuf/compiler/javamicro/javamicro_message_field.cc \
-    src/google/protobuf/compiler/javamicro/javamicro_primitive_field.cc \
-    src/google/protobuf/compiler/javanano/javanano_enum.cc \
-    src/google/protobuf/compiler/javanano/javanano_enum_field.cc \
-    src/google/protobuf/compiler/javanano/javanano_extension.cc \
-    src/google/protobuf/compiler/javanano/javanano_field.cc \
-    src/google/protobuf/compiler/javanano/javanano_file.cc \
-    src/google/protobuf/compiler/javanano/javanano_generator.cc \
-    src/google/protobuf/compiler/javanano/javanano_helpers.cc \
-    src/google/protobuf/compiler/javanano/javanano_message.cc \
-    src/google/protobuf/compiler/javanano/javanano_message_field.cc \
-    src/google/protobuf/compiler/javanano/javanano_primitive_field.cc \
-    src/google/protobuf/compiler/python/python_generator.cc \
-    src/google/protobuf/io/coded_stream.cc \
-    src/google/protobuf/io/gzip_stream.cc \
-    src/google/protobuf/io/printer.cc \
-    src/google/protobuf/io/tokenizer.cc \
-    src/google/protobuf/io/zero_copy_stream.cc \
-    src/google/protobuf/io/zero_copy_stream_impl.cc \
-    src/google/protobuf/io/zero_copy_stream_impl_lite.cc \
-    src/google/protobuf/stubs/common.cc \
-    src/google/protobuf/stubs/hash.cc \
-    src/google/protobuf/stubs/once.cc \
-    src/google/protobuf/stubs/structurally_valid.cc \
-    src/google/protobuf/stubs/strutil.cc \
-    src/google/protobuf/stubs/substitute.cc
-
-# Java nano library (for device-side users)
-# =======================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libprotobuf-java-nano
-LOCAL_MODULE_TAGS := optional
-LOCAL_SDK_VERSION := 8
-
-LOCAL_SRC_FILES := $(call all-java-files-under, java/src/main/java/com/google/protobuf/nano)
-LOCAL_SRC_FILES += $(call all-java-files-under, java/src/device/main/java/com/google/protobuf/nano)
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-# Java nano library (for host-side users)
-# =======================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := host-libprotobuf-java-nano
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, java/src/main/java/com/google/protobuf/nano)
-
-include $(BUILD_HOST_JAVA_LIBRARY)
-
-# Java micro library (for device-side users)
-# =======================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libprotobuf-java-micro
-LOCAL_MODULE_TAGS := optional
-LOCAL_SDK_VERSION := 8
-
-LOCAL_SRC_FILES := $(call all-java-files-under, java/src/main/java/com/google/protobuf/micro)
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-# Java micro library (for host-side users)
-# =======================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := host-libprotobuf-java-micro
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, java/src/main/java/com/google/protobuf/micro)
-
-include $(BUILD_HOST_JAVA_LIBRARY)
-
-# Java lite library (for device-side users)
-# =======================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libprotobuf-java-lite
-LOCAL_MODULE_TAGS := optional
-LOCAL_SDK_VERSION := 8
-
-LOCAL_SRC_FILES := $(JAVA_LITE_SRC_FILES)
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-# Java lite library (for host-side users)
-# =======================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := host-libprotobuf-java-lite
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(JAVA_LITE_SRC_FILES)
-
-include $(BUILD_HOST_JAVA_LIBRARY)
-
-# C++ lite library
-# =======================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libprotobuf-cpp-lite
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CPP_EXTENSION := .cc
-
-LOCAL_SRC_FILES := $(CC_LITE_SRC_FILES)
-
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/android \
-    $(LOCAL_PATH)/src
-
-# Define the header files to be copied
-#LOCAL_COPY_HEADERS := \
-#    src/google/protobuf/stubs/once.h \
-#    src/google/protobuf/stubs/common.h \
-#    src/google/protobuf/io/coded_stream.h \
-#    src/google/protobuf/generated_message_util.h \
-#    src/google/protobuf/repeated_field.h \
-#    src/google/protobuf/extension_set.h \
-#    src/google/protobuf/wire_format_lite_inl.h
-#
-#LOCAL_COPY_HEADERS_TO := $(LOCAL_MODULE)
-
-LOCAL_CFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI $(IGNORED_WARNINGS)
-
-# These are the minimum versions and don't need to be update.
-ifeq ($(TARGET_ARCH),arm)
-LOCAL_SDK_VERSION := 8
-else
-# x86/mips support only available from API 9.
-LOCAL_SDK_VERSION := 9
-endif
-LOCAL_NDK_STL_VARIANT := stlport_static
-
-include $(BUILD_STATIC_LIBRARY)
-
-# C++ lite library (libc++ flavored for the platform)
-# =======================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libprotobuf-cpp-lite
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CPP_EXTENSION := .cc
-
-LOCAL_SRC_FILES := $(CC_LITE_SRC_FILES)
-
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/android \
-    $(LOCAL_PATH)/src
-
-LOCAL_CFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI $(IGNORED_WARNINGS)
-
-include $(BUILD_SHARED_LIBRARY)
-
-# C++ full library
-# =======================================================
-protobuf_cc_full_src_files := \
-    $(CC_LITE_SRC_FILES)                                             \
-    src/google/protobuf/stubs/strutil.cc                             \
-    src/google/protobuf/stubs/strutil.h                              \
-    src/google/protobuf/stubs/substitute.cc                          \
-    src/google/protobuf/stubs/substitute.h                           \
-    src/google/protobuf/stubs/structurally_valid.cc                  \
-    src/google/protobuf/descriptor.cc                                \
-    src/google/protobuf/descriptor.pb.cc                             \
-    src/google/protobuf/descriptor_database.cc                       \
-    src/google/protobuf/dynamic_message.cc                           \
-    src/google/protobuf/extension_set_heavy.cc                       \
-    src/google/protobuf/generated_message_reflection.cc              \
-    src/google/protobuf/message.cc                                   \
-    src/google/protobuf/reflection_ops.cc                            \
-    src/google/protobuf/service.cc                                   \
-    src/google/protobuf/text_format.cc                               \
-    src/google/protobuf/unknown_field_set.cc                         \
-    src/google/protobuf/wire_format.cc                               \
-    src/google/protobuf/io/gzip_stream.cc                            \
-    src/google/protobuf/io/printer.cc                                \
-    src/google/protobuf/io/tokenizer.cc                              \
-    src/google/protobuf/io/zero_copy_stream_impl.cc                  \
-    src/google/protobuf/compiler/importer.cc                         \
-    src/google/protobuf/compiler/parser.cc
-
-# C++ full library - stlport version
-# =======================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libprotobuf-cpp-full
-LOCAL_MODULE_TAGS := optional
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_SRC_FILES := $(protobuf_cc_full_src_files)
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/android \
-    external/zlib \
-    $(LOCAL_PATH)/src
-
-# Define the header files to be copied
-#LOCAL_COPY_HEADERS := \
-#    src/google/protobuf/stubs/once.h \
-#    src/google/protobuf/stubs/common.h \
-#    src/google/protobuf/io/coded_stream.h \
-#    src/google/protobuf/generated_message_util.h \
-#    src/google/protobuf/repeated_field.h \
-#    src/google/protobuf/extension_set.h \
-#    src/google/protobuf/wire_format_lite_inl.h
-#
-#LOCAL_COPY_HEADERS_TO := $(LOCAL_MODULE)
-
-LOCAL_CFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI $(IGNORED_WARNINGS)
-
-# These are the minimum versions and don't need to be update.
-ifeq ($(TARGET_ARCH),arm)
-LOCAL_SDK_VERSION := 8
-else
-# x86/mips support only available from API 9.
-LOCAL_SDK_VERSION := 9
-endif
-LOCAL_NDK_STL_VARIANT := stlport_static
-
-include $(BUILD_STATIC_LIBRARY)
-
-# C++ full library - Gnustl+rtti version
-# =======================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libprotobuf-cpp-full-gnustl-rtti
-LOCAL_MODULE_TAGS := optional
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_SRC_FILES := $(protobuf_cc_full_src_files)
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/android \
-    external/zlib \
-    $(LOCAL_PATH)/src
-
-LOCAL_CFLAGS := -frtti $(IGNORED_WARNINGS)
-LOCAL_SDK_VERSION := 14
-LOCAL_NDK_STL_VARIANT := gnustl_static
-
-include $(BUILD_STATIC_LIBRARY)
-
-# C++ full library - libc++ version for the platform
-# =======================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libprotobuf-cpp-full
-LOCAL_MODULE_TAGS := optional
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_SRC_FILES := $(protobuf_cc_full_src_files)
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/android \
-    external/zlib \
-    $(LOCAL_PATH)/src
-
-LOCAL_CFLAGS := -DGOOGLE_PROTOBUF_NO_RTTI $(IGNORED_WARNINGS)
-LOCAL_SHARED_LIBRARIES := libz
-
-include $(BUILD_SHARED_LIBRARY)
-
-# Clean temp vars
-protobuf_cc_full_src_files :=
-
-
-# Android Protocol buffer compiler, aprotoc (host executable)
-# used by the build systems as $(PROTOC) defined in
-# build/core/config.mk
-# =======================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := aprotoc
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_SRC_FILES := $(COMPILER_SRC_FILES)
-
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/android \
-    external/zlib \
-    $(LOCAL_PATH)/src
-
-LOCAL_STATIC_LIBRARIES += libz
-
-ifneq ($(HOST_OS),windows)
-LOCAL_LDLIBS := -lpthread
-endif
-
-LOCAL_CFLAGS := $(IGNORED_WARNINGS)
-
-include $(BUILD_HOST_EXECUTABLE)
-
-# To test java proto params build rules.
-# =======================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := aprotoc-test-nano-params
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := nano
-
-LOCAL_SRC_FILES := \
-        src/google/protobuf/unittest_import_nano.proto \
-        src/google/protobuf/unittest_simple_nano.proto \
-        src/google/protobuf/unittest_stringutf8_nano.proto \
-        src/google/protobuf/unittest_recursive_nano.proto
-
-
-LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/src
-
-LOCAL_PROTO_JAVA_OUTPUT_PARAMS := \
-        java_package = $(LOCAL_PATH)/src/google/protobuf/unittest_import_nano.proto|com.google.protobuf.nano, \
-        java_outer_classname = $(LOCAL_PATH)/src/google/protobuf/unittest_import_nano.proto|UnittestImportNano
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-# To test Android-specific nanoproto features.
-# =======================================================
-include $(CLEAR_VARS)
-
-# Parcelable messages
-LOCAL_MODULE := android-nano-test-parcelable
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := nano
-
-LOCAL_SRC_FILES := src/google/protobuf/unittest_simple_nano.proto
-
-LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/src
-
-LOCAL_PROTO_JAVA_OUTPUT_PARAMS := \
-        parcelable_messages = true
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-include $(CLEAR_VARS)
-
-# Parcelable and extendable messages
-LOCAL_MODULE := android-nano-test-parcelable-extendable
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := nano
-
-LOCAL_SRC_FILES := src/google/protobuf/unittest_extension_nano.proto
-
-LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/src
-
-LOCAL_PROTO_JAVA_OUTPUT_PARAMS := \
-        parcelable_messages = true, \
-        store_unknown_fields = true
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-include $(CLEAR_VARS)
-
-# Test APK
-LOCAL_PACKAGE_NAME := NanoAndroidTest
-
-LOCAL_SDK_VERSION := 8
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, java/src/device/test/java/com/google/protobuf/nano)
-
-LOCAL_MANIFEST_FILE := java/src/device/test/AndroidManifest.xml
-
-LOCAL_STATIC_JAVA_LIBRARIES := libprotobuf-java-nano \
-        android-nano-test-parcelable \
-        android-nano-test-parcelable-extendable
-
-LOCAL_DEX_PREOPT := false
-
-include $(BUILD_PACKAGE)
-
-# 2.3.0 prebuilts for backwards compatibility.
-include $(LOCAL_PATH)/prebuilts/Android.mk

+ 422 - 0
BUILD

@@ -0,0 +1,422 @@
+# Bazel (http://bazel.io/) BUILD file for Protobuf.
+
+licenses(["notice"])
+
+################################################################################
+# Protobuf Runtime Library
+################################################################################
+
+COPTS = [
+    "-DHAVE_PTHREAD",
+    "-Wall",
+    "-Wwrite-strings",
+    "-Woverloaded-virtual",
+    "-Wno-sign-compare",
+    "-Wno-error=unused-function",
+]
+
+# Bazel should provide portable link_opts for pthread.
+LINK_OPTS = ["-lpthread"]
+
+cc_library(
+    name = "protobuf_lite",
+    srcs = [
+        # AUTOGEN(protobuf_lite_srcs)
+        "src/google/protobuf/arena.cc",
+        "src/google/protobuf/arenastring.cc",
+        "src/google/protobuf/extension_set.cc",
+        "src/google/protobuf/generated_message_util.cc",
+        "src/google/protobuf/io/coded_stream.cc",
+        "src/google/protobuf/io/zero_copy_stream.cc",
+        "src/google/protobuf/io/zero_copy_stream_impl_lite.cc",
+        "src/google/protobuf/message_lite.cc",
+        "src/google/protobuf/repeated_field.cc",
+        "src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc",
+        "src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc",
+        "src/google/protobuf/stubs/bytestream.cc",
+        "src/google/protobuf/stubs/common.cc",
+        "src/google/protobuf/stubs/once.cc",
+        "src/google/protobuf/stubs/status.cc",
+        "src/google/protobuf/stubs/statusor.cc",
+        "src/google/protobuf/stubs/stringpiece.cc",
+        "src/google/protobuf/stubs/stringprintf.cc",
+        "src/google/protobuf/stubs/strutil.cc",
+        "src/google/protobuf/stubs/time.cc",
+        "src/google/protobuf/wire_format_lite.cc",
+    ],
+    copts = COPTS,
+    includes = ["src/"],
+    linkopts = LINK_OPTS,
+    visibility = ["//visibility:public"],
+)
+
+cc_library(
+    name = "protobuf",
+    srcs = [
+        # AUTOGEN(protobuf_srcs)
+        "src/google/protobuf/any.cc",
+        "src/google/protobuf/any.pb.cc",
+        "src/google/protobuf/api.pb.cc",
+        "src/google/protobuf/compiler/importer.cc",
+        "src/google/protobuf/compiler/parser.cc",
+        "src/google/protobuf/descriptor.cc",
+        "src/google/protobuf/descriptor.pb.cc",
+        "src/google/protobuf/descriptor_database.cc",
+        "src/google/protobuf/duration.pb.cc",
+        "src/google/protobuf/dynamic_message.cc",
+        "src/google/protobuf/empty.pb.cc",
+        "src/google/protobuf/extension_set_heavy.cc",
+        "src/google/protobuf/field_mask.pb.cc",
+        "src/google/protobuf/generated_message_reflection.cc",
+        "src/google/protobuf/io/gzip_stream.cc",
+        "src/google/protobuf/io/printer.cc",
+        "src/google/protobuf/io/strtod.cc",
+        "src/google/protobuf/io/tokenizer.cc",
+        "src/google/protobuf/io/zero_copy_stream_impl.cc",
+        "src/google/protobuf/map_field.cc",
+        "src/google/protobuf/message.cc",
+        "src/google/protobuf/reflection_ops.cc",
+        "src/google/protobuf/service.cc",
+        "src/google/protobuf/source_context.pb.cc",
+        "src/google/protobuf/struct.pb.cc",
+        "src/google/protobuf/stubs/mathlimits.cc",
+        "src/google/protobuf/stubs/structurally_valid.cc",
+        "src/google/protobuf/stubs/substitute.cc",
+        "src/google/protobuf/text_format.cc",
+        "src/google/protobuf/timestamp.pb.cc",
+        "src/google/protobuf/type.pb.cc",
+        "src/google/protobuf/unknown_field_set.cc",
+        "src/google/protobuf/util/field_comparator.cc",
+        "src/google/protobuf/util/internal/datapiece.cc",
+        "src/google/protobuf/util/internal/default_value_objectwriter.cc",
+        "src/google/protobuf/util/internal/error_listener.cc",
+        "src/google/protobuf/util/internal/field_mask_utility.cc",
+        "src/google/protobuf/util/internal/json_escaping.cc",
+        "src/google/protobuf/util/internal/json_objectwriter.cc",
+        "src/google/protobuf/util/internal/json_stream_parser.cc",
+        "src/google/protobuf/util/internal/object_writer.cc",
+        "src/google/protobuf/util/internal/protostream_objectsource.cc",
+        "src/google/protobuf/util/internal/protostream_objectwriter.cc",
+        "src/google/protobuf/util/internal/type_info.cc",
+        "src/google/protobuf/util/internal/type_info_test_helper.cc",
+        "src/google/protobuf/util/internal/utility.cc",
+        "src/google/protobuf/util/json_util.cc",
+        "src/google/protobuf/util/message_differencer.cc",
+        "src/google/protobuf/util/type_resolver_util.cc",
+        "src/google/protobuf/wire_format.cc",
+        "src/google/protobuf/wrappers.pb.cc",
+    ],
+    copts = COPTS,
+    includes = ["src/"],
+    linkopts = LINK_OPTS,
+    visibility = ["//visibility:public"],
+    deps = [":protobuf_lite"],
+)
+
+objc_library(
+    name = "protobuf_objc",
+    hdrs = ["objectivec/GPBProtocolBuffers.h"],
+    includes = ["objectivec"],
+    non_arc_srcs = ["objectivec/GPBProtocolBuffers.m"],
+    visibility = ["//visibility:public"],
+)
+
+WELL_KNOWN_PROTOS = [
+    # AUTOGEN(well_known_protos)
+    "google/protobuf/any.proto",
+    "google/protobuf/api.proto",
+    "google/protobuf/compiler/plugin.proto",
+    "google/protobuf/descriptor.proto",
+    "google/protobuf/duration.proto",
+    "google/protobuf/empty.proto",
+    "google/protobuf/field_mask.proto",
+    "google/protobuf/source_context.proto",
+    "google/protobuf/struct.proto",
+    "google/protobuf/timestamp.proto",
+    "google/protobuf/type.proto",
+    "google/protobuf/wrappers.proto",
+]
+
+################################################################################
+# Protocol Buffers Compiler
+################################################################################
+
+cc_library(
+    name = "protoc_lib",
+    srcs = [
+        # AUTOGEN(protoc_lib_srcs)
+        "src/google/protobuf/compiler/code_generator.cc",
+        "src/google/protobuf/compiler/command_line_interface.cc",
+        "src/google/protobuf/compiler/cpp/cpp_enum.cc",
+        "src/google/protobuf/compiler/cpp/cpp_enum_field.cc",
+        "src/google/protobuf/compiler/cpp/cpp_extension.cc",
+        "src/google/protobuf/compiler/cpp/cpp_field.cc",
+        "src/google/protobuf/compiler/cpp/cpp_file.cc",
+        "src/google/protobuf/compiler/cpp/cpp_generator.cc",
+        "src/google/protobuf/compiler/cpp/cpp_helpers.cc",
+        "src/google/protobuf/compiler/cpp/cpp_map_field.cc",
+        "src/google/protobuf/compiler/cpp/cpp_message.cc",
+        "src/google/protobuf/compiler/cpp/cpp_message_field.cc",
+        "src/google/protobuf/compiler/cpp/cpp_primitive_field.cc",
+        "src/google/protobuf/compiler/cpp/cpp_service.cc",
+        "src/google/protobuf/compiler/cpp/cpp_string_field.cc",
+        "src/google/protobuf/compiler/csharp/csharp_enum.cc",
+        "src/google/protobuf/compiler/csharp/csharp_enum_field.cc",
+        "src/google/protobuf/compiler/csharp/csharp_field_base.cc",
+        "src/google/protobuf/compiler/csharp/csharp_generator.cc",
+        "src/google/protobuf/compiler/csharp/csharp_helpers.cc",
+        "src/google/protobuf/compiler/csharp/csharp_map_field.cc",
+        "src/google/protobuf/compiler/csharp/csharp_message.cc",
+        "src/google/protobuf/compiler/csharp/csharp_message_field.cc",
+        "src/google/protobuf/compiler/csharp/csharp_primitive_field.cc",
+        "src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc",
+        "src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc",
+        "src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc",
+        "src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc",
+        "src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc",
+        "src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc",
+        "src/google/protobuf/compiler/java/java_context.cc",
+        "src/google/protobuf/compiler/java/java_doc_comment.cc",
+        "src/google/protobuf/compiler/java/java_enum.cc",
+        "src/google/protobuf/compiler/java/java_enum_field.cc",
+        "src/google/protobuf/compiler/java/java_enum_field_lite.cc",
+        "src/google/protobuf/compiler/java/java_extension.cc",
+        "src/google/protobuf/compiler/java/java_field.cc",
+        "src/google/protobuf/compiler/java/java_file.cc",
+        "src/google/protobuf/compiler/java/java_generator.cc",
+        "src/google/protobuf/compiler/java/java_generator_factory.cc",
+        "src/google/protobuf/compiler/java/java_helpers.cc",
+        "src/google/protobuf/compiler/java/java_lazy_message_field.cc",
+        "src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc",
+        "src/google/protobuf/compiler/java/java_map_field.cc",
+        "src/google/protobuf/compiler/java/java_map_field_lite.cc",
+        "src/google/protobuf/compiler/java/java_message.cc",
+        "src/google/protobuf/compiler/java/java_message_builder.cc",
+        "src/google/protobuf/compiler/java/java_message_builder_lite.cc",
+        "src/google/protobuf/compiler/java/java_message_field.cc",
+        "src/google/protobuf/compiler/java/java_message_field_lite.cc",
+        "src/google/protobuf/compiler/java/java_message_lite.cc",
+        "src/google/protobuf/compiler/java/java_name_resolver.cc",
+        "src/google/protobuf/compiler/java/java_primitive_field.cc",
+        "src/google/protobuf/compiler/java/java_primitive_field_lite.cc",
+        "src/google/protobuf/compiler/java/java_service.cc",
+        "src/google/protobuf/compiler/java/java_shared_code_generator.cc",
+        "src/google/protobuf/compiler/java/java_string_field.cc",
+        "src/google/protobuf/compiler/java/java_string_field_lite.cc",
+        "src/google/protobuf/compiler/javanano/javanano_enum.cc",
+        "src/google/protobuf/compiler/javanano/javanano_enum_field.cc",
+        "src/google/protobuf/compiler/javanano/javanano_extension.cc",
+        "src/google/protobuf/compiler/javanano/javanano_field.cc",
+        "src/google/protobuf/compiler/javanano/javanano_file.cc",
+        "src/google/protobuf/compiler/javanano/javanano_generator.cc",
+        "src/google/protobuf/compiler/javanano/javanano_helpers.cc",
+        "src/google/protobuf/compiler/javanano/javanano_map_field.cc",
+        "src/google/protobuf/compiler/javanano/javanano_message.cc",
+        "src/google/protobuf/compiler/javanano/javanano_message_field.cc",
+        "src/google/protobuf/compiler/javanano/javanano_primitive_field.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_enum.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_extension.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_field.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_file.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_generator.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_helpers.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_map_field.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_message.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_message_field.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_oneof.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc",
+        "src/google/protobuf/compiler/plugin.cc",
+        "src/google/protobuf/compiler/plugin.pb.cc",
+        "src/google/protobuf/compiler/python/python_generator.cc",
+        "src/google/protobuf/compiler/ruby/ruby_generator.cc",
+        "src/google/protobuf/compiler/subprocess.cc",
+        "src/google/protobuf/compiler/zip_writer.cc",
+    ],
+    copts = COPTS,
+    includes = ["src/"],
+    linkopts = LINK_OPTS,
+    visibility = ["//visibility:public"],
+    deps = [":protobuf"],
+)
+
+cc_binary(
+    name = "protoc",
+    srcs = ["src/google/protobuf/compiler/main.cc"],
+    linkopts = LINK_OPTS,
+    visibility = ["//visibility:public"],
+    deps = [":protoc_lib"],
+)
+
+################################################################################
+# Tests
+################################################################################
+
+LITE_TEST_PROTOS = [
+    # AUTOGEN(lite_test_protos)
+    "google/protobuf/map_lite_unittest.proto",
+    "google/protobuf/unittest_import_lite.proto",
+    "google/protobuf/unittest_import_public_lite.proto",
+    "google/protobuf/unittest_lite.proto",
+]
+
+TEST_PROTOS = [
+    # AUTOGEN(test_protos)
+    "google/protobuf/any_test.proto",
+    "google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto",
+    "google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto",
+    "google/protobuf/map_proto2_unittest.proto",
+    "google/protobuf/map_unittest.proto",
+    "google/protobuf/unittest.proto",
+    "google/protobuf/unittest_arena.proto",
+    "google/protobuf/unittest_custom_options.proto",
+    "google/protobuf/unittest_drop_unknown_fields.proto",
+    "google/protobuf/unittest_embed_optimize_for.proto",
+    "google/protobuf/unittest_empty.proto",
+    "google/protobuf/unittest_enormous_descriptor.proto",
+    "google/protobuf/unittest_import.proto",
+    "google/protobuf/unittest_import_public.proto",
+    "google/protobuf/unittest_lite_imports_nonlite.proto",
+    "google/protobuf/unittest_mset.proto",
+    "google/protobuf/unittest_no_arena.proto",
+    "google/protobuf/unittest_no_arena_import.proto",
+    "google/protobuf/unittest_no_field_presence.proto",
+    "google/protobuf/unittest_no_generic_services.proto",
+    "google/protobuf/unittest_optimize_for.proto",
+    "google/protobuf/unittest_preserve_unknown_enum.proto",
+    "google/protobuf/unittest_preserve_unknown_enum2.proto",
+    "google/protobuf/unittest_proto3_arena.proto",
+    "google/protobuf/unittest_well_known_types.proto",
+    "google/protobuf/util/internal/testdata/anys.proto",
+    "google/protobuf/util/internal/testdata/books.proto",
+    "google/protobuf/util/internal/testdata/default_value.proto",
+    "google/protobuf/util/internal/testdata/default_value_test.proto",
+    "google/protobuf/util/internal/testdata/field_mask.proto",
+    "google/protobuf/util/internal/testdata/maps.proto",
+    "google/protobuf/util/internal/testdata/struct.proto",
+    "google/protobuf/util/internal/testdata/timestamp_duration.proto",
+    "google/protobuf/util/json_format_proto3.proto",
+]
+
+PROTOS = LITE_TEST_PROTOS + TEST_PROTOS
+
+INPUTS = PROTOS + WELL_KNOWN_PROTOS
+
+OUTPUTS = ["src/" + x[:-5] + "pb.h" for x in PROTOS] + \
+          ["src/" + x[:-5] + "pb.cc" for x in PROTOS]
+
+genrule(
+    name = "gen_test_protos",
+    srcs = ["src/" + x for x in INPUTS],
+    outs = OUTPUTS,
+    cmd =
+        "$(location :protoc) --cpp_out=$(@D)/src" +
+        "".join([" -I" + x + "=$(location src/" + x + ")" for x in INPUTS]) +
+        "".join([" $(location src/" + x + ")" for x in PROTOS]),
+    tools = [":protoc"],
+)
+
+COMMON_TEST_SRCS = [
+    # AUTOGEN(common_test_srcs)
+    "src/google/protobuf/arena_test_util.cc",
+    "src/google/protobuf/map_test_util.cc",
+    "src/google/protobuf/test_util.cc",
+    "src/google/protobuf/testing/file.cc",
+    "src/google/protobuf/testing/googletest.cc",
+]
+
+cc_binary(
+    name = "test_plugin",
+    srcs = [
+        # AUTOGEN(test_plugin_srcs)
+        "src/google/protobuf/compiler/mock_code_generator.cc",
+        "src/google/protobuf/compiler/test_plugin.cc",
+        "src/google/protobuf/testing/file.cc",
+    ],
+    deps = [
+        ":protobuf",
+        ":protoc_lib",
+        "//external:gtest",
+    ],
+)
+
+cc_test(
+    name = "protobuf_test",
+    srcs = OUTPUTS + COMMON_TEST_SRCS + [
+        # AUTOGEN(test_srcs)
+        "src/google/protobuf/any_test.cc",
+        "src/google/protobuf/arena_unittest.cc",
+        "src/google/protobuf/arenastring_unittest.cc",
+        "src/google/protobuf/compiler/command_line_interface_unittest.cc",
+        "src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc",
+        "src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc",
+        "src/google/protobuf/compiler/cpp/cpp_unittest.cc",
+        "src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc",
+        "src/google/protobuf/compiler/importer_unittest.cc",
+        "src/google/protobuf/compiler/java/java_doc_comment_unittest.cc",
+        "src/google/protobuf/compiler/java/java_plugin_unittest.cc",
+        "src/google/protobuf/compiler/mock_code_generator.cc",
+        "src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc",
+        "src/google/protobuf/compiler/parser_unittest.cc",
+        "src/google/protobuf/compiler/python/python_plugin_unittest.cc",
+        "src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc",
+        "src/google/protobuf/descriptor_database_unittest.cc",
+        "src/google/protobuf/descriptor_unittest.cc",
+        "src/google/protobuf/drop_unknown_fields_test.cc",
+        "src/google/protobuf/dynamic_message_unittest.cc",
+        "src/google/protobuf/extension_set_unittest.cc",
+        "src/google/protobuf/generated_message_reflection_unittest.cc",
+        "src/google/protobuf/io/coded_stream_unittest.cc",
+        "src/google/protobuf/io/printer_unittest.cc",
+        "src/google/protobuf/io/tokenizer_unittest.cc",
+        "src/google/protobuf/io/zero_copy_stream_unittest.cc",
+        "src/google/protobuf/map_field_test.cc",
+        "src/google/protobuf/map_test.cc",
+        "src/google/protobuf/message_unittest.cc",
+        "src/google/protobuf/no_field_presence_test.cc",
+        "src/google/protobuf/preserve_unknown_enum_test.cc",
+        "src/google/protobuf/proto3_arena_unittest.cc",
+        "src/google/protobuf/reflection_ops_unittest.cc",
+        "src/google/protobuf/repeated_field_reflection_unittest.cc",
+        "src/google/protobuf/repeated_field_unittest.cc",
+        "src/google/protobuf/stubs/bytestream_unittest.cc",
+        "src/google/protobuf/stubs/common_unittest.cc",
+        "src/google/protobuf/stubs/once_unittest.cc",
+        "src/google/protobuf/stubs/status_test.cc",
+        "src/google/protobuf/stubs/statusor_test.cc",
+        "src/google/protobuf/stubs/stringpiece_unittest.cc",
+        "src/google/protobuf/stubs/stringprintf_unittest.cc",
+        "src/google/protobuf/stubs/structurally_valid_unittest.cc",
+        "src/google/protobuf/stubs/strutil_unittest.cc",
+        "src/google/protobuf/stubs/template_util_unittest.cc",
+        "src/google/protobuf/stubs/time_test.cc",
+        "src/google/protobuf/stubs/type_traits_unittest.cc",
+        "src/google/protobuf/text_format_unittest.cc",
+        "src/google/protobuf/unknown_field_set_unittest.cc",
+        "src/google/protobuf/util/field_comparator_test.cc",
+        "src/google/protobuf/util/internal/default_value_objectwriter_test.cc",
+        "src/google/protobuf/util/internal/json_objectwriter_test.cc",
+        "src/google/protobuf/util/internal/json_stream_parser_test.cc",
+        "src/google/protobuf/util/internal/protostream_objectsource_test.cc",
+        "src/google/protobuf/util/internal/protostream_objectwriter_test.cc",
+        "src/google/protobuf/util/internal/type_info_test_helper.cc",
+        "src/google/protobuf/util/json_util_test.cc",
+        "src/google/protobuf/util/type_resolver_util_test.cc",
+        "src/google/protobuf/well_known_types_unittest.cc",
+        "src/google/protobuf/wire_format_unittest.cc",
+    ],
+    copts = COPTS,
+    data = [
+        ":test_plugin",
+    ],
+    includes = [
+        "src/",
+    ],
+    linkopts = LINK_OPTS,
+    deps = [
+        ":protobuf",
+        ":protoc_lib",
+        "//external:gtest_main",
+    ],
+)
+

+ 182 - 0
CHANGES.txt

@@ -1,3 +1,185 @@
+2015-05-25 version 3.0.0-alpha-3 (Objective-C/C#):
+  General
+  * Introduced two new language implementations (Objective-C, C#) to proto3.
+  * Explicit "optional" keyword are disallowed in proto3 syntax, as fields are
+    optional by default.
+  * Group fields are no longer supported in proto3 syntax.
+  * Changed repeated primitive fields to use packed serialization by default in
+    proto3 (implemented for C++, Java, Python in this release).  The user can
+    still disable packed serialization by setting packed to false for now.
+  * Added well-known type protos (any.proto, empty.proto, timestamp.proto,
+    duration.proto, etc.). Users can import and use these protos just like
+    regular proto files. Addtional runtime support will be added for them in
+    future releases (in the form of utility helper functions, or having them
+    replaced by language specific types in generated code).
+  * Added a "reserved" keyword in both proto2 and proto3 syntax. User can use
+    this keyword to declare reserved field numbers and names to prevent them
+    from being reused by other fields in the same message.
+
+    To reserve field numbers, add a reserved declaration in your message:
+
+      message TestMessage {
+        reserved 2, 15, 9 to 11, 3;
+      }
+
+    This reserves field numbers 2, 3, 9, 10, 11 and 15. If a user uses any of
+    these as field numbers, the protocol buffer compiler will report an error.
+
+    Field names can also be reserved:
+
+      message TestMessage {
+        reserved "foo", "bar";
+      }
+
+  * Various bug fixes since 3.0.0-alpha-2
+
+  Objective-C
+    Objective-C includes a code generator and a native objective-c runtime
+    library.  By adding “--objc_out” to protoc, the code generator will generate
+    a header(*.pbobjc.h) and an implementation file(*.pbobjc.m) for each proto
+    file.
+
+    In this first release, the generated interface provides: enums, messages,
+    field support(single, repeated, map, oneof), proto2 and proto3 syntax
+    support, parsing and serialization. It’s  compatible with ARC and non-ARC
+    usage. Besides, user can also access it via the swift bridging header.
+
+    See objectivec/README.md for details.
+
+  C#
+    * C# protobufs are based on project
+      https://github.com/jskeet/protobuf-csharp-port. The original project was
+      frozen and all the new development will happen here.
+    * Codegen plugin for C# was completely rewritten to C++ and is now an
+      intergral part of protoc.
+    * Some refactorings and cleanup has been applied to the C# runtime library.
+    * Only proto2 is supported in C# at the moment, proto3 support is in
+      progress and will likely bring significant breaking changes to the API.
+
+    See csharp/README.md for details.
+
+  C++
+    * Added runtime support for Any type. To use Any in your proto file, first
+      import the definition of Any:
+
+        // foo.proto
+        import "google/protobuf/any.proto";
+        message Foo {
+          google.protobuf.Any any_field = 1;
+        }
+        message Bar {
+          int32 value = 1;
+        }
+
+      Then in C++ you can access the Any field using PackFrom()/UnpackTo()
+      methods:
+
+        Foo foo;
+        Bar bar = ...;
+        foo.mutable_any_field()->PackFrom(bar);
+        ...
+        if (foo.any_field().IsType<Bar>()) {
+          foo.any_field().UnpackTo(&bar);
+          ...
+        }
+    * In text format, entries of a map field will be sorted by key.
+
+  Java
+    * Continued optimizations on the lite runtime to improve performance for
+      Android.
+
+  Python
+    * Added map support.
+      - maps now have a dict-like interface (msg.map_field[key] = value)
+      - existing code that modifies maps via the repeated field interface
+        will need to be updated.
+
+  Ruby
+    * Improvements to RepeatedField's emulation of the Ruby Array API.
+    * Various speedups and internal cleanups.
+
+2015-02-26 version 3.0.0-alpha-2 (Python/Ruby/JavaNano):
+  General
+  * Introduced three new language implementations (Ruby, JavaNano, and
+    Python) to proto3.
+  * Various bug fixes since 3.0.0-alpha-1
+
+  Python:
+    Python has received several updates, most notably support for proto3
+    semantics in any .proto file that declares syntax="proto3".
+    Messages declared in proto3 files no longer represent field presence
+    for scalar fields (number, enums, booleans, or strings).  You can
+    no longer call HasField() for such fields, and they are serialized
+    based on whether they have a non-zero/empty/false value.
+
+    One other notable change is in the C++-accelerated implementation.
+    Descriptor objects (which describe the protobuf schema and allow
+    reflection over it) are no longer duplicated between the Python
+    and C++ layers.  The Python descriptors are now simple wrappers
+    around the C++ descriptors.  This change should significantly
+    reduce the memory usage of programs that use a lot of message
+    types.
+
+  Ruby:
+    We have added proto3 support for Ruby via a native C extension.
+
+    The Ruby extension itself is included in the ruby/ directory, and details on
+    building and installing the extension are in ruby/README.md. The extension
+    will also be published as a Ruby gem. Code generator support is included as
+    part of `protoc` with the `--ruby_out` flag.
+
+    The Ruby extension implements a user-friendly DSL to define message types
+    (also generated by the code generator from `.proto` files).  Once a message
+    type is defined, the user may create instances of the message that behave in
+    ways idiomatic to Ruby. For example:
+
+    - Message fields are present as ordinary Ruby properties (getter method
+      `foo` and setter method `foo=`).
+    - Repeated field elements are stored in a container that acts like a native
+      Ruby array, and map elements are stored in a container that acts like a
+      native Ruby hashmap.
+    - The usual well-known methods, such as `#to_s`, `#dup`, and the like, are
+      present.
+
+    Unlike several existing third-party Ruby extensions for protobuf, this
+    extension is built on a "strongly-typed" philosophy: message fields and
+    array/map containers will throw exceptions eagerly when values of the
+    incorrect type are inserted.
+
+    See ruby/README.md for details.
+
+  JavaNano:
+    JavaNano is a special code generator and runtime library designed especially
+    for resource-restricted systems, like Android. It is very resource-friendly
+    in both the amount of code and the runtime overhead. Here is an an overview
+    of JavaNano features compared with the official Java protobuf:
+
+    - No descriptors or message builders.
+    - All messages are mutable; fields are public Java fields.
+    - For optional fields only, encapsulation behind setter/getter/hazzer/
+      clearer functions is opt-in, which provide proper 'has' state support.
+    - For proto2, if not opted in, has state (field presence) is not available.
+      Serialization outputs all fields not equal to their defaults.
+      The behavior is consistent with proto3 semantics.
+    - Required fields (proto2 only) are always serialized.
+    - Enum constants are integers; protection against invalid values only
+      when parsing from the wire.
+    - Enum constants can be generated into container interfaces bearing
+      the enum's name (so the referencing code is in Java style).
+    - CodedInputByteBufferNano can only take byte[] (not InputStream).
+    - Similarly CodedOutputByteBufferNano can only write to byte[].
+    - Repeated fields are in arrays, not ArrayList or Vector. Null array
+      elements are allowed and silently ignored.
+    - Full support for serializing/deserializing repeated packed fields.
+    - Support  extensions (in proto2).
+    - Unset messages/groups are null, not an immutable empty default
+      instance.
+    - toByteArray(...) and mergeFrom(...) are now static functions of
+      MessageNano.
+    - The 'bytes' type translates to the Java type byte[].
+
+    See javanano/README.txt for details.
+
 2014-12-01 version 3.0.0-alpha-1 (C++/Java):
 2014-12-01 version 3.0.0-alpha-1 (C++/Java):
 
 
   General
   General

+ 0 - 2
LICENSE

@@ -8,8 +8,6 @@ This license applies to all parts of Protocol Buffers except the following:
     src/google/protobuf/stubs/atomicops_internals_aix.h.
     src/google/protobuf/stubs/atomicops_internals_aix.h.
     This file is copyrighted by Bloomberg Finance LP.
     This file is copyrighted by Bloomberg Finance LP.
 
 
-  - Andorid.mk, which is copyrighted by The Android Open Source Project.
-
 Copyright 2014, Google Inc.  All rights reserved.
 Copyright 2014, Google Inc.  All rights reserved.
 
 
 Redistribution and use in source and binary forms, with or without
 Redistribution and use in source and binary forms, with or without

+ 389 - 58
Makefile.am

@@ -8,59 +8,177 @@ AUTOMAKE_OPTIONS = foreign
 # the right time.
 # the right time.
 SUBDIRS = . src
 SUBDIRS = . src
 
 
-# Always include gtest in distributions.
-DIST_SUBDIRS = $(subdirs) src
+# Always include gmock in distributions.
+DIST_SUBDIRS = $(subdirs) src conformance
 
 
-# Build gtest before we build protobuf tests.  We don't add gtest to SUBDIRS
-# because then "make check" would also build and run all of gtest's own tests,
+# Build gmock before we build protobuf tests.  We don't add gmock to SUBDIRS
+# because then "make check" would also build and run all of gmock's own tests,
 # which takes a lot of time and is generally not useful to us.  Also, we don't
 # which takes a lot of time and is generally not useful to us.  Also, we don't
-# want "make install" to recurse into gtest since we don't want to overwrite
-# the installed version of gtest if there is one.
+# want "make install" to recurse into gmock since we don't want to overwrite
+# the installed version of gmock if there is one.
 check-local:
 check-local:
-	@echo "Making lib/libgtest.a lib/libgtest_main.a in gtest"
-	@cd gtest && $(MAKE) $(AM_MAKEFLAGS) lib/libgtest.la lib/libgtest_main.la
+	@echo "Making lib/libgmock.a lib/libgmock_main.a in gmock"
+	@cd gmock && $(MAKE) $(AM_MAKEFLAGS) lib/libgmock.la lib/libgmock_main.la
+	@cd gmock/gtest && $(MAKE) $(AM_MAKEFLAGS) lib/libgtest.la lib/libgtest_main.la
 
 
-# We would like to clean gtest when "make clean" is invoked.  But we have to
+# We would like to clean gmock when "make clean" is invoked.  But we have to
 # be careful because clean-local is also invoked during "make distclean", but
 # be careful because clean-local is also invoked during "make distclean", but
-# "make distclean" already recurses into gtest because it's listed among the
-# DIST_SUBDIRS.  distclean will delete gtest/Makefile, so if we then try to
+# "make distclean" already recurses into gmock because it's listed among the
+# DIST_SUBDIRS.  distclean will delete gmock/Makefile, so if we then try to
 # cd to the directory again and "make clean" it will fail.  So, check that the
 # cd to the directory again and "make clean" it will fail.  So, check that the
 # Makefile exists before recursing.
 # Makefile exists before recursing.
 clean-local:
 clean-local:
-	@if test -e gtest/Makefile; then \
-	  echo "Making clean in gtest"; \
-	  cd gtest && $(MAKE) $(AM_MAKEFLAGS) clean; \
+	@if test -e gmock/Makefile; then \
+	  echo "Making clean in gmock"; \
+	  cd gmock && $(MAKE) $(AM_MAKEFLAGS) clean; \
+	fi; \
+	if test -e conformance/Makefile; then \
+	  echo "Making clean in conformance"; \
+	  cd conformance && $(MAKE) $(AM_MAKEFLAGS) clean; \
 	fi
 	fi
 
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = protobuf.pc protobuf-lite.pc
 pkgconfig_DATA = protobuf.pc protobuf-lite.pc
 
 
+csharp_EXTRA_DIST=                                                           \
+  csharp/CHANGES.txt                                                         \
+  csharp/README.md                                                           \
+  csharp/build_packages.bat                                                  \
+  csharp/buildall.sh                                                         \
+  csharp/generate_protos.sh                                                  \
+  csharp/keys/Google.Protobuf.public.snk                                     \
+  csharp/keys/README.md                                                      \
+  csharp/protos/unittest_issues.proto                                        \
+  csharp/src/AddressBook/AddPerson.cs                                        \
+  csharp/src/AddressBook/AddressBook.csproj                                  \
+  csharp/src/AddressBook/Addressbook.cs                                      \
+  csharp/src/AddressBook/ListPeople.cs                                       \
+  csharp/src/AddressBook/Program.cs                                          \
+  csharp/src/AddressBook/Properties/AssemblyInfo.cs                          \
+  csharp/src/AddressBook/SampleUsage.cs                                      \
+  csharp/src/AddressBook/app.config                                          \
+  csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj        \
+  csharp/src/Google.Protobuf.JsonDump/Program.cs                             \
+  csharp/src/Google.Protobuf.JsonDump/Properties/AssemblyInfo.cs             \
+  csharp/src/Google.Protobuf.JsonDump/app.config                             \
+  csharp/src/Google.Protobuf.Test/ByteStringTest.cs                          \
+  csharp/src/Google.Protobuf.Test/CodedInputStreamExtensions.cs              \
+  csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs                    \
+  csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs                   \
+  csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs                \
+  csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs           \
+  csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs                    \
+  csharp/src/Google.Protobuf.Test/EqualityTester.cs                          \
+  csharp/src/Google.Protobuf.Test/FieldCodecTest.cs                          \
+  csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs                    \
+  csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj                \
+  csharp/src/Google.Protobuf.Test/IssuesTest.cs                              \
+  csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs                       \
+  csharp/src/Google.Protobuf.Test/Properties/AppManifest.xml                 \
+  csharp/src/Google.Protobuf.Test/Properties/AssemblyInfo.cs                 \
+  csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs              \
+  csharp/src/Google.Protobuf.Test/SampleEnum.cs                              \
+  csharp/src/Google.Protobuf.Test/SampleMessages.cs                          \
+  csharp/src/Google.Protobuf.Test/TestCornerCases.cs                         \
+  csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs            \
+  csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs         \
+  csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs   \
+  csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs               \
+  csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs               \
+  csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs       \
+  csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs             \
+  csharp/src/Google.Protobuf.Test/packages.config                            \
+  csharp/src/Google.Protobuf.sln                                             \
+  csharp/src/Google.Protobuf/ByteArray.cs                                    \
+  csharp/src/Google.Protobuf/ByteString.cs                                   \
+  csharp/src/Google.Protobuf/CodedInputStream.cs                             \
+  csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs                \
+  csharp/src/Google.Protobuf/CodedOutputStream.cs                            \
+  csharp/src/Google.Protobuf/Collections/MapField.cs                         \
+  csharp/src/Google.Protobuf/Collections/ReadOnlyDictionary.cs               \
+  csharp/src/Google.Protobuf/Collections/RepeatedField.cs                    \
+  csharp/src/Google.Protobuf/FieldCodec.cs                                   \
+  csharp/src/Google.Protobuf/FrameworkPortability.cs                         \
+  csharp/src/Google.Protobuf/Google.Protobuf.csproj                          \
+  csharp/src/Google.Protobuf/Google.Protobuf.nuspec                          \
+  csharp/src/Google.Protobuf/IMessage.cs                                     \
+  csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs               \
+  csharp/src/Google.Protobuf/JsonFormatter.cs                                \
+  csharp/src/Google.Protobuf/LimitedInputStream.cs                           \
+  csharp/src/Google.Protobuf/MessageExtensions.cs                            \
+  csharp/src/Google.Protobuf/MessageParser.cs                                \
+  csharp/src/Google.Protobuf/Preconditions.cs                                \
+  csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs                      \
+  csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs                    \
+  csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs                    \
+  csharp/src/Google.Protobuf/Reflection/DescriptorProtoFile.cs               \
+  csharp/src/Google.Protobuf/Reflection/DescriptorUtil.cs                    \
+  csharp/src/Google.Protobuf/Reflection/DescriptorValidationException.cs     \
+  csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs                    \
+  csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs               \
+  csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs                 \
+  csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs                   \
+  csharp/src/Google.Protobuf/Reflection/FieldType.cs                         \
+  csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs                    \
+  csharp/src/Google.Protobuf/Reflection/GeneratedCodeInfo.cs                 \
+  csharp/src/Google.Protobuf/Reflection/IDescriptor.cs                       \
+  csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs                    \
+  csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs                  \
+  csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs                 \
+  csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs                  \
+  csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs                     \
+  csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs                   \
+  csharp/src/Google.Protobuf/Reflection/PackageDescriptor.cs                 \
+  csharp/src/Google.Protobuf/Reflection/PartialClasses.cs                    \
+  csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs                    \
+  csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs             \
+  csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs                 \
+  csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs               \
+  csharp/src/Google.Protobuf/WellKnownTypes/Any.cs                           \
+  csharp/src/Google.Protobuf/WellKnownTypes/Api.cs                           \
+  csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs                      \
+  csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs                         \
+  csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs                     \
+  csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs                 \
+  csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs                        \
+  csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs                     \
+  csharp/src/Google.Protobuf/WellKnownTypes/Type.cs                          \
+  csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs                      \
+  csharp/src/Google.Protobuf/WireFormat.cs                                   \
+  csharp/src/packages/repositories.config
+
 java_EXTRA_DIST=                                                             \
 java_EXTRA_DIST=                                                             \
   java/src/main/java/com/google/protobuf/AbstractMessage.java                \
   java/src/main/java/com/google/protobuf/AbstractMessage.java                \
   java/src/main/java/com/google/protobuf/AbstractMessageLite.java            \
   java/src/main/java/com/google/protobuf/AbstractMessageLite.java            \
   java/src/main/java/com/google/protobuf/AbstractParser.java                 \
   java/src/main/java/com/google/protobuf/AbstractParser.java                 \
+  java/src/main/java/com/google/protobuf/AbstractProtobufList.java           \
   java/src/main/java/com/google/protobuf/BlockingRpcChannel.java             \
   java/src/main/java/com/google/protobuf/BlockingRpcChannel.java             \
   java/src/main/java/com/google/protobuf/BlockingService.java                \
   java/src/main/java/com/google/protobuf/BlockingService.java                \
   java/src/main/java/com/google/protobuf/BoundedByteString.java              \
   java/src/main/java/com/google/protobuf/BoundedByteString.java              \
+  java/src/main/java/com/google/protobuf/BooleanArrayList.java               \
   java/src/main/java/com/google/protobuf/ByteString.java                     \
   java/src/main/java/com/google/protobuf/ByteString.java                     \
   java/src/main/java/com/google/protobuf/CodedInputStream.java               \
   java/src/main/java/com/google/protobuf/CodedInputStream.java               \
   java/src/main/java/com/google/protobuf/CodedOutputStream.java              \
   java/src/main/java/com/google/protobuf/CodedOutputStream.java              \
   java/src/main/java/com/google/protobuf/Descriptors.java                    \
   java/src/main/java/com/google/protobuf/Descriptors.java                    \
+  java/src/main/java/com/google/protobuf/DoubleArrayList.java                \
   java/src/main/java/com/google/protobuf/DynamicMessage.java                 \
   java/src/main/java/com/google/protobuf/DynamicMessage.java                 \
   java/src/main/java/com/google/protobuf/Extension.java                      \
   java/src/main/java/com/google/protobuf/Extension.java                      \
   java/src/main/java/com/google/protobuf/ExtensionLite.java                  \
   java/src/main/java/com/google/protobuf/ExtensionLite.java                  \
   java/src/main/java/com/google/protobuf/ExtensionRegistry.java              \
   java/src/main/java/com/google/protobuf/ExtensionRegistry.java              \
   java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java          \
   java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java          \
   java/src/main/java/com/google/protobuf/FieldSet.java                       \
   java/src/main/java/com/google/protobuf/FieldSet.java                       \
+  java/src/main/java/com/google/protobuf/FloatArrayList.java                 \
   java/src/main/java/com/google/protobuf/GeneratedMessage.java               \
   java/src/main/java/com/google/protobuf/GeneratedMessage.java               \
   java/src/main/java/com/google/protobuf/GeneratedMessageLite.java           \
   java/src/main/java/com/google/protobuf/GeneratedMessageLite.java           \
   java/src/main/java/com/google/protobuf/Internal.java                       \
   java/src/main/java/com/google/protobuf/Internal.java                       \
+  java/src/main/java/com/google/protobuf/IntArrayList.java                   \
   java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \
   java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \
   java/src/main/java/com/google/protobuf/LazyField.java                      \
   java/src/main/java/com/google/protobuf/LazyField.java                      \
   java/src/main/java/com/google/protobuf/LazyFieldLite.java                  \
   java/src/main/java/com/google/protobuf/LazyFieldLite.java                  \
   java/src/main/java/com/google/protobuf/LazyStringArrayList.java            \
   java/src/main/java/com/google/protobuf/LazyStringArrayList.java            \
   java/src/main/java/com/google/protobuf/LazyStringList.java                 \
   java/src/main/java/com/google/protobuf/LazyStringList.java                 \
   java/src/main/java/com/google/protobuf/LiteralByteString.java              \
   java/src/main/java/com/google/protobuf/LiteralByteString.java              \
+  java/src/main/java/com/google/protobuf/LongArrayList.java                  \
   java/src/main/java/com/google/protobuf/MapEntry.java                       \
   java/src/main/java/com/google/protobuf/MapEntry.java                       \
   java/src/main/java/com/google/protobuf/MapEntryLite.java                   \
   java/src/main/java/com/google/protobuf/MapEntryLite.java                   \
   java/src/main/java/com/google/protobuf/MapField.java                       \
   java/src/main/java/com/google/protobuf/MapField.java                       \
@@ -70,7 +188,9 @@ java_EXTRA_DIST=                                                             \
   java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java           \
   java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java           \
   java/src/main/java/com/google/protobuf/MessageOrBuilder.java               \
   java/src/main/java/com/google/protobuf/MessageOrBuilder.java               \
   java/src/main/java/com/google/protobuf/MessageReflection.java              \
   java/src/main/java/com/google/protobuf/MessageReflection.java              \
+  java/src/main/java/com/google/protobuf/MutabilityOracle.java               \
   java/src/main/java/com/google/protobuf/Parser.java                         \
   java/src/main/java/com/google/protobuf/Parser.java                         \
+  java/src/main/java/com/google/protobuf/ProtobufArrayList.java              \
   java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java            \
   java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java            \
   java/src/main/java/com/google/protobuf/ProtocolStringList.java             \
   java/src/main/java/com/google/protobuf/ProtocolStringList.java             \
   java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java           \
   java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java           \
@@ -89,19 +209,24 @@ java_EXTRA_DIST=                                                             \
   java/src/main/java/com/google/protobuf/UnknownFieldSetLite.java            \
   java/src/main/java/com/google/protobuf/UnknownFieldSetLite.java            \
   java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java     \
   java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java     \
   java/src/main/java/com/google/protobuf/Utf8.java                           \
   java/src/main/java/com/google/protobuf/Utf8.java                           \
+  java/src/test/java/com/google/protobuf/WellKnownTypesTest.java             \
   java/src/main/java/com/google/protobuf/WireFormat.java                     \
   java/src/main/java/com/google/protobuf/WireFormat.java                     \
   java/src/test/java/com/google/protobuf/AbstractMessageTest.java            \
   java/src/test/java/com/google/protobuf/AbstractMessageTest.java            \
   java/src/test/java/com/google/protobuf/BoundedByteStringTest.java          \
   java/src/test/java/com/google/protobuf/BoundedByteStringTest.java          \
+  java/src/test/java/com/google/protobuf/BooleanArrayListTest.java           \
   java/src/test/java/com/google/protobuf/ByteStringTest.java                 \
   java/src/test/java/com/google/protobuf/ByteStringTest.java                 \
   java/src/test/java/com/google/protobuf/CheckUtf8Test.java                  \
   java/src/test/java/com/google/protobuf/CheckUtf8Test.java                  \
   java/src/test/java/com/google/protobuf/CodedInputStreamTest.java           \
   java/src/test/java/com/google/protobuf/CodedInputStreamTest.java           \
   java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java          \
   java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java          \
   java/src/test/java/com/google/protobuf/DeprecatedFieldTest.java            \
   java/src/test/java/com/google/protobuf/DeprecatedFieldTest.java            \
   java/src/test/java/com/google/protobuf/DescriptorsTest.java                \
   java/src/test/java/com/google/protobuf/DescriptorsTest.java                \
+  java/src/test/java/com/google/protobuf/DoubleArrayListTest.java            \
   java/src/test/java/com/google/protobuf/DynamicMessageTest.java             \
   java/src/test/java/com/google/protobuf/DynamicMessageTest.java             \
   java/src/test/java/com/google/protobuf/FieldPresenceTest.java              \
   java/src/test/java/com/google/protobuf/FieldPresenceTest.java              \
+  java/src/test/java/com/google/protobuf/FloatArrayListTest.java             \
   java/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java       \
   java/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java       \
   java/src/test/java/com/google/protobuf/GeneratedMessageTest.java           \
   java/src/test/java/com/google/protobuf/GeneratedMessageTest.java           \
+  java/src/test/java/com/google/protobuf/IntArrayListTest.java               \
   java/src/test/java/com/google/protobuf/IsValidUtf8Test.java                \
   java/src/test/java/com/google/protobuf/IsValidUtf8Test.java                \
   java/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java            \
   java/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java            \
   java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java              \
   java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java              \
@@ -112,12 +237,14 @@ java_EXTRA_DIST=                                                             \
   java/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java          \
   java/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java          \
   java/src/test/java/com/google/protobuf/LiteralByteStringTest.java          \
   java/src/test/java/com/google/protobuf/LiteralByteStringTest.java          \
   java/src/test/java/com/google/protobuf/LiteTest.java                       \
   java/src/test/java/com/google/protobuf/LiteTest.java                       \
+  java/src/test/java/com/google/protobuf/LongArrayListTest.java              \
   java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java           \
   java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java           \
   java/src/test/java/com/google/protobuf/MapForProto2Test.java               \
   java/src/test/java/com/google/protobuf/MapForProto2Test.java               \
   java/src/test/java/com/google/protobuf/MapTest.java                        \
   java/src/test/java/com/google/protobuf/MapTest.java                        \
   java/src/test/java/com/google/protobuf/MessageTest.java                    \
   java/src/test/java/com/google/protobuf/MessageTest.java                    \
   java/src/test/java/com/google/protobuf/NestedBuildersTest.java             \
   java/src/test/java/com/google/protobuf/NestedBuildersTest.java             \
   java/src/test/java/com/google/protobuf/ParserTest.java                     \
   java/src/test/java/com/google/protobuf/ParserTest.java                     \
+  java/src/test/java/com/google/protobuf/ProtobufArrayListTest.java          \
   java/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java       \
   java/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java       \
   java/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java    \
   java/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java    \
   java/src/test/java/com/google/protobuf/RopeByteStringTest.java             \
   java/src/test/java/com/google/protobuf/RopeByteStringTest.java             \
@@ -137,6 +264,7 @@ java_EXTRA_DIST=                                                             \
   java/src/test/java/com/google/protobuf/lite_equals_and_hash.proto          \
   java/src/test/java/com/google/protobuf/lite_equals_and_hash.proto          \
   java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto      \
   java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto      \
   java/src/test/java/com/google/protobuf/map_for_proto2_test.proto           \
   java/src/test/java/com/google/protobuf/map_for_proto2_test.proto           \
+  java/src/test/java/com/google/protobuf/map_initialization_order_test.proto \
   java/src/test/java/com/google/protobuf/map_test.proto                      \
   java/src/test/java/com/google/protobuf/map_test.proto                      \
   java/src/test/java/com/google/protobuf/multiple_files_test.proto           \
   java/src/test/java/com/google/protobuf/multiple_files_test.proto           \
   java/src/test/java/com/google/protobuf/nested_builders_test.proto          \
   java/src/test/java/com/google/protobuf/nested_builders_test.proto          \
@@ -151,36 +279,209 @@ java_EXTRA_DIST=                                                             \
   java/src/test/java/com/google/protobuf/test_check_utf8.proto               \
   java/src/test/java/com/google/protobuf/test_check_utf8.proto               \
   java/src/test/java/com/google/protobuf/test_check_utf8_size.proto          \
   java/src/test/java/com/google/protobuf/test_check_utf8_size.proto          \
   java/src/test/java/com/google/protobuf/test_custom_options.proto           \
   java/src/test/java/com/google/protobuf/test_custom_options.proto           \
+  java/src/test/java/com/google/protobuf/test_extra_interfaces.proto         \
   java/pom.xml                                                               \
   java/pom.xml                                                               \
-  java/README.txt
+  java/README.md
+
+javanano_EXTRA_DIST=                                                                      \
+  javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java          \
+  javanano/src/main/java/com/google/protobuf/nano/FieldData.java                          \
+  javanano/src/main/java/com/google/protobuf/nano/FieldArray.java                         \
+  javanano/src/main/java/com/google/protobuf/nano/WireFormatNano.java                     \
+  javanano/src/main/java/com/google/protobuf/nano/Extension.java                          \
+  javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java           \
+  javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java                   \
+  javanano/src/main/java/com/google/protobuf/nano/MessageNano.java                        \
+  javanano/src/main/java/com/google/protobuf/nano/InternalNano.java                       \
+  javanano/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java \
+  javanano/src/main/java/com/google/protobuf/nano/MapFactories.java                       \
+  javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java              \
+  javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java                 \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_accessors_nano.proto           \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_enum_class_nano.proto          \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_reference_types_nano.proto     \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_extension_repeated_nano.proto  \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_has_nano.proto                 \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto                     \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_multiple_nameclash_nano.proto  \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_single_nano.proto              \
+  javanano/src/test/java/com/google/protobuf/nano/NanoTest.java                           \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_simple_nano.proto              \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_import_nano.proto              \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_repeated_merge_nano.proto      \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto           \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_repeated_packables_nano.proto  \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_extension_singular_nano.proto  \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_recursive_nano.proto           \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_extension_packed_nano.proto    \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_enum_validity_nano.proto       \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_stringutf8_nano.proto          \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_multiple_nano.proto            \
+  javanano/src/test/java/com/google/protobuf/nano/unittest_enum_class_multiple_nano.proto \
+  javanano/src/test/java/com/google/protobuf/nano/map_test.proto                          \
+  javanano/README.md                                                                      \
+  javanano/pom.xml
+
+objectivec_EXTRA_DIST=                                                       \
+  objectivec/DevTools/check_version_stamps.sh                                \
+  objectivec/DevTools/full_mac_build.sh                                      \
+  objectivec/DevTools/pddm.py                                                \
+  objectivec/DevTools/pddm_tests.py                                          \
+  objectivec/generate_descriptors_proto.sh                                   \
+  objectivec/google/protobuf/Any.pbobjc.h                                    \
+  objectivec/google/protobuf/Any.pbobjc.m                                    \
+  objectivec/google/protobuf/Api.pbobjc.h                                    \
+  objectivec/google/protobuf/Api.pbobjc.m                                    \
+  objectivec/google/protobuf/Descriptor.pbobjc.h                             \
+  objectivec/google/protobuf/Descriptor.pbobjc.m                             \
+  objectivec/google/protobuf/Duration.pbobjc.h                               \
+  objectivec/google/protobuf/Duration.pbobjc.m                               \
+  objectivec/google/protobuf/Empty.pbobjc.h                                  \
+  objectivec/google/protobuf/Empty.pbobjc.m                                  \
+  objectivec/google/protobuf/FieldMask.pbobjc.h                              \
+  objectivec/google/protobuf/FieldMask.pbobjc.m                              \
+  objectivec/google/protobuf/SourceContext.pbobjc.h                          \
+  objectivec/google/protobuf/SourceContext.pbobjc.m                          \
+  objectivec/google/protobuf/Struct.pbobjc.h                                 \
+  objectivec/google/protobuf/Struct.pbobjc.m                                 \
+  objectivec/google/protobuf/Timestamp.pbobjc.h                              \
+  objectivec/google/protobuf/Timestamp.pbobjc.m                              \
+  objectivec/google/protobuf/Type.pbobjc.h                                   \
+  objectivec/google/protobuf/Type.pbobjc.m                                   \
+  objectivec/google/protobuf/Wrappers.pbobjc.h                               \
+  objectivec/google/protobuf/Wrappers.pbobjc.m                               \
+  objectivec/GPBArray.h                                                      \
+  objectivec/GPBArray.m                                                      \
+  objectivec/GPBArray_PackagePrivate.h                                       \
+  objectivec/GPBBootstrap.h                                                  \
+  objectivec/GPBCodedInputStream.h                                           \
+  objectivec/GPBCodedInputStream.m                                           \
+  objectivec/GPBCodedInputStream_PackagePrivate.h                            \
+  objectivec/GPBCodedOutputStream.h                                          \
+  objectivec/GPBCodedOutputStream.m                                          \
+  objectivec/GPBDescriptor.h                                                 \
+  objectivec/GPBDescriptor.m                                                 \
+  objectivec/GPBDescriptor_PackagePrivate.h                                  \
+  objectivec/GPBDictionary.h                                                 \
+  objectivec/GPBDictionary.m                                                 \
+  objectivec/GPBDictionary_PackagePrivate.h                                  \
+  objectivec/GPBExtensionInternals.h                                         \
+  objectivec/GPBExtensionInternals.m                                         \
+  objectivec/GPBExtensionRegistry.h                                          \
+  objectivec/GPBExtensionRegistry.m                                          \
+  objectivec/GPBMessage.h                                                    \
+  objectivec/GPBMessage.m                                                    \
+  objectivec/GPBMessage_PackagePrivate.h                                     \
+  objectivec/GPBProtocolBuffers.h                                            \
+  objectivec/GPBProtocolBuffers.m                                            \
+  objectivec/GPBProtocolBuffers_RuntimeSupport.h                             \
+  objectivec/GPBRootObject.h                                                 \
+  objectivec/GPBRootObject.m                                                 \
+  objectivec/GPBRootObject_PackagePrivate.h                                  \
+  objectivec/GPBRuntimeTypes.h                                               \
+  objectivec/GPBUnknownField.h                                               \
+  objectivec/GPBUnknownField.m                                               \
+  objectivec/GPBUnknownField_PackagePrivate.h                                \
+  objectivec/GPBUnknownFieldSet.h                                            \
+  objectivec/GPBUnknownFieldSet.m                                            \
+  objectivec/GPBUnknownFieldSet_PackagePrivate.h                             \
+  objectivec/GPBUtilities.h                                                  \
+  objectivec/GPBUtilities.m                                                  \
+  objectivec/GPBUtilities_PackagePrivate.h                                   \
+  objectivec/GPBWellKnownTypes.h                                             \
+  objectivec/GPBWellKnownTypes.m                                             \
+  objectivec/GPBWireFormat.h                                                 \
+  objectivec/GPBWireFormat.m                                                 \
+  objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj                   \
+  objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata \
+  objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings \
+  objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcbaselines/8BBEA4A5147C727100C4ADB7.xcbaseline/FFE465CA-0E74-40E8-9F09-500B66B7DCB2.plist \
+  objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcbaselines/8BBEA4A5147C727100C4ADB7.xcbaseline/Info.plist \
+  objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme \
+  objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme \
+  objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj                   \
+  objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/contents.xcworkspacedata \
+  objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings \
+  objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme \
+  objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme \
+  objectivec/README.md                                                       \
+  objectivec/Tests/golden_message                                            \
+  objectivec/Tests/golden_packed_fields_message                              \
+  objectivec/Tests/GPBARCUnittestProtos.m                                    \
+  objectivec/Tests/GPBArrayTests.m                                           \
+  objectivec/Tests/GPBCodedInputStreamTests.m                                \
+  objectivec/Tests/GPBCodedOuputStreamTests.m                                \
+  objectivec/Tests/GPBConcurrencyTests.m                                     \
+  objectivec/Tests/GPBDescriptorTests.m                                      \
+  objectivec/Tests/GPBDictionaryTests+Bool.m                                 \
+  objectivec/Tests/GPBDictionaryTests+Int32.m                                \
+  objectivec/Tests/GPBDictionaryTests+Int64.m                                \
+  objectivec/Tests/GPBDictionaryTests+String.m                               \
+  objectivec/Tests/GPBDictionaryTests+UInt32.m                               \
+  objectivec/Tests/GPBDictionaryTests+UInt64.m                               \
+  objectivec/Tests/GPBDictionaryTests.pddm                                   \
+  objectivec/Tests/GPBMessageTests+Merge.m                                   \
+  objectivec/Tests/GPBMessageTests+Runtime.m                                 \
+  objectivec/Tests/GPBMessageTests+Serialization.m                           \
+  objectivec/Tests/GPBMessageTests.m                                         \
+  objectivec/Tests/GPBPerfTests.m                                            \
+  objectivec/Tests/GPBStringTests.m                                          \
+  objectivec/Tests/GPBSwiftTests.swift                                       \
+  objectivec/Tests/GPBTestUtilities.h                                        \
+  objectivec/Tests/GPBTestUtilities.m                                        \
+  objectivec/Tests/GPBUnittestProtos.m                                       \
+  objectivec/Tests/GPBUnknownFieldSetTest.m                                  \
+  objectivec/Tests/GPBUtilitiesTests.m                                       \
+  objectivec/Tests/GPBWellKnownTypesTest.m                                   \
+  objectivec/Tests/GPBWireFormatTests.m                                      \
+  objectivec/Tests/iOSTestHarness/AppDelegate.m                              \
+  objectivec/Tests/iOSTestHarness/en.lproj/InfoPlist.strings                 \
+  objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json      \
+  objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6.png          \
+  objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6_2x.png       \
+  objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7.png          \
+  objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7_2x.png       \
+  objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6.png        \
+  objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6_2x.png     \
+  objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_2x.png     \
+  objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7_3x.png     \
+  objectivec/Tests/iOSTestHarness/Images.xcassets/LaunchImage.launchimage/Contents.json \
+  objectivec/Tests/iOSTestHarness/Info.plist                                  \
+  objectivec/Tests/iOSTestHarness/LaunchScreen.xib                            \
+  objectivec/Tests/text_format_map_unittest_data.txt                          \
+  objectivec/Tests/text_format_unittest_data.txt                              \
+  objectivec/Tests/unittest_cycle.proto                                       \
+  objectivec/Tests/unittest_objc.proto                                        \
+  objectivec/Tests/unittest_runtime_proto2.proto                              \
+  objectivec/Tests/unittest_runtime_proto3.proto                              \
+  objectivec/Tests/UnitTests-Bridging-Header.h                                \
+  objectivec/Tests/UnitTests-Info.plist                                       \
+  Protobuf.podspec
 
 
 python_EXTRA_DIST=                                                           \
 python_EXTRA_DIST=                                                           \
+  python/MANIFEST.in                                                         \
   python/google/protobuf/internal/api_implementation.cc                      \
   python/google/protobuf/internal/api_implementation.cc                      \
   python/google/protobuf/internal/api_implementation.py                      \
   python/google/protobuf/internal/api_implementation.py                      \
-  python/google/protobuf/internal/api_implementation_default_test.py         \
   python/google/protobuf/internal/containers.py                              \
   python/google/protobuf/internal/containers.py                              \
-  python/google/protobuf/internal/cpp_message.py                             \
   python/google/protobuf/internal/decoder.py                                 \
   python/google/protobuf/internal/decoder.py                                 \
   python/google/protobuf/internal/descriptor_database_test.py                \
   python/google/protobuf/internal/descriptor_database_test.py                \
   python/google/protobuf/internal/descriptor_pool_test.py                    \
   python/google/protobuf/internal/descriptor_pool_test.py                    \
   python/google/protobuf/internal/descriptor_pool_test1.proto                \
   python/google/protobuf/internal/descriptor_pool_test1.proto                \
   python/google/protobuf/internal/descriptor_pool_test2.proto                \
   python/google/protobuf/internal/descriptor_pool_test2.proto                \
-  python/google/protobuf/internal/descriptor_python_test.py                  \
   python/google/protobuf/internal/descriptor_test.py                         \
   python/google/protobuf/internal/descriptor_test.py                         \
   python/google/protobuf/internal/encoder.py                                 \
   python/google/protobuf/internal/encoder.py                                 \
   python/google/protobuf/internal/enum_type_wrapper.py                       \
   python/google/protobuf/internal/enum_type_wrapper.py                       \
   python/google/protobuf/internal/factory_test1.proto                        \
   python/google/protobuf/internal/factory_test1.proto                        \
   python/google/protobuf/internal/factory_test2.proto                        \
   python/google/protobuf/internal/factory_test2.proto                        \
   python/google/protobuf/internal/generator_test.py                          \
   python/google/protobuf/internal/generator_test.py                          \
-  python/google/protobuf/internal/message_factory_python_test.py             \
   python/google/protobuf/internal/message_factory_test.py                    \
   python/google/protobuf/internal/message_factory_test.py                    \
   python/google/protobuf/internal/message_listener.py                        \
   python/google/protobuf/internal/message_listener.py                        \
-  python/google/protobuf/internal/message_python_test.py                     \
   python/google/protobuf/internal/message_test.py                            \
   python/google/protobuf/internal/message_test.py                            \
   python/google/protobuf/internal/missing_enum_values.proto                  \
   python/google/protobuf/internal/missing_enum_values.proto                  \
   python/google/protobuf/internal/more_extensions.proto                      \
   python/google/protobuf/internal/more_extensions.proto                      \
   python/google/protobuf/internal/more_extensions_dynamic.proto              \
   python/google/protobuf/internal/more_extensions_dynamic.proto              \
   python/google/protobuf/internal/more_messages.proto                        \
   python/google/protobuf/internal/more_messages.proto                        \
+  python/google/protobuf/internal/_parameterized.py                          \
   python/google/protobuf/internal/proto_builder_test.py                      \
   python/google/protobuf/internal/proto_builder_test.py                      \
   python/google/protobuf/internal/python_message.py                          \
   python/google/protobuf/internal/python_message.py                          \
   python/google/protobuf/internal/reflection_test.py                         \
   python/google/protobuf/internal/reflection_test.py                         \
@@ -195,7 +496,6 @@ python_EXTRA_DIST=                                                           \
   python/google/protobuf/internal/wire_format.py                             \
   python/google/protobuf/internal/wire_format.py                             \
   python/google/protobuf/internal/wire_format_test.py                        \
   python/google/protobuf/internal/wire_format_test.py                        \
   python/google/protobuf/internal/__init__.py                                \
   python/google/protobuf/internal/__init__.py                                \
-  python/google/protobuf/internal/import_test_package/BUILD                  \
   python/google/protobuf/internal/import_test_package/__init__.py            \
   python/google/protobuf/internal/import_test_package/__init__.py            \
   python/google/protobuf/internal/import_test_package/inner.proto            \
   python/google/protobuf/internal/import_test_package/inner.proto            \
   python/google/protobuf/internal/import_test_package/outer.proto            \
   python/google/protobuf/internal/import_test_package/outer.proto            \
@@ -203,20 +503,25 @@ python_EXTRA_DIST=                                                           \
   python/google/protobuf/pyext/cpp_message.py                                \
   python/google/protobuf/pyext/cpp_message.py                                \
   python/google/protobuf/pyext/descriptor.h                                  \
   python/google/protobuf/pyext/descriptor.h                                  \
   python/google/protobuf/pyext/descriptor.cc                                 \
   python/google/protobuf/pyext/descriptor.cc                                 \
-  python/google/protobuf/pyext/descriptor_cpp2_test.py                       \
+  python/google/protobuf/pyext/descriptor_pool.h                             \
+  python/google/protobuf/pyext/descriptor_pool.cc                            \
+  python/google/protobuf/pyext/descriptor_containers.h                       \
+  python/google/protobuf/pyext/descriptor_containers.cc                      \
   python/google/protobuf/pyext/extension_dict.h                              \
   python/google/protobuf/pyext/extension_dict.h                              \
   python/google/protobuf/pyext/extension_dict.cc                             \
   python/google/protobuf/pyext/extension_dict.cc                             \
   python/google/protobuf/pyext/message.h                                     \
   python/google/protobuf/pyext/message.h                                     \
   python/google/protobuf/pyext/message.cc                                    \
   python/google/protobuf/pyext/message.cc                                    \
-  python/google/protobuf/pyext/message_factory_cpp2_test.py                  \
+  python/google/protobuf/pyext/message_map_container.cc                      \
+  python/google/protobuf/pyext/message_map_container.h                       \
   python/google/protobuf/pyext/proto2_api_test.proto                         \
   python/google/protobuf/pyext/proto2_api_test.proto                         \
   python/google/protobuf/pyext/python.proto                                  \
   python/google/protobuf/pyext/python.proto                                  \
   python/google/protobuf/pyext/python_protobuf.h                             \
   python/google/protobuf/pyext/python_protobuf.h                             \
-  python/google/protobuf/pyext/reflection_cpp2_generated_test.py             \
   python/google/protobuf/pyext/repeated_composite_container.h                \
   python/google/protobuf/pyext/repeated_composite_container.h                \
   python/google/protobuf/pyext/repeated_composite_container.cc               \
   python/google/protobuf/pyext/repeated_composite_container.cc               \
   python/google/protobuf/pyext/repeated_scalar_container.h                   \
   python/google/protobuf/pyext/repeated_scalar_container.h                   \
   python/google/protobuf/pyext/repeated_scalar_container.cc                  \
   python/google/protobuf/pyext/repeated_scalar_container.cc                  \
+  python/google/protobuf/pyext/scalar_map_container.cc                       \
+  python/google/protobuf/pyext/scalar_map_container.h                        \
   python/google/protobuf/pyext/scoped_pyobject_ptr.h                         \
   python/google/protobuf/pyext/scoped_pyobject_ptr.h                         \
   python/google/protobuf/pyext/__init__.py                                   \
   python/google/protobuf/pyext/__init__.py                                   \
   python/google/protobuf/descriptor.py                                       \
   python/google/protobuf/descriptor.py                                       \
@@ -237,14 +542,18 @@ python_EXTRA_DIST=                                                           \
   python/setup.py                                                            \
   python/setup.py                                                            \
   python/mox.py                                                              \
   python/mox.py                                                              \
   python/stubout.py                                                          \
   python/stubout.py                                                          \
-  python/README.txt
+  python/README.md
 
 
 ruby_EXTRA_DIST=                                                             \
 ruby_EXTRA_DIST=                                                             \
+  ruby/Gemfile                                                               \
+  ruby/Gemfile.lock                                                          \
+  ruby/.gitignore                                                            \
   ruby/README.md                                                             \
   ruby/README.md                                                             \
   ruby/Rakefile                                                              \
   ruby/Rakefile                                                              \
   ruby/ext/google/protobuf_c/defs.c                                          \
   ruby/ext/google/protobuf_c/defs.c                                          \
   ruby/ext/google/protobuf_c/encode_decode.c                                 \
   ruby/ext/google/protobuf_c/encode_decode.c                                 \
   ruby/ext/google/protobuf_c/extconf.rb                                      \
   ruby/ext/google/protobuf_c/extconf.rb                                      \
+  ruby/ext/google/protobuf_c/map.c                                           \
   ruby/ext/google/protobuf_c/message.c                                       \
   ruby/ext/google/protobuf_c/message.c                                       \
   ruby/ext/google/protobuf_c/protobuf.c                                      \
   ruby/ext/google/protobuf_c/protobuf.c                                      \
   ruby/ext/google/protobuf_c/protobuf.h                                      \
   ruby/ext/google/protobuf_c/protobuf.h                                      \
@@ -253,43 +562,65 @@ ruby_EXTRA_DIST=                                                             \
   ruby/ext/google/protobuf_c/upb.c                                           \
   ruby/ext/google/protobuf_c/upb.c                                           \
   ruby/ext/google/protobuf_c/upb.h                                           \
   ruby/ext/google/protobuf_c/upb.h                                           \
   ruby/google-protobuf.gemspec                                               \
   ruby/google-protobuf.gemspec                                               \
+  ruby/lib/google/protobuf/message_exts.rb                                   \
+  ruby/lib/google/protobuf/repeated_field.rb                                 \
   ruby/lib/google/protobuf.rb                                                \
   ruby/lib/google/protobuf.rb                                                \
+  ruby/pom.xml                                                               \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyBuilder.java              \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptor.java           \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java       \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyEnumBuilderContext.java   \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyEnumDescriptor.java       \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java                 \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java      \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java                  \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyMessageBuilderContext.java \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java              \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyOneofBuilderContext.java  \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyOneofDescriptor.java      \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyProtobuf.java             \
+  ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java        \
+  ruby/src/main/java/com/google/protobuf/jruby/SentinelOuterClass.java       \
+  ruby/src/main/java/com/google/protobuf/jruby/Utils.java                    \
+  ruby/src/main/java/google/ProtobufJavaService.java                         \
+  ruby/src/main/sentinel.proto                                               \
   ruby/tests/basic.rb                                                        \
   ruby/tests/basic.rb                                                        \
-  ruby/tests/stress.rb
+  ruby/tests/repeated_field_test.rb                                          \
+  ruby/tests/stress.rb                                                       \
+  ruby/tests/generated_code.proto                                            \
+  ruby/tests/generated_code.rb                                               \
+  ruby/tests/generated_code_test.rb                                          \
+  ruby/travis-test.sh
 
 
-all_EXTRA_DIST=$(java_EXTRA_DIST) $(python_EXTRA_DIST) $(ruby_EXTRA_DIST)
+all_EXTRA_DIST=$(csharp_EXTRA_DIST) $(java_EXTRA_DIST) $(javanano_EXTRA_DIST) $(objectivec_EXTRA_DIST) $(python_EXTRA_DIST) $(ruby_EXTRA_DIST)
 
 
-EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST)                                       \
-  autogen.sh                                                                 \
-  generate_descriptor_proto.sh                                               \
-  README.md                                                                  \
-  INSTALL.txt                                                                \
-  LICENSE                                                                    \
-  CONTRIBUTORS.txt                                                           \
-  CHANGES.txt                                                                \
-  editors/README.txt                                                         \
-  editors/proto.vim                                                          \
-  editors/protobuf-mode.el                                                   \
-  vsprojects/config.h                                                        \
-  vsprojects/extract_includes.bat                                            \
-  vsprojects/libprotobuf.vcproj                                              \
-  vsprojects/libprotobuf-lite.vcproj                                         \
-  vsprojects/libprotoc.vcproj                                                \
-  vsprojects/protobuf.sln                                                    \
-  vsprojects/protoc.vcproj                                                   \
-  vsprojects/readme.txt                                                      \
-  vsprojects/test_plugin.vcproj                                              \
-  vsprojects/tests.vcproj                                                    \
-  vsprojects/lite-test.vcproj                                                \
-  vsprojects/convert2008to2005.sh                                            \
-  examples/README.txt                                                        \
-  examples/Makefile                                                          \
-  examples/addressbook.proto                                                 \
-  examples/add_person.cc                                                     \
-  examples/list_people.cc                                                    \
-  examples/AddPerson.java                                                    \
-  examples/ListPeople.java                                                   \
-  examples/add_person.py                                                     \
+EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST) \
+  autogen.sh                           \
+  generate_descriptor_proto.sh         \
+  README.md                            \
+  INSTALL.txt                          \
+  LICENSE                              \
+  CONTRIBUTORS.txt                     \
+  CHANGES.txt                          \
+  update_file_lists.sh                 \
+  cmake/CMakeLists.txt                 \
+  cmake/libprotobuf.cmake              \
+  cmake/libprotobuf-lite.cmake         \
+  cmake/libprotoc.cmake                \
+  cmake/protoc.cmake                   \
+  cmake/README.md                      \
+  cmake/tests.cmake                    \
+  editors/README.txt                   \
+  editors/proto.vim                    \
+  editors/protobuf-mode.el             \
+  examples/README.txt                  \
+  examples/Makefile                    \
+  examples/addressbook.proto           \
+  examples/add_person.cc               \
+  examples/list_people.cc              \
+  examples/AddPerson.java              \
+  examples/ListPeople.java             \
+  examples/add_person.py               \
   examples/list_people.py
   examples/list_people.py
 
 
 # Deletes all the files generated by autogen.sh.
 # Deletes all the files generated by autogen.sh.

+ 24 - 0
Protobuf.podspec

@@ -0,0 +1,24 @@
+# This file describes to Cocoapods how to integrate the Objective-C runtime into a dependent
+# project.
+# Despite this file being specific to Objective-C, it needs to be on the root of the repository.
+# Otherwise, Cocoapods gives trouble like not picking up the license file correctly, or not letting
+# dependent projects use the :git notation to refer to the library.
+Pod::Spec.new do |s|
+  s.name     = 'Protobuf'
+  s.version  = '3.0.0-alpha-4-pre'
+  s.summary  = 'Protocol Buffers v.3 runtime library for Objective-C.'
+  s.homepage = 'https://github.com/google/protobuf'
+  s.license  = 'New BSD'
+  s.authors  = { 'The Protocol Buffers contributors' => 'protobuf@googlegroups.com' }
+
+  s.source_files = 'objectivec/GPBProtocolBuffers.{h,m}'
+  # GPBProtocolBuffers.{h,m} are umbrella files. We need Cocoapods to preserve the files imported by
+  # them.
+  s.preserve_paths = 'objectivec/*.{h,m}',
+                     'objectivec/google/protobuf/*.pbobjc.{h,m}'
+  s.header_mappings_dir = 'objectivec'
+
+  s.ios.deployment_target = '7.1'
+  s.osx.deployment_target = '10.9'
+  s.requires_arc = false
+end

+ 20 - 4
README.md

@@ -1,7 +1,7 @@
 Protocol Buffers - Google's data interchange format
 Protocol Buffers - Google's data interchange format
 ===================================================
 ===================================================
 
 
-[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf)
+[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf) [![Build status](https://ci.appveyor.com/api/projects/status/73ctee6ua4w2ruin?svg=true)](https://ci.appveyor.com/project/protobuf/protobuf)
 
 
 Copyright 2008 Google Inc.
 Copyright 2008 Google Inc.
 
 
@@ -15,12 +15,12 @@ first:
 
 
     $ ./autogen.sh
     $ ./autogen.sh
 
 
-This will download gtest source (which is used for C++ Protocol Buffer
+This will download gmock source (which is used for C++ Protocol Buffer
 unit-tests) to the current directory and run automake, autoconf, etc.
 unit-tests) to the current directory and run automake, autoconf, etc.
 to generate the configure script and various template makefiles.
 to generate the configure script and various template makefiles.
 
 
 You can skip this step if you are using a release package (which already
 You can skip this step if you are using a release package (which already
-contains gtest and the configure script).
+contains gmock and the configure script).
 
 
 To build and install the C++ Protocol Buffer runtime and the Protocol
 To build and install the C++ Protocol Buffer runtime and the Protocol
 Buffer compiler (protoc) execute the following:
 Buffer compiler (protoc) execute the following:
@@ -88,6 +88,22 @@ For advanced usage information on configure and make, see INSTALL.txt.
   If you only want protobuf-lite, substitute "protobuf-lite" in place
   If you only want protobuf-lite, substitute "protobuf-lite" in place
   of "protobuf" in these examples.
   of "protobuf" in these examples.
 
 
+**Note for Mac users**
+
+  For a Mac system, Unix tools are not available by default. You will first need
+  to install Xcode from the Mac AppStore and then run the following command from
+  a terminal:
+
+    $ sudo xcode-select --install
+
+  To install Unix tools, you can install "port" following the instructions at
+  https://www.macports.org . This will reside in /opt/local/bin/port for most
+  Mac installations.
+
+    $ sudo /opt/local/bin/port install autoconf automake libtool
+
+  Then follow the Unix instructions above.
+
 **Note for cross-compiling**
 **Note for cross-compiling**
 
 
   The makefiles normally invoke the protoc executable that they just
   The makefiles normally invoke the protoc executable that they just
@@ -140,7 +156,7 @@ For advanced usage information on configure and make, see INSTALL.txt.
 C++ Installation - Windows
 C++ Installation - Windows
 --------------------------
 --------------------------
 
 
-If you are using Microsoft Visual C++, see vsprojects/readme.txt.
+If you are using Microsoft Visual C++, see cmake/README.md.
 
 
 If you are using Cygwin or MinGW, follow the Unix installation
 If you are using Cygwin or MinGW, follow the Unix installation
 instructions, above.
 instructions, above.

+ 16 - 0
WORKSPACE

@@ -0,0 +1,16 @@
+new_http_archive(
+  name = "gmock_archive",
+  url = "https://googlemock.googlecode.com/files/gmock-1.7.0.zip",
+  sha256 = "26fcbb5925b74ad5fc8c26b0495dfc96353f4d553492eb97e85a8a6d2f43095b",
+  build_file = "gmock.BUILD",
+)
+
+bind(
+  name = "gtest",
+  actual = "@gmock_archive//:gtest",
+)
+
+bind(
+  name = "gtest_main",
+  actual = "@gmock_archive//:gtest_main",
+)

+ 29 - 0
appveyor.bat

@@ -0,0 +1,29 @@
+setlocal
+
+IF %language%==cpp GOTO build_cpp
+IF %language%==csharp GOTO build_csharp
+
+echo Unsupported language %language%. Exiting.
+goto :error
+
+:build_cpp
+echo Building C++
+mkdir build_msvc
+cd build_msvc
+cmake -G "%generator%" -DBUILD_SHARED_LIBS=%BUILD_DLL% ../cmake
+msbuild protobuf.sln /p:Platform=%vcplatform% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" || goto error
+cd %configuration%
+tests.exe || goto error
+goto :EOF
+
+:build_csharp
+echo Building C#
+cd csharp\src
+nuget restore
+msbuild Google.Protobuf.sln /p:Platform="Any CPU" /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" || goto error
+nunit-console Google.Protobuf.Test\bin\%configuration%\Google.Protobuf.Test.dll || goto error
+goto :EOF
+
+:error
+echo Failed!
+EXIT /b %ERRORLEVEL%

+ 32 - 0
appveyor.yml

@@ -0,0 +1,32 @@
+# Only test one combination: "Visual Studio 12 + Win64 + Debug + DLL". We can
+# test more combinations but AppVeyor just takes too long to finish (each
+# combination takes ~15mins).
+platform:
+  - Win64
+
+configuration:
+  - Debug
+
+environment:
+  matrix:
+    - language: cpp
+      BUILD_DLL: ON
+
+    - language: csharp
+
+install:
+  - ps: Start-FileDownload https://googlemock.googlecode.com/files/gmock-1.7.0.zip
+  - 7z x gmock-1.7.0.zip
+  - rename gmock-1.7.0 gmock
+
+before_build:
+  - if %platform%==Win32 set generator=Visual Studio 12
+  - if %platform%==Win64 set generator=Visual Studio 12 Win64
+  - if %platform%==Win32 set vcplatform=Win32
+  - if %platform%==Win64 set vcplatform=x64
+
+build_script:
+  - CALL appveyor.bat
+
+skip_commits:
+  message: /.*\[skip appveyor\].*/

+ 7 - 16
autogen.sh

@@ -15,27 +15,18 @@ __EOF__
   exit 1
   exit 1
 fi
 fi
 
 
-# Check that gtest is present.  Usually it is already there since the
+# Check that gmock is present.  Usually it is already there since the
 # directory is set up as an SVN external.
 # directory is set up as an SVN external.
-if test ! -e gtest; then
-  echo "Google Test not present.  Fetching gtest-1.7.0 from the web..."
-  curl -O https://googletest.googlecode.com/files/gtest-1.7.0.zip
-  unzip -q gtest-1.7.0.zip
-  rm gtest-1.7.0.zip
-  mv gtest-1.7.0 gtest
+if test ! -e gmock; then
+  echo "Google Mock not present.  Fetching gmock-1.7.0 from the web..."
+  curl -O https://googlemock.googlecode.com/files/gmock-1.7.0.zip
+  unzip -q gmock-1.7.0.zip
+  rm gmock-1.7.0.zip
+  mv gmock-1.7.0 gmock
 fi
 fi
 
 
 set -ex
 set -ex
 
 
-# Temporary hack:  Must change C runtime library to "multi-threaded DLL",
-#   otherwise it will be set to "multi-threaded static" when MSVC upgrades
-#   the project file to MSVC 2005/2008.  vladl of Google Test says gtest will
-#   probably change their default to match, then this will be unnecessary.
-#   One of these mappings converts the debug configuration and the other
-#   converts the release configuration.  I don't know which is which.
-sed -i -e 's/RuntimeLibrary="5"/RuntimeLibrary="3"/g;
-           s/RuntimeLibrary="4"/RuntimeLibrary="2"/g;' gtest/msvc/*.vcproj
-
 # TODO(kenton):  Remove the ",no-obsolete" part and fix the resulting warnings.
 # TODO(kenton):  Remove the ",no-obsolete" part and fix the resulting warnings.
 autoreconf -f -i -Wall,no-obsolete
 autoreconf -f -i -Wall,no-obsolete
 
 

+ 2 - 0
benchmarks/google_size.proto

@@ -1,3 +1,5 @@
+syntax = "proto2";
+
 package benchmarks;
 package benchmarks;
 
 
 option java_outer_classname = "GoogleSize";
 option java_outer_classname = "GoogleSize";

+ 2 - 0
benchmarks/google_speed.proto

@@ -1,3 +1,5 @@
+syntax = "proto2";
+
 package benchmarks;
 package benchmarks;
 
 
 option java_outer_classname = "GoogleSpeed";
 option java_outer_classname = "GoogleSpeed";

+ 91 - 0
cmake/CMakeLists.txt

@@ -0,0 +1,91 @@
+cmake_minimum_required(VERSION 2.8)
+
+project(protobuf C CXX)
+
+option(BUILD_TESTING "Build tests" ON)
+option(BUILD_SHARED_LIBS "Build Shared Libraries" OFF)
+if (MSVC)
+  option(ZLIB "Build with zlib support" OFF)
+endif (MSVC)
+
+add_definitions(-DGOOGLE_PROTOBUF_CMAKE_BUILD)
+
+find_package(Threads REQUIRED)
+if (CMAKE_USE_PTHREADS_INIT)
+  add_definitions(-DHAVE_PTHREAD)
+endif (CMAKE_USE_PTHREADS_INIT)
+
+if (MSVC)
+  if (ZLIB)
+    set(HAVE_ZLIB 1)
+    find_path(ZLIB_INCLUDE_DIRECTORIES zlib.h ${protobuf_SOURCE_DIR})
+    find_library(ZLIB_LIBRARIES zdll ${protobuf_SOURCE_DIR})
+  else (ZLIB)
+    set(HAVE_ZLIB 0)
+  endif (ZLIB)
+else (MSVC)
+  find_package(ZLIB)
+  if (ZLIB_FOUND)
+    set(HAVE_ZLIB 1)
+  else (ZLIB_FOUND)
+    set(HAVE_ZLIB 0)
+    # Explicitly set these to empty (override NOT_FOUND) so cmake doesn't
+    # complain when we use them later.
+    set(ZLIB_INCLUDE_DIRECTORIES)
+    set(ZLIB_LIBRARIES)
+  endif (ZLIB_FOUND)
+endif (MSVC)
+
+if (HAVE_ZLIB)
+  add_definitions(-DHAVE_ZLIB)
+endif (HAVE_ZLIB)
+
+if (MSVC)
+  if (BUILD_SHARED_LIBS)
+    add_definitions(-DPROTOBUF_USE_DLLS)
+  else (BUILD_SHARED_LIBS)
+    # In case we are building static libraries, link also the runtime library statically
+	# so that MSVCR*.DLL is not required at runtime.
+    # https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx
+    # This is achieved by replacing msvc option /MD with /MT and /MDd with /MTd
+    # http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F
+    foreach(flag_var
+        CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+        CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+      if(${flag_var} MATCHES "/MD")
+        string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
+      endif(${flag_var} MATCHES "/MD")
+    endforeach(flag_var)
+  endif (BUILD_SHARED_LIBS)
+  add_definitions(/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305)
+endif (MSVC)
+
+if (MSVC)
+  string(REPLACE "/" "\\" PROTOBUF_SOURCE_WIN32_PATH ${protobuf_SOURCE_DIR})
+  string(REPLACE "/" "\\" PROTOBUF_BINARY_WIN32_PATH ${protobuf_BINARY_DIR})
+  configure_file(extract_includes.bat.in extract_includes.bat)
+endif (MSVC)
+
+get_filename_component(protobuf_source_dir ${protobuf_SOURCE_DIR} PATH)
+
+include_directories(
+  ${ZLIB_INCLUDE_DIRECTORIES}
+  ${protobuf_BINARY_DIR}
+  ${protobuf_source_dir}/src)
+
+if (MSVC)
+  # Add the "lib" prefix for generated .lib outputs.
+  set(LIB_PREFIX lib)
+else (MSVC)
+  # When building with "make", "lib" prefix will be added automatically by
+  # the build tool.
+  set(LIB_PREFIX)
+endif (MSVC)
+
+include(libprotobuf-lite.cmake)
+include(libprotobuf.cmake)
+include(libprotoc.cmake)
+include(protoc.cmake)
+if (BUILD_TESTING)
+  include(tests.cmake)
+endif (BUILD_TESTING)

+ 139 - 0
cmake/README.md

@@ -0,0 +1,139 @@
+This directory contains cmake files that can be used to generate MSVC project
+files in order to build protobuf on windows. You need to have cmake installed
+on your computer before proceeding.
+
+Compiling and Installing
+========================
+
+1. Check whether a gmock directory exists in the upper level directory. If you
+   checkout the code from github via "git clone", this gmock directory won't
+   exist and you won't be able to build protobuf unit-tests. Consider using one
+   of the release tar balls instead:
+
+        https://github.com/google/protobuf/releases
+
+   These release tar balls are more stable versions of protobuf and already
+   have the gmock directory included.
+
+   You can also download gmock by yourself and put it in the right place.
+
+   If you absolutely don't want to build and run protobuf unit-tests, skip
+   this step and use protobuf at your own risk.
+
+2. Use cmake to generate MSVC project files. Running the following commands
+   in a command shell will generate project files for Visual Studio 2008 in
+   a sub-directory named "build".
+
+        $ cd path/to/protobuf/cmake
+        $ mkdir build
+        $ cd build
+        $ cmake -G "Visual Studio 9 2008" ..
+
+   If you don't have gmock, skip the build of tests by turning off the
+   BUILD_TESTING option:
+
+        $ cmake -G "Visual Studio 9 2008" -DBUILD_TESTING=OFF ..
+
+3. Open the generated protobuf.sln file in Microsoft Visual Studio.
+4. Choose "Debug" or "Release" configuration as desired.
+5. From the Build menu, choose "Build Solution".  Wait for compiling to finish.
+6. If you have built tests, run tests.exe and lite-test.exe from a command
+   shell and check that all tests pass. Make sure you have changed the working
+   directory to the output directory because tests.exe will try to find and run
+   test_plugin.exe in the working directory.
+7. Run extract_includes.bat to copy all the public headers into a separate
+   "include" directory. This batch script can be found along with the generated
+   protobuf.sln file in the same directory.
+8. Copy the contents of the include directory to wherever you want to put
+   headers.
+9. Copy protoc.exe wherever you put build tools (probably somewhere in your
+   PATH).
+10. Copy libprotobuf.lib, libprotobuf-lite.lib, and libprotoc.lib wherever you
+    put libraries.
+
+  To avoid conflicts between the MSVC debug and release runtime libraries, when
+  compiling a debug build of your application, you may need to link against a
+  debug build of libprotobuf.lib.  Similarly, release builds should link against
+  release libs.
+
+DLLs vs. static linking
+=======================
+
+Static linking is now the default for the Protocol Buffer libraries.  Due to
+issues with Win32's use of a separate heap for each DLL, as well as binary
+compatibility issues between different versions of MSVC's STL library, it is
+recommended that you use static linkage only.  However, it is possible to
+build libprotobuf and libprotoc as DLLs if you really want.  To do this,
+do the following:
+
+  1. Add an additional flag "-DBUILD_SHARED_LIBS=ON" when invoking cmake:
+
+        $ cmake -G "Visual Studio 9 2008" -DBUILD_SHARED_LIBS=ON ..
+
+  2. Follow the same steps as described in the above section.
+  3. When compiling your project, make sure to #define PROTOBUF_USE_DLLS.
+
+When distributing your software to end users, we strongly recommend that you
+do NOT install libprotobuf.dll or libprotoc.dll to any shared location.
+Instead, keep these libraries next to your binaries, in your application's
+own install directory.  C++ makes it very difficult to maintain binary
+compatibility between releases, so it is likely that future versions of these
+libraries will *not* be usable as drop-in replacements.
+
+If your project is itself a DLL intended for use by third-party software, we
+recommend that you do NOT expose protocol buffer objects in your library's
+public interface, and that you statically link protocol buffers into your
+library.
+
+ZLib support
+============
+
+If you want to include GzipInputStream and GzipOutputStream
+(google/protobuf/io/gzip_stream.h) in libprotobuf, you will need to do a few
+additional steps:
+
+1. Obtain a copy of the zlib library.  The pre-compiled DLL at zlib.net works.
+2. Make sure zlib's two headers are in your include path and that the .lib file
+   is in your library path.  You could place all three files directly into this
+   cmake directory to compile libprotobuf, but they need to be visible to
+   your own project as well, so you should probably just put them into the
+   VC shared icnlude and library directories.
+3. Add flag "-DZLIB=ON" when invoking cmake:
+
+        $ cmake -G "Visual Studio 9 2008" -DZLIB=ON ..
+
+   If it reports NOTFOUND for zlib_include or zlib_lib, you might haven't put
+   the headers or the .lib file in the right directory.
+4) Open the generated protobuf.sln file and build as usual.
+
+Notes on Compiler Warnings
+==========================
+
+The following warnings have been disabled while building the protobuf libraries
+and compiler.  You may have to disable some of them in your own project as
+well, or live with them.
+
+* C4018 - 'expression' : signed/unsigned mismatch
+* C4146 - unary minus operator applied to unsigned type, result still unsigned
+* C4244 - Conversion from 'type1' to 'type2', possible loss of data.
+* C4251 - 'identifier' : class 'type' needs to have dll-interface to be used by
+  clients of class 'type2'
+* C4267 - Conversion from 'size_t' to 'type', possible loss of data.
+* C4305 - 'identifier' : truncation from 'type1' to 'type2'
+* C4355 - 'this' : used in base member initializer list
+* C4800 - 'type' : forcing value to bool 'true' or 'false' (performance warning)
+* C4996 - 'function': was declared deprecated
+
+C4251 is of particular note, if you are compiling the Protocol Buffer library
+as a DLL (see previous section).  The protocol buffer library uses templates in
+its public interfaces.  MSVC does not provide any reasonable way to export
+template classes from a DLL.  However, in practice, it appears that exporting
+templates is not necessary anyway.  Since the complete definition of any
+template is available in the header files, anyone importing the DLL will just
+end up compiling instances of the templates into their own binary.  The
+Protocol Buffer implementation does not rely on static template members being
+unique, so there should be no problem with this, but MSVC prints warning
+nevertheless.  So, we disable it.  Unfortunately, this warning will also be
+produced when compiling code which merely uses protocol buffers, meaning you
+may have to disable it in your code too.
+

+ 120 - 0
cmake/extract_includes.bat.in

@@ -0,0 +1,120 @@
+mkdir include
+mkdir include\google
+mkdir include\google\protobuf
+mkdir include\google\protobuf\compiler
+mkdir include\google\protobuf\compiler\cpp
+mkdir include\google\protobuf\compiler\csharp
+mkdir include\google\protobuf\compiler\java
+mkdir include\google\protobuf\compiler\javanano
+mkdir include\google\protobuf\compiler\objectivec
+mkdir include\google\protobuf\compiler\python
+mkdir include\google\protobuf\compiler\ruby
+mkdir include\google\protobuf\io
+mkdir include\google\protobuf\stubs
+mkdir include\google\protobuf\util
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\any.h include\google\protobuf\any.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\any.pb.h include\google\protobuf\any.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\api.pb.h include\google\protobuf\api.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arena.h include\google\protobuf\arena.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arenastring.h include\google\protobuf\arenastring.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\code_generator.h include\google\protobuf\compiler\code_generator.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\command_line_interface.h include\google\protobuf\compiler\command_line_interface.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\cpp_generator.h include\google\protobuf\compiler\cpp\cpp_generator.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_generator.h include\google\protobuf\compiler\csharp\csharp_generator.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_names.h include\google\protobuf\compiler\csharp\csharp_names.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\importer.h include\google\protobuf\compiler\importer.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_generator.h include\google\protobuf\compiler\java\java_generator.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_names.h include\google\protobuf\compiler\java\java_names.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\javanano\javanano_generator.h include\google\protobuf\compiler\javanano\javanano_generator.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\objectivec\objectivec_generator.h include\google\protobuf\compiler\objectivec\objectivec_generator.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\objectivec\objectivec_helpers.h include\google\protobuf\compiler\objectivec\objectivec_helpers.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\parser.h include\google\protobuf\compiler\parser.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.h include\google\protobuf\compiler\plugin.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.pb.h include\google\protobuf\compiler\plugin.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\python\python_generator.h include\google\protobuf\compiler\python\python_generator.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\ruby\ruby_generator.h include\google\protobuf\compiler\ruby\ruby_generator.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor.h include\google\protobuf\descriptor.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor.pb.h include\google\protobuf\descriptor.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor_database.h include\google\protobuf\descriptor_database.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\duration.pb.h include\google\protobuf\duration.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\dynamic_message.h include\google\protobuf\dynamic_message.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\empty.pb.h include\google\protobuf\empty.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\extension_set.h include\google\protobuf\extension_set.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\field_mask.pb.h include\google\protobuf\field_mask.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_enum_reflection.h include\google\protobuf\generated_enum_reflection.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_enum_util.h include\google\protobuf\generated_enum_util.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_reflection.h include\google\protobuf\generated_message_reflection.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_util.h include\google\protobuf\generated_message_util.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\coded_stream.h include\google\protobuf\io\coded_stream.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\gzip_stream.h include\google\protobuf\io\gzip_stream.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\printer.h include\google\protobuf\io\printer.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\strtod.h include\google\protobuf\io\strtod.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\tokenizer.h include\google\protobuf\io\tokenizer.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\zero_copy_stream.h include\google\protobuf\io\zero_copy_stream.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\zero_copy_stream_impl.h include\google\protobuf\io\zero_copy_stream_impl.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\zero_copy_stream_impl_lite.h include\google\protobuf\io\zero_copy_stream_impl_lite.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map.h include\google\protobuf\map.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_entry.h include\google\protobuf\map_entry.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_entry_lite.h include\google\protobuf\map_entry_lite.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_field.h include\google\protobuf\map_field.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_field_inl.h include\google\protobuf\map_field_inl.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_field_lite.h include\google\protobuf\map_field_lite.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_type_handler.h include\google\protobuf\map_type_handler.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\message.h include\google\protobuf\message.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\message_lite.h include\google\protobuf\message_lite.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\metadata.h include\google\protobuf\metadata.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\reflection.h include\google\protobuf\reflection.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\reflection_ops.h include\google\protobuf\reflection_ops.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\repeated_field.h include\google\protobuf\repeated_field.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\repeated_field_reflection.h include\google\protobuf\repeated_field_reflection.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\service.h include\google\protobuf\service.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\source_context.pb.h include\google\protobuf\source_context.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\struct.pb.h include\google\protobuf\struct.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomic_sequence_num.h include\google\protobuf\stubs\atomic_sequence_num.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops.h include\google\protobuf\stubs\atomicops.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_aix.h include\google\protobuf\stubs\atomicops_internals_aix.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_arm64_gcc.h include\google\protobuf\stubs\atomicops_internals_arm64_gcc.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_arm_gcc.h include\google\protobuf\stubs\atomicops_internals_arm_gcc.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_arm_qnx.h include\google\protobuf\stubs\atomicops_internals_arm_qnx.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_atomicword_compat.h include\google\protobuf\stubs\atomicops_internals_atomicword_compat.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_generic_gcc.h include\google\protobuf\stubs\atomicops_internals_generic_gcc.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_macosx.h include\google\protobuf\stubs\atomicops_internals_macosx.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_mips_gcc.h include\google\protobuf\stubs\atomicops_internals_mips_gcc.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_pnacl.h include\google\protobuf\stubs\atomicops_internals_pnacl.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_solaris.h include\google\protobuf\stubs\atomicops_internals_solaris.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_tsan.h include\google\protobuf\stubs\atomicops_internals_tsan.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_x86_gcc.h include\google\protobuf\stubs\atomicops_internals_x86_gcc.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\atomicops_internals_x86_msvc.h include\google\protobuf\stubs\atomicops_internals_x86_msvc.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\bytestream.h include\google\protobuf\stubs\bytestream.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\callback.h include\google\protobuf\stubs\callback.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\casts.h include\google\protobuf\stubs\casts.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\common.h include\google\protobuf\stubs\common.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\fastmem.h include\google\protobuf\stubs\fastmem.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\hash.h include\google\protobuf\stubs\hash.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\logging.h include\google\protobuf\stubs\logging.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\macros.h include\google\protobuf\stubs\macros.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\mutex.h include\google\protobuf\stubs\mutex.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\once.h include\google\protobuf\stubs\once.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\platform_macros.h include\google\protobuf\stubs\platform_macros.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\port.h include\google\protobuf\stubs\port.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\scoped_ptr.h include\google\protobuf\stubs\scoped_ptr.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\shared_ptr.h include\google\protobuf\stubs\shared_ptr.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\singleton.h include\google\protobuf\stubs\singleton.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\status.h include\google\protobuf\stubs\status.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\stl_util.h include\google\protobuf\stubs\stl_util.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\stringpiece.h include\google\protobuf\stubs\stringpiece.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\template_util.h include\google\protobuf\stubs\template_util.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\type_traits.h include\google\protobuf\stubs\type_traits.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\text_format.h include\google\protobuf\text_format.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\timestamp.pb.h include\google\protobuf\timestamp.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\type.pb.h include\google\protobuf\type.pb.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\unknown_field_set.h include\google\protobuf\unknown_field_set.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\field_comparator.h include\google\protobuf\util\field_comparator.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\json_util.h include\google\protobuf\util\json_util.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\message_differencer.h include\google\protobuf\util\message_differencer.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\type_resolver.h include\google\protobuf\util\type_resolver.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\type_resolver_util.h include\google\protobuf\util\type_resolver_util.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format.h include\google\protobuf\wire_format.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format_lite.h include\google\protobuf\wire_format_lite.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format_lite_inl.h include\google\protobuf\wire_format_lite_inl.h
+copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wrappers.pb.h include\google\protobuf\wrappers.pb.h

+ 30 - 0
cmake/libprotobuf-lite.cmake

@@ -0,0 +1,30 @@
+set(libprotobuf_lite_files
+  ${protobuf_source_dir}/src/google/protobuf/arena.cc
+  ${protobuf_source_dir}/src/google/protobuf/arenastring.cc
+  ${protobuf_source_dir}/src/google/protobuf/extension_set.cc
+  ${protobuf_source_dir}/src/google/protobuf/generated_message_util.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/coded_stream.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/message_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/repeated_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/bytestream.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/common.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/once.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/status.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/statusor.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/stringpiece.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/stringprintf.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/strutil.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/time.cc
+  ${protobuf_source_dir}/src/google/protobuf/wire_format_lite.cc
+)
+
+add_library(libprotobuf-lite ${libprotobuf_lite_files})
+target_link_libraries(libprotobuf-lite ${CMAKE_THREAD_LIBS_INIT})
+target_include_directories(libprotobuf-lite PUBLIC ${protobuf_source_dir}/src)
+set_target_properties(libprotobuf-lite PROPERTIES
+    COMPILE_DEFINITIONS LIBPROTOBUF_EXPORTS
+    OUTPUT_NAME ${LIB_PREFIX}protobuf-lite)

+ 60 - 0
cmake/libprotobuf.cmake

@@ -0,0 +1,60 @@
+set(libprotobuf_files
+  ${protobuf_source_dir}/src/google/protobuf/any.cc
+  ${protobuf_source_dir}/src/google/protobuf/any.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/api.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/importer.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/parser.cc
+  ${protobuf_source_dir}/src/google/protobuf/descriptor.cc
+  ${protobuf_source_dir}/src/google/protobuf/descriptor.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/descriptor_database.cc
+  ${protobuf_source_dir}/src/google/protobuf/duration.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/dynamic_message.cc
+  ${protobuf_source_dir}/src/google/protobuf/empty.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/extension_set_heavy.cc
+  ${protobuf_source_dir}/src/google/protobuf/field_mask.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/generated_message_reflection.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/gzip_stream.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/printer.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/strtod.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/tokenizer.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl.cc
+  ${protobuf_source_dir}/src/google/protobuf/map_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/message.cc
+  ${protobuf_source_dir}/src/google/protobuf/reflection_ops.cc
+  ${protobuf_source_dir}/src/google/protobuf/service.cc
+  ${protobuf_source_dir}/src/google/protobuf/source_context.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/struct.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/mathlimits.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/structurally_valid.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/substitute.cc
+  ${protobuf_source_dir}/src/google/protobuf/text_format.cc
+  ${protobuf_source_dir}/src/google/protobuf/timestamp.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/type.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/unknown_field_set.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/field_comparator.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/datapiece.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/default_value_objectwriter.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/error_listener.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/field_mask_utility.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/json_escaping.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/json_objectwriter.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/json_stream_parser.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/object_writer.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/protostream_objectsource.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/protostream_objectwriter.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/type_info.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/type_info_test_helper.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/utility.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/json_util.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/message_differencer.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/type_resolver_util.cc
+  ${protobuf_source_dir}/src/google/protobuf/wire_format.cc
+  ${protobuf_source_dir}/src/google/protobuf/wrappers.pb.cc
+)
+
+add_library(libprotobuf ${libprotobuf_lite_files} ${libprotobuf_files})
+target_link_libraries(libprotobuf ${CMAKE_THREAD_LIBS_INIT} ${ZLIB_LIBRARIES})
+target_include_directories(libprotobuf PUBLIC ${protobuf_source_dir}/src)
+set_target_properties(libprotobuf PROPERTIES
+    COMPILE_DEFINITIONS LIBPROTOBUF_EXPORTS
+    OUTPUT_NAME ${LIB_PREFIX}protobuf)

+ 95 - 0
cmake/libprotoc.cmake

@@ -0,0 +1,95 @@
+set(libprotoc_files
+  ${protobuf_source_dir}/src/google/protobuf/compiler/code_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/command_line_interface.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_enum.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_extension.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_file.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_map_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_service.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_enum.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
+  ${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
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_context.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_doc_comment.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_enum.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_enum_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_enum_field_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_extension.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_file.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_generator_factory.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_helpers.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_lazy_message_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_map_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_map_field_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message_builder.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message_builder_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message_field_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_message_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_name_resolver.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_primitive_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_service.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_shared_code_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_string_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_string_field_lite.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_enum.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_extension.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_file.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_helpers.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_map_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_message.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_message_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_file.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_message.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/plugin.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/plugin.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/python/python_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/ruby/ruby_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/subprocess.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/zip_writer.cc
+)
+
+add_library(libprotoc ${libprotoc_files})
+target_link_libraries(libprotoc libprotobuf)
+set_target_properties(libprotoc PROPERTIES
+    COMPILE_DEFINITIONS LIBPROTOC_EXPORTS
+    OUTPUT_NAME ${LIB_PREFIX}protoc)

+ 6 - 0
cmake/protoc.cmake

@@ -0,0 +1,6 @@
+set(protoc_files
+  ${protobuf_source_dir}/src/google/protobuf/compiler/main.cc
+)
+
+add_executable(protoc ${protoc_files})
+target_link_libraries(protoc libprotobuf libprotoc)

+ 182 - 0
cmake/tests.cmake

@@ -0,0 +1,182 @@
+if (NOT EXISTS "${PROJECT_SOURCE_DIR}/../gmock/CMakeLists.txt")
+  message(FATAL_ERROR "Cannot find gmock directory.")
+endif()
+
+include_directories(
+  ${protobuf_source_dir}/gmock
+  ${protobuf_source_dir}/gmock/gtest
+  ${protobuf_source_dir}/gmock/gtest/include
+  ${protobuf_source_dir}/gmock/include
+)
+
+add_library(gmock STATIC
+  ${protobuf_source_dir}/gmock/src/gmock-all.cc
+  ${protobuf_source_dir}/gmock/gtest/src/gtest-all.cc
+)
+add_library(gmock_main STATIC ${protobuf_source_dir}/gmock/src/gmock_main.cc)
+target_link_libraries(gmock_main gmock)
+
+set(lite_test_protos
+  google/protobuf/map_lite_unittest.proto
+  google/protobuf/unittest_import_lite.proto
+  google/protobuf/unittest_import_public_lite.proto
+  google/protobuf/unittest_lite.proto
+)
+
+set(tests_protos
+  google/protobuf/any_test.proto
+  google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
+  google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto
+  google/protobuf/map_proto2_unittest.proto
+  google/protobuf/map_unittest.proto
+  google/protobuf/unittest.proto
+  google/protobuf/unittest_arena.proto
+  google/protobuf/unittest_custom_options.proto
+  google/protobuf/unittest_drop_unknown_fields.proto
+  google/protobuf/unittest_embed_optimize_for.proto
+  google/protobuf/unittest_empty.proto
+  google/protobuf/unittest_enormous_descriptor.proto
+  google/protobuf/unittest_import.proto
+  google/protobuf/unittest_import_public.proto
+  google/protobuf/unittest_lite_imports_nonlite.proto
+  google/protobuf/unittest_mset.proto
+  google/protobuf/unittest_no_arena.proto
+  google/protobuf/unittest_no_arena_import.proto
+  google/protobuf/unittest_no_field_presence.proto
+  google/protobuf/unittest_no_generic_services.proto
+  google/protobuf/unittest_optimize_for.proto
+  google/protobuf/unittest_preserve_unknown_enum.proto
+  google/protobuf/unittest_preserve_unknown_enum2.proto
+  google/protobuf/unittest_proto3_arena.proto
+  google/protobuf/unittest_well_known_types.proto
+  google/protobuf/util/internal/testdata/anys.proto
+  google/protobuf/util/internal/testdata/books.proto
+  google/protobuf/util/internal/testdata/default_value.proto
+  google/protobuf/util/internal/testdata/default_value_test.proto
+  google/protobuf/util/internal/testdata/field_mask.proto
+  google/protobuf/util/internal/testdata/maps.proto
+  google/protobuf/util/internal/testdata/struct.proto
+  google/protobuf/util/internal/testdata/timestamp_duration.proto
+  google/protobuf/util/json_format_proto3.proto
+)
+
+macro(compile_proto_file filename)
+  get_filename_component(dirname ${filename} PATH)
+  get_filename_component(basename ${filename} NAME_WE)
+  add_custom_command(
+    OUTPUT ${protobuf_source_dir}/src/${dirname}/${basename}.pb.cc
+    DEPENDS protoc ${protobuf_source_dir}/src/${dirname}/${basename}.proto
+    COMMAND protoc ${protobuf_source_dir}/src/${dirname}/${basename}.proto
+        --proto_path=${protobuf_source_dir}/src
+        --cpp_out=${protobuf_source_dir}/src
+  )
+endmacro(compile_proto_file)
+
+set(lite_test_proto_files)
+foreach(proto_file ${lite_test_protos})
+  compile_proto_file(${proto_file})
+  string(REPLACE .proto .pb.cc pb_file ${proto_file})
+  set(lite_test_proto_files ${lite_test_proto_files}
+      ${protobuf_source_dir}/src/${pb_file})
+endforeach(proto_file)
+
+set(tests_proto_files)
+foreach(proto_file ${tests_protos})
+  compile_proto_file(${proto_file})
+  string(REPLACE .proto .pb.cc pb_file ${proto_file})
+  set(tests_proto_files ${tests_proto_files}
+      ${protobuf_source_dir}/src/${pb_file})
+endforeach(proto_file)
+
+set(common_test_files
+  ${protobuf_source_dir}/src/google/protobuf/arena_test_util.cc
+  ${protobuf_source_dir}/src/google/protobuf/map_test_util.cc
+  ${protobuf_source_dir}/src/google/protobuf/test_util.cc
+  ${protobuf_source_dir}/src/google/protobuf/testing/file.cc
+  ${protobuf_source_dir}/src/google/protobuf/testing/googletest.cc
+)
+
+set(tests_files
+  ${protobuf_source_dir}/src/google/protobuf/any_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/arena_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/arenastring_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/command_line_interface_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/importer_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/java/java_plugin_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/mock_code_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/parser_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/python/python_plugin_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/descriptor_database_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/descriptor_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/drop_unknown_fields_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/dynamic_message_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/extension_set_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/generated_message_reflection_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/coded_stream_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/printer_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/tokenizer_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/map_field_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/map_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/message_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/no_field_presence_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/preserve_unknown_enum_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/proto3_arena_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/reflection_ops_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/repeated_field_reflection_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/repeated_field_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/bytestream_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/common_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/once_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/status_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/statusor_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/stringpiece_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/stringprintf_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/structurally_valid_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/strutil_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/template_util_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/time_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/type_traits_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/text_format_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/unknown_field_set_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/field_comparator_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/json_objectwriter_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/json_stream_parser_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/protostream_objectsource_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/internal/type_info_test_helper.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/json_util_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/util/type_resolver_util_test.cc
+  ${protobuf_source_dir}/src/google/protobuf/well_known_types_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/wire_format_unittest.cc
+)
+
+add_executable(tests ${tests_files} ${common_test_files} ${tests_proto_files} ${lite_test_proto_files})
+target_link_libraries(tests libprotoc libprotobuf gmock_main)
+
+set(test_plugin_files
+  ${protobuf_source_dir}/src/google/protobuf/compiler/mock_code_generator.cc
+  ${protobuf_source_dir}/src/google/protobuf/testing/file.cc
+  ${protobuf_source_dir}/src/google/protobuf/testing/file.h
+  ${protobuf_source_dir}/src/google/protobuf/compiler/test_plugin.cc
+)
+
+add_executable(test_plugin ${test_plugin_files})
+target_link_libraries(test_plugin libprotoc libprotobuf gmock)
+
+set(lite_test_files
+  ${protobuf_source_dir}/src/google/protobuf/arena_test_util.cc
+  ${protobuf_source_dir}/src/google/protobuf/lite_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/map_lite_test_util.cc
+  ${protobuf_source_dir}/src/google/protobuf/test_util_lite.cc
+)
+add_executable(lite-test ${lite_test_files} ${lite_test_proto_files})
+target_link_libraries(lite-test libprotobuf-lite)

+ 14 - 8
configure.ac

@@ -12,18 +12,21 @@ AC_PREREQ(2.59)
 # In the SVN trunk, the version should always be the next anticipated release
 # In the SVN trunk, the version should always be the next anticipated release
 # version with the "-pre" suffix.  (We used to use "-SNAPSHOT" but this pushed
 # version with the "-pre" suffix.  (We used to use "-SNAPSHOT" but this pushed
 # the size of one file name in the dist tarfile over the 99-char limit.)
 # the size of one file name in the dist tarfile over the 99-char limit.)
-AC_INIT([Protocol Buffers],[3.0.0-pre],[protobuf@googlegroups.com],[protobuf])
+AC_INIT([Protocol Buffers],[3.0.0-alpha-4-pre],[protobuf@googlegroups.com],[protobuf])
 
 
 AM_MAINTAINER_MODE([enable])
 AM_MAINTAINER_MODE([enable])
 
 
 AC_CONFIG_SRCDIR(src/google/protobuf/message.cc)
 AC_CONFIG_SRCDIR(src/google/protobuf/message.cc)
+# The config file is generated but not used by the source code, since we only
+# need very few of them, e.g. HAVE_PTHREAD and HAVE_ZLIB. Those macros are
+# passed down in CXXFLAGS manually in src/Makefile.am
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_MACRO_DIR([m4])
 AC_CONFIG_MACRO_DIR([m4])
 
 
 AC_ARG_VAR(DIST_LANG, [language to include in the distribution package (i.e., make dist)])
 AC_ARG_VAR(DIST_LANG, [language to include in the distribution package (i.e., make dist)])
 case "$DIST_LANG" in
 case "$DIST_LANG" in
   "") DIST_LANG=all ;;
   "") DIST_LANG=all ;;
-  all | cpp | java | python | javanano | ruby) ;;
+  all | cpp | csharp | java | python | javanano | objectivec | ruby) ;;
   *) AC_MSG_FAILURE([unknown language: $DIST_LANG]) ;;
   *) AC_MSG_FAILURE([unknown language: $DIST_LANG]) ;;
 esac
 esac
 AC_SUBST(DIST_LANG)
 AC_SUBST(DIST_LANG)
@@ -37,7 +40,7 @@ AS_IF([test "x${ac_cv_env_CXXFLAGS_set}" = "x"],
 
 
 AC_CANONICAL_TARGET
 AC_CANONICAL_TARGET
 
 
-AM_INIT_AUTOMAKE([subdir-objects])
+AM_INIT_AUTOMAKE([1.9 tar-ustar subdir-objects])
 
 
 AC_ARG_WITH([zlib],
 AC_ARG_WITH([zlib],
   [AS_HELP_STRING([--with-zlib],
   [AS_HELP_STRING([--with-zlib],
@@ -54,7 +57,7 @@ AC_PROG_CC
 AC_PROG_CXX
 AC_PROG_CXX
 AC_LANG([C++])
 AC_LANG([C++])
 ACX_USE_SYSTEM_EXTENSIONS
 ACX_USE_SYSTEM_EXTENSIONS
-AM_PROG_AR
+m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
 AM_CONDITIONAL(GCC, test "$GCC" = yes)   # let the Makefile know if we're gcc
 AM_CONDITIONAL(GCC, test "$GCC" = yes)   # let the Makefile know if we're gcc
 
 
 # test_util.cc takes forever to compile with GCC and optimization turned on.
 # test_util.cc takes forever to compile with GCC and optimization turned on.
@@ -146,6 +149,9 @@ AS_IF([test "$with_protoc" != "no"], [
 AM_CONDITIONAL([USE_EXTERNAL_PROTOC], [test "$with_protoc" != "no"])
 AM_CONDITIONAL([USE_EXTERNAL_PROTOC], [test "$with_protoc" != "no"])
 
 
 ACX_PTHREAD
 ACX_PTHREAD
+AM_CONDITIONAL([HAVE_PTHREAD], [test "x$acx_pthread_ok" = "xyes"])
+
+# We still keep this for improving pbconfig.h for unsupported platforms.
 AC_CXX_STL_HASH
 AC_CXX_STL_HASH
 
 
 case "$target_os" in
 case "$target_os" in
@@ -157,12 +163,12 @@ case "$target_os" in
     ;;
     ;;
 esac
 esac
 
 
-# HACK:  Make gtest's configure script pick up our copy of CFLAGS and CXXFLAGS,
-#   since the flags added by ACX_CHECK_SUNCC must be used when compiling gtest
+# HACK:  Make gmock's configure script pick up our copy of CFLAGS and CXXFLAGS,
+#   since the flags added by ACX_CHECK_SUNCC must be used when compiling gmock
 #   too.
 #   too.
 export CFLAGS
 export CFLAGS
 export CXXFLAGS
 export CXXFLAGS
-AC_CONFIG_SUBDIRS([gtest])
+AC_CONFIG_SUBDIRS([gmock])
 
 
-AC_CONFIG_FILES([Makefile src/Makefile protobuf.pc protobuf-lite.pc])
+AC_CONFIG_FILES([Makefile src/Makefile conformance/Makefile protobuf.pc protobuf-lite.pc])
 AC_OUTPUT
 AC_OUTPUT

+ 120 - 0
conformance/ConformanceJava.java

@@ -0,0 +1,120 @@
+
+import com.google.protobuf.conformance.Conformance;
+import com.google.protobuf.InvalidProtocolBufferException;
+
+class ConformanceJava {
+  private int testCount = 0;
+
+  private boolean readFromStdin(byte[] buf, int len) throws Exception {
+    int ofs = 0;
+    while (len > 0) {
+      int read = System.in.read(buf, ofs, len);
+      if (read == -1) {
+        return false;  // EOF
+      }
+      ofs += read;
+      len -= read;
+    }
+
+    return true;
+  }
+
+  private void writeToStdout(byte[] buf) throws Exception {
+    System.out.write(buf);
+  }
+
+  // Returns -1 on EOF (the actual values will always be positive).
+  private int readLittleEndianIntFromStdin() throws Exception {
+    byte[] buf = new byte[4];
+    if (!readFromStdin(buf, 4)) {
+      return -1;
+    }
+    return buf[0] | (buf[1] << 1) | (buf[2] << 2) | (buf[3] << 3);
+  }
+
+  private void writeLittleEndianIntToStdout(int val) throws Exception {
+    byte[] buf = new byte[4];
+    buf[0] = (byte)val;
+    buf[1] = (byte)(val >> 8);
+    buf[2] = (byte)(val >> 16);
+    buf[3] = (byte)(val >> 24);
+    writeToStdout(buf);
+  }
+
+  private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) {
+    Conformance.TestAllTypes testMessage;
+
+    switch (request.getPayloadCase()) {
+      case PROTOBUF_PAYLOAD: {
+        try {
+          testMessage = Conformance.TestAllTypes.parseFrom(request.getProtobufPayload());
+        } catch (InvalidProtocolBufferException e) {
+          return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
+        }
+        break;
+      }
+      case JSON_PAYLOAD: {
+        return Conformance.ConformanceResponse.newBuilder().setSkipped("JSON not yet supported.").build();
+      }
+      case PAYLOAD_NOT_SET: {
+        throw new RuntimeException("Request didn't have payload.");
+      }
+
+      default: {
+        throw new RuntimeException("Unexpected payload case.");
+      }
+    }
+
+    switch (request.getRequestedOutputFormat()) {
+      case UNSPECIFIED:
+        throw new RuntimeException("Unspecified output format.");
+
+      case PROTOBUF:
+        return Conformance.ConformanceResponse.newBuilder().setProtobufPayload(testMessage.toByteString()).build();
+
+      case JSON:
+        return Conformance.ConformanceResponse.newBuilder().setSkipped("JSON not yet supported.").build();
+
+      default: {
+        throw new RuntimeException("Unexpected request output.");
+      }
+    }
+  }
+
+  private boolean doTestIo() throws Exception {
+    int bytes = readLittleEndianIntFromStdin();
+
+    if (bytes == -1) {
+      return false;  // EOF
+    }
+
+    byte[] serializedInput = new byte[bytes];
+
+    if (!readFromStdin(serializedInput, bytes)) {
+      throw new RuntimeException("Unexpected EOF from test program.");
+    }
+
+    Conformance.ConformanceRequest request =
+        Conformance.ConformanceRequest.parseFrom(serializedInput);
+    Conformance.ConformanceResponse response = doTest(request);
+    byte[] serializedOutput = response.toByteArray();
+
+    writeLittleEndianIntToStdout(serializedOutput.length);
+    writeToStdout(serializedOutput);
+
+    return true;
+  }
+
+  public void run() throws Exception {
+    while (doTestIo()) {
+      // Empty.
+    }
+
+    System.err.println("ConformanceJava: received EOF from test runner after " +
+        this.testCount + " tests");
+  }
+
+  public static void main(String[] args) throws Exception {
+    new ConformanceJava().run();
+  }
+}

+ 78 - 0
conformance/Makefile.am

@@ -0,0 +1,78 @@
+## Process this file with automake to produce Makefile.in
+
+protoc_inputs =                                                \
+  conformance.proto
+
+protoc_outputs =                                               \
+  conformance.pb.cc                                            \
+  conformance.pb.h
+
+bin_PROGRAMS = conformance-test-runner conformance-cpp
+
+conformance_test_runner_LDADD = $(top_srcdir)/src/libprotobuf.la
+conformance_test_runner_SOURCES = conformance_test.cc conformance_test_runner.cc
+nodist_conformance_test_runner_SOURCES = conformance.pb.cc
+conformance_test_runner_CPPFLAGS = -I$(top_srcdir)/src
+
+conformance_cpp_LDADD = $(top_srcdir)/src/libprotobuf.la
+conformance_cpp_SOURCES = conformance_cpp.cc
+nodist_conformance_cpp_SOURCES = conformance.pb.cc
+conformance_cpp_CPPFLAGS = -I$(top_srcdir)/src
+
+if USE_EXTERNAL_PROTOC
+
+protoc_middleman: $(protoc_inputs)
+	$(PROTOC) -I$(srcdir) --cpp_out=. --java_out=. --ruby_out=. $^
+	touch protoc_middleman
+
+else
+
+# We have to cd to $(srcdir) before executing protoc because $(protoc_inputs) is
+# relative to srcdir, which may not be the same as the current directory when
+# building out-of-tree.
+protoc_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(protoc_inputs)
+	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd $(protoc_inputs) )
+	touch protoc_middleman
+
+endif
+
+$(protoc_outputs): protoc_middleman
+
+BUILT_SOURCES = $(protoc_outputs)
+
+CLEANFILES = $(protoc_outputs) protoc_middleman javac_middleman conformance-java conformance-csharp
+
+MAINTAINERCLEANFILES =   \
+  Makefile.in
+
+javac_middleman: ConformanceJava.java protoc_middleman
+	javac -classpath ../java/target/classes ConformanceJava.java com/google/protobuf/conformance/Conformance.java
+	@touch javac_middleman
+
+conformance-java: javac_middleman
+	@echo "Writing shortcut script conformance-java..."
+	@echo '#! /bin/sh' > conformance-java
+	@echo 'java -classpath .:../java/target/classes ConformanceJava "$$@"' >> conformance-java
+	@chmod +x conformance-java
+
+# Currently the conformance code is alongside the rest of the C#
+# source, as it's easier to maintain there. We assume we've already
+# built that, so we just need a script to run it.
+conformance-csharp:
+	@echo "Writing shortcut script conformance-csharp..."
+	@echo '#! /bin/sh' > conformance-csharp
+	@echo 'mono ../csharp/src/Google.Protobuf.Conformance/bin/Release/Google.Protobuf.Conformance.exe "$$@"' >> conformance-csharp
+	@chmod +x conformance-csharp
+
+# Targets for actually running tests.
+test_cpp: protoc_middleman conformance-test-runner conformance-cpp
+	./conformance-test-runner --failure_list failure_list_cpp.txt ./conformance-cpp
+
+test_java: protoc_middleman conformance-test-runner conformance-java
+	./conformance-test-runner ./conformance-java
+
+test_csharp: protoc_middleman conformance-test-runner conformance-csharp
+	./conformance-test-runner --failure_list failure_list_csharp.txt ./conformance-csharp
+
+test_ruby: protoc_middleman conformance-test-runner
+	RUBYLIB=../ruby/lib:. ./conformance-test-runner --failure_list failure_list_ruby.txt ./conformance_ruby.rb

+ 45 - 0
conformance/README.md

@@ -0,0 +1,45 @@
+Protocol Buffers - Google's data interchange format
+===================================================
+
+[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf)
+
+Copyright 2008 Google Inc.
+
+This directory contains conformance tests for testing completeness and
+correctness of Protocol Buffers implementations.  These tests are designed
+to be easy to run against any Protocol Buffers implementation.
+
+This directory contains the tester process `conformance-test`, which
+contains all of the tests themselves.  Then separate programs written
+in whatever language you want to test communicate with the tester
+program over a pipe.
+
+Before running any of these tests, make sure you run `make` in the base
+directory to build `protoc`, since all the tests depend on it.
+
+    $ make
+
+Then to run the tests against the C++ implementation, run:
+
+    $ cd conformance && make test_cpp
+
+More tests and languages will be added soon!
+
+Testing other Protocol Buffer implementations
+---------------------------------------------
+
+To run these tests against a new Protocol Buffers implementation, write a
+program in your language that uses the protobuf implementation you want
+to test.  This program should implement the testing protocol defined in
+[conformance.proto](https://github.com/google/protobuf/blob/master/conformance/conformance.proto).
+This is designed to be as easy as possible: the C++ version is only
+150 lines and is a good example for what this program should look like
+(see [conformance_cpp.cc](https://github.com/google/protobuf/blob/master/conformance/conformance_cpp.cc)).
+The program only needs to be able to read from stdin and write to stdout.
+
+Portability
+-----------
+
+Note that the test runner currently does not work on Windows.  Patches
+to fix this are welcome!  (But please get in touch first to settle on
+a general implementation strategy).

+ 212 - 0
conformance/conformance.proto

@@ -0,0 +1,212 @@
+// 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.
+
+syntax = "proto3";
+package conformance;
+option java_package = "com.google.protobuf.conformance";
+
+// This defines the conformance testing protocol.  This protocol exists between
+// the conformance test suite itself and the code being tested.  For each test,
+// the suite will send a ConformanceRequest message and expect a
+// ConformanceResponse message.
+//
+// You can either run the tests in two different ways:
+//
+//   1. in-process (using the interface in conformance_test.h).
+//
+//   2. as a sub-process communicating over a pipe.  Information about how to
+//      do this is in conformance_test_runner.cc.
+//
+// Pros/cons of the two approaches:
+//
+//   - running as a sub-process is much simpler for languages other than C/C++.
+//
+//   - running as a sub-process may be more tricky in unusual environments like
+//     iOS apps, where fork/stdin/stdout are not available.
+
+enum WireFormat {
+  UNSPECIFIED = 0;
+  PROTOBUF = 1;
+  JSON = 2;
+}
+
+// Represents a single test case's input.  The testee should:
+//
+//   1. parse this proto (which should always succeed)
+//   2. parse the protobuf or JSON payload in "payload" (which may fail)
+//   3. if the parse succeeded, serialize the message in the requested format.
+message ConformanceRequest {
+  // The payload (whether protobuf of JSON) is always for a TestAllTypes proto
+  // (see below).
+  oneof payload {
+    bytes protobuf_payload = 1;
+    string json_payload = 2;
+  }
+
+  // Which format should the testee serialize its message to?
+  WireFormat requested_output_format = 3;
+}
+
+// Represents a single test case's output.
+message ConformanceResponse {
+  oneof result {
+    // This string should be set to indicate parsing failed.  The string can
+    // provide more information about the parse error if it is available.
+    //
+    // Setting this string does not necessarily mean the testee failed the
+    // test.  Some of the test cases are intentionally invalid input.
+    string parse_error = 1;
+
+    // This should be set if some other error occurred.  This will always
+    // indicate that the test failed.  The string can provide more information
+    // about the failure.
+    string runtime_error = 2;
+
+    // If the input was successfully parsed and the requested output was
+    // protobuf, serialize it to protobuf and set it in this field.
+    bytes protobuf_payload = 3;
+
+    // If the input was successfully parsed and the requested output was JSON,
+    // serialize to JSON and set it in this field.
+    string json_payload = 4;
+
+    // For when the testee skipped the test, likely because a certain feature
+    // wasn't supported, like JSON input/output.
+    string skipped = 5;
+  }
+}
+
+// This proto includes every type of field in both singular and repeated
+// forms.
+message TestAllTypes {
+  message NestedMessage {
+    int32 a = 1;
+    TestAllTypes corecursive = 2;
+  }
+
+  enum NestedEnum {
+    FOO = 0;
+    BAR = 1;
+    BAZ = 2;
+    NEG = -1;  // Intentionally negative.
+  }
+
+  // Singular
+  int32 optional_int32    =  1;
+  int64 optional_int64    =  2;
+  uint32 optional_uint32   =  3;
+  uint64 optional_uint64   =  4;
+  sint32 optional_sint32   =  5;
+  sint64 optional_sint64   =  6;
+  fixed32 optional_fixed32  =  7;
+  fixed64 optional_fixed64  =  8;
+  sfixed32 optional_sfixed32 =  9;
+  sfixed64 optional_sfixed64 = 10;
+  float optional_float    = 11;
+  double optional_double   = 12;
+  bool optional_bool     = 13;
+  string optional_string   = 14;
+  bytes optional_bytes    = 15;
+
+  NestedMessage                        optional_nested_message  = 18;
+  ForeignMessage                       optional_foreign_message = 19;
+
+  NestedEnum                           optional_nested_enum     = 21;
+  ForeignEnum                          optional_foreign_enum    = 22;
+
+  string optional_string_piece = 24 [ctype=STRING_PIECE];
+  string optional_cord = 25 [ctype=CORD];
+
+  TestAllTypes recursive_message = 27;
+
+  // Repeated
+  repeated    int32 repeated_int32    = 31;
+  repeated    int64 repeated_int64    = 32;
+  repeated   uint32 repeated_uint32   = 33;
+  repeated   uint64 repeated_uint64   = 34;
+  repeated   sint32 repeated_sint32   = 35;
+  repeated   sint64 repeated_sint64   = 36;
+  repeated  fixed32 repeated_fixed32  = 37;
+  repeated  fixed64 repeated_fixed64  = 38;
+  repeated sfixed32 repeated_sfixed32 = 39;
+  repeated sfixed64 repeated_sfixed64 = 40;
+  repeated    float repeated_float    = 41;
+  repeated   double repeated_double   = 42;
+  repeated     bool repeated_bool     = 43;
+  repeated   string repeated_string   = 44;
+  repeated    bytes repeated_bytes    = 45;
+
+  repeated NestedMessage                        repeated_nested_message  = 48;
+  repeated ForeignMessage                       repeated_foreign_message = 49;
+
+  repeated NestedEnum                           repeated_nested_enum     = 51;
+  repeated ForeignEnum                          repeated_foreign_enum    = 52;
+
+  repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+  repeated string repeated_cord = 55 [ctype=CORD];
+
+  // Map
+  map <   int32, int32>    map_int32_int32 = 56;
+  map <   int64, int64>    map_int64_int64 = 57;
+  map <  uint32, uint32>   map_uint32_uint32 = 58;
+  map <  uint64, uint64>   map_uint64_uint64 = 59;
+  map <  sint32, sint32>   map_sint32_sint32 = 60;
+  map <  sint64, sint64>   map_sint64_sint64 = 61;
+  map < fixed32, fixed32>  map_fixed32_fixed32 = 62;
+  map < fixed64, fixed64>  map_fixed64_fixed64 = 63;
+  map <sfixed32, sfixed32> map_sfixed32_sfixed32 = 64;
+  map <sfixed64, sfixed64> map_sfixed64_sfixed64 = 65;
+  map <   int32, float>    map_int32_float = 66;
+  map <   int32, double>   map_int32_double = 67;
+  map <    bool, bool>     map_bool_bool = 68;
+  map <  string, string>   map_string_string = 69;
+  map <  string, bytes>    map_string_bytes = 70;
+  map <  string, NestedMessage>  map_string_nested_message = 71;
+  map <  string, ForeignMessage> map_string_foreign_message = 72;
+  map <  string, NestedEnum>     map_string_nested_enum = 73;
+  map <  string, ForeignEnum>    map_string_foreign_enum = 74;
+
+  oneof oneof_field {
+    uint32 oneof_uint32 = 111;
+    NestedMessage oneof_nested_message = 112;
+    string oneof_string = 113;
+    bytes oneof_bytes = 114;
+  }
+}
+
+message ForeignMessage {
+  int32 c = 1;
+}
+
+enum ForeignEnum {
+  FOREIGN_FOO = 0;
+  FOREIGN_BAR = 1;
+  FOREIGN_BAZ = 2;
+}

+ 194 - 0
conformance/conformance_cpp.cc

@@ -0,0 +1,194 @@
+// 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.
+
+#include <errno.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#include "conformance.pb.h"
+#include <google/protobuf/util/json_util.h>
+#include <google/protobuf/util/type_resolver_util.h>
+
+using conformance::ConformanceRequest;
+using conformance::ConformanceResponse;
+using conformance::TestAllTypes;
+using google::protobuf::Descriptor;
+using google::protobuf::DescriptorPool;
+using google::protobuf::internal::scoped_ptr;
+using google::protobuf::util::BinaryToJsonString;
+using google::protobuf::util::JsonToBinaryString;
+using google::protobuf::util::NewTypeResolverForDescriptorPool;
+using google::protobuf::util::Status;
+using google::protobuf::util::TypeResolver;
+using std::string;
+
+static const char kTypeUrlPrefix[] = "type.googleapis.com";
+
+static string GetTypeUrl(const Descriptor* message) {
+  return string(kTypeUrlPrefix) + "/" + message->full_name();
+}
+
+int test_count = 0;
+bool verbose = false;
+TypeResolver* type_resolver;
+string* type_url;
+
+
+bool CheckedRead(int fd, void *buf, size_t len) {
+  size_t ofs = 0;
+  while (len > 0) {
+    ssize_t bytes_read = read(fd, (char*)buf + ofs, len);
+
+    if (bytes_read == 0) return false;
+
+    if (bytes_read < 0) {
+      GOOGLE_LOG(FATAL) << "Error reading from test runner: " <<  strerror(errno);
+    }
+
+    len -= bytes_read;
+    ofs += bytes_read;
+  }
+
+  return true;
+}
+
+void CheckedWrite(int fd, const void *buf, size_t len) {
+  if (write(fd, buf, len) != len) {
+    GOOGLE_LOG(FATAL) << "Error writing to test runner: " << strerror(errno);
+  }
+}
+
+void DoTest(const ConformanceRequest& request, ConformanceResponse* response) {
+  TestAllTypes test_message;
+
+  switch (request.payload_case()) {
+    case ConformanceRequest::kProtobufPayload:
+      if (!test_message.ParseFromString(request.protobuf_payload())) {
+        // Getting parse details would involve something like:
+        //   http://stackoverflow.com/questions/22121922/how-can-i-get-more-details-about-errors-generated-during-protobuf-parsing-c
+        response->set_parse_error("Parse error (no more details available).");
+        return;
+      }
+      break;
+
+    case ConformanceRequest::kJsonPayload: {
+      string proto_binary;
+      Status status = JsonToBinaryString(type_resolver, *type_url,
+                                         request.json_payload(), &proto_binary);
+      if (!status.ok()) {
+        response->set_parse_error(string("Parse error: ") +
+                                  status.error_message().as_string());
+        return;
+      }
+
+      GOOGLE_CHECK(test_message.ParseFromString(proto_binary));
+      break;
+    }
+
+    case ConformanceRequest::PAYLOAD_NOT_SET:
+      GOOGLE_LOG(FATAL) << "Request didn't have payload.";
+      break;
+  }
+
+  switch (request.requested_output_format()) {
+    case conformance::UNSPECIFIED:
+      GOOGLE_LOG(FATAL) << "Unspecified output format";
+      break;
+
+    case conformance::PROTOBUF:
+      GOOGLE_CHECK(
+          test_message.SerializeToString(response->mutable_protobuf_payload()));
+      break;
+
+    case conformance::JSON: {
+      string proto_binary;
+      GOOGLE_CHECK(test_message.SerializeToString(&proto_binary));
+      Status status = BinaryToJsonString(type_resolver, *type_url, proto_binary,
+                                         response->mutable_json_payload());
+      GOOGLE_CHECK(status.ok());
+      break;
+    }
+  }
+}
+
+bool DoTestIo() {
+  string serialized_input;
+  string serialized_output;
+  ConformanceRequest request;
+  ConformanceResponse response;
+  uint32_t bytes;
+
+  if (!CheckedRead(STDIN_FILENO, &bytes, sizeof(uint32_t))) {
+    // EOF.
+    return false;
+  }
+
+  serialized_input.resize(bytes);
+
+  if (!CheckedRead(STDIN_FILENO, (char*)serialized_input.c_str(), bytes)) {
+    GOOGLE_LOG(ERROR) << "Unexpected EOF on stdin. " << strerror(errno);
+  }
+
+  if (!request.ParseFromString(serialized_input)) {
+    GOOGLE_LOG(FATAL) << "Parse of ConformanceRequest proto failed.";
+    return false;
+  }
+
+  DoTest(request, &response);
+
+  response.SerializeToString(&serialized_output);
+
+  bytes = serialized_output.size();
+  CheckedWrite(STDOUT_FILENO, &bytes, sizeof(uint32_t));
+  CheckedWrite(STDOUT_FILENO, serialized_output.c_str(), bytes);
+
+  if (verbose) {
+    fprintf(stderr, "conformance-cpp: request=%s, response=%s\n",
+            request.ShortDebugString().c_str(),
+            response.ShortDebugString().c_str());
+  }
+
+  test_count++;
+
+  return true;
+}
+
+int main() {
+  type_resolver = NewTypeResolverForDescriptorPool(
+      kTypeUrlPrefix, DescriptorPool::generated_pool());
+  type_url = new string(GetTypeUrl(TestAllTypes::descriptor()));
+  while (1) {
+    if (!DoTestIo()) {
+      fprintf(stderr, "conformance-cpp: received EOF from test runner "
+                      "after %d tests, exiting\n", test_count);
+      return 0;
+    }
+  }
+}

+ 114 - 0
conformance/conformance_ruby.rb

@@ -0,0 +1,114 @@
+#!/usr/bin/env ruby
+#
+# 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.
+
+require 'conformance'
+
+$test_count = 0
+$verbose = false
+
+def do_test(request)
+  test_message = Conformance::TestAllTypes.new
+  response = Conformance::ConformanceResponse.new
+
+  begin
+    case request.payload
+    when :protobuf_payload
+      begin
+        test_message =
+          Conformance::TestAllTypes.decode(request.protobuf_payload)
+      rescue Google::Protobuf::ParseError => err
+        response.parse_error = err.message.encode('utf-8')
+        return response
+      end
+
+    when :json_payload
+      test_message = Conformance::TestAllTypes.decode_json(request.json_payload)
+
+    when nil
+      fail "Request didn't have payload"
+    end
+
+    case request.requested_output_format
+    when :UNSPECIFIED
+      fail 'Unspecified output format'
+
+    when :PROTOBUF
+      response.protobuf_payload = test_message.to_proto
+
+    when :JSON
+      response.json_payload = test_message.to_json
+    end
+  rescue StandardError => err
+    response.runtime_error = err.message.encode('utf-8')
+  end
+
+  response
+end
+
+# Returns true if the test ran successfully, false on legitimate EOF.
+# If EOF is encountered in an unexpected place, raises IOError.
+def do_test_io
+  length_bytes = STDIN.read(4)
+  return false if length_bytes.nil?
+
+  length = length_bytes.unpack('V').first
+  serialized_request = STDIN.read(length)
+  if serialized_request.nil? || serialized_request.length != length
+    fail IOError
+  end
+
+  request = Conformance::ConformanceRequest.decode(serialized_request)
+
+  response = do_test(request)
+
+  serialized_response = Conformance::ConformanceResponse.encode(response)
+  STDOUT.write([serialized_response.length].pack('V'))
+  STDOUT.write(serialized_response)
+  STDOUT.flush
+
+  if $verbose
+    STDERR.puts("conformance-cpp: request={request.to_json}, " \
+                                 "response={response.to_json}\n")
+  end
+
+  $test_count += 1
+
+  true
+end
+
+loop do
+  unless do_test_io
+    STDERR.puts('conformance-cpp: received EOF from test runner ' \
+                "after #{$test_count} tests, exiting")
+    break
+  end
+end

+ 534 - 0
conformance/conformance_test.cc

@@ -0,0 +1,534 @@
+// 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.
+
+#include <stdarg.h>
+#include <string>
+
+#include "conformance.pb.h"
+#include "conformance_test.h"
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/text_format.h>
+#include <google/protobuf/util/json_util.h>
+#include <google/protobuf/util/message_differencer.h>
+#include <google/protobuf/util/type_resolver_util.h>
+#include <google/protobuf/wire_format_lite.h>
+
+using conformance::ConformanceRequest;
+using conformance::ConformanceResponse;
+using conformance::TestAllTypes;
+using conformance::WireFormat;
+using google::protobuf::Descriptor;
+using google::protobuf::FieldDescriptor;
+using google::protobuf::internal::WireFormatLite;
+using google::protobuf::TextFormat;
+using google::protobuf::util::JsonToBinaryString;
+using google::protobuf::util::MessageDifferencer;
+using google::protobuf::util::NewTypeResolverForDescriptorPool;
+using google::protobuf::util::Status;
+using std::string;
+
+namespace {
+
+static const char kTypeUrlPrefix[] = "type.googleapis.com";
+
+static string GetTypeUrl(const Descriptor* message) {
+  return string(kTypeUrlPrefix) + "/" + message->full_name();
+}
+
+/* Routines for building arbitrary protos *************************************/
+
+// We would use CodedOutputStream except that we want more freedom to build
+// arbitrary protos (even invalid ones).
+
+const string empty;
+
+string cat(const string& a, const string& b,
+           const string& c = empty,
+           const string& d = empty,
+           const string& e = empty,
+           const string& f = empty,
+           const string& g = empty,
+           const string& h = empty,
+           const string& i = empty,
+           const string& j = empty,
+           const string& k = empty,
+           const string& l = empty) {
+  string ret;
+  ret.reserve(a.size() + b.size() + c.size() + d.size() + e.size() + f.size() +
+              g.size() + h.size() + i.size() + j.size() + k.size() + l.size());
+  ret.append(a);
+  ret.append(b);
+  ret.append(c);
+  ret.append(d);
+  ret.append(e);
+  ret.append(f);
+  ret.append(g);
+  ret.append(h);
+  ret.append(i);
+  ret.append(j);
+  ret.append(k);
+  ret.append(l);
+  return ret;
+}
+
+// The maximum number of bytes that it takes to encode a 64-bit varint.
+#define VARINT_MAX_LEN 10
+
+size_t vencode64(uint64_t val, char *buf) {
+  if (val == 0) { buf[0] = 0; return 1; }
+  size_t i = 0;
+  while (val) {
+    uint8_t byte = val & 0x7fU;
+    val >>= 7;
+    if (val) byte |= 0x80U;
+    buf[i++] = byte;
+  }
+  return i;
+}
+
+string varint(uint64_t x) {
+  char buf[VARINT_MAX_LEN];
+  size_t len = vencode64(x, buf);
+  return string(buf, len);
+}
+
+// TODO: proper byte-swapping for big-endian machines.
+string fixed32(void *data) { return string(static_cast<char*>(data), 4); }
+string fixed64(void *data) { return string(static_cast<char*>(data), 8); }
+
+string delim(const string& buf) { return cat(varint(buf.size()), buf); }
+string uint32(uint32_t u32) { return fixed32(&u32); }
+string uint64(uint64_t u64) { return fixed64(&u64); }
+string flt(float f) { return fixed32(&f); }
+string dbl(double d) { return fixed64(&d); }
+string zz32(int32_t x) { return varint(WireFormatLite::ZigZagEncode32(x)); }
+string zz64(int64_t x) { return varint(WireFormatLite::ZigZagEncode64(x)); }
+
+string tag(uint32_t fieldnum, char wire_type) {
+  return varint((fieldnum << 3) | wire_type);
+}
+
+string submsg(uint32_t fn, const string& buf) {
+  return cat( tag(fn, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), delim(buf) );
+}
+
+#define UNKNOWN_FIELD 666
+
+uint32_t GetFieldNumberForType(FieldDescriptor::Type type, bool repeated) {
+  const Descriptor* d = TestAllTypes().GetDescriptor();
+  for (int i = 0; i < d->field_count(); i++) {
+    const FieldDescriptor* f = d->field(i);
+    if (f->type() == type && f->is_repeated() == repeated) {
+      return f->number();
+    }
+  }
+  GOOGLE_LOG(FATAL) << "Couldn't find field with type " << (int)type;
+  return 0;
+}
+
+string UpperCase(string str) {
+  for (int i = 0; i < str.size(); i++) {
+    str[i] = toupper(str[i]);
+  }
+  return str;
+}
+
+}  // anonymous namespace
+
+namespace google {
+namespace protobuf {
+
+void ConformanceTestSuite::ReportSuccess(const string& test_name) {
+  if (expected_to_fail_.erase(test_name) != 0) {
+    StringAppendF(&output_,
+                  "ERROR: test %s is in the failure list, but test succeeded.  "
+                  "Remove it from the failure list.\n",
+                  test_name.c_str());
+    unexpected_succeeding_tests_.insert(test_name);
+  }
+  successes_++;
+}
+
+void ConformanceTestSuite::ReportFailure(const string& test_name,
+                                         const ConformanceRequest& request,
+                                         const ConformanceResponse& response,
+                                         const char* fmt, ...) {
+  if (expected_to_fail_.erase(test_name) == 1) {
+    expected_failures_++;
+    if (!verbose_)
+      return;
+  } else {
+    StringAppendF(&output_, "ERROR, test=%s: ", test_name.c_str());
+    unexpected_failing_tests_.insert(test_name);
+  }
+  va_list args;
+  va_start(args, fmt);
+  StringAppendV(&output_, fmt, args);
+  va_end(args);
+  StringAppendF(&output_, " request=%s, response=%s\n",
+                request.ShortDebugString().c_str(),
+                response.ShortDebugString().c_str());
+}
+
+void ConformanceTestSuite::ReportSkip(const string& test_name,
+                                      const ConformanceRequest& request,
+                                      const ConformanceResponse& response) {
+  if (verbose_) {
+    StringAppendF(&output_, "SKIPPED, test=%s request=%s, response=%s\n",
+                  test_name.c_str(), request.ShortDebugString().c_str(),
+                  response.ShortDebugString().c_str());
+  }
+  skipped_.insert(test_name);
+}
+
+void ConformanceTestSuite::RunTest(const string& test_name,
+                                   const ConformanceRequest& request,
+                                   ConformanceResponse* response) {
+  if (test_names_.insert(test_name).second == false) {
+    GOOGLE_LOG(FATAL) << "Duplicated test name: " << test_name;
+  }
+
+  string serialized_request;
+  string serialized_response;
+  request.SerializeToString(&serialized_request);
+
+  runner_->RunTest(serialized_request, &serialized_response);
+
+  if (!response->ParseFromString(serialized_response)) {
+    response->Clear();
+    response->set_runtime_error("response proto could not be parsed.");
+  }
+
+  if (verbose_) {
+    StringAppendF(&output_, "conformance test: name=%s, request=%s, response=%s\n",
+                  test_name.c_str(),
+                  request.ShortDebugString().c_str(),
+                  response->ShortDebugString().c_str());
+  }
+}
+
+void ConformanceTestSuite::RunValidInputTest(
+    const string& test_name, const string& input, WireFormat input_format,
+    const string& equivalent_text_format, WireFormat requested_output) {
+  TestAllTypes reference_message;
+  GOOGLE_CHECK(
+      TextFormat::ParseFromString(equivalent_text_format, &reference_message));
+
+  ConformanceRequest request;
+  ConformanceResponse response;
+
+  switch (input_format) {
+    case conformance::PROTOBUF:
+      request.set_protobuf_payload(input);
+      break;
+
+    case conformance::JSON:
+      request.set_json_payload(input);
+      break;
+
+    case conformance::UNSPECIFIED:
+      GOOGLE_LOG(FATAL) << "Unspecified input format";
+
+  }
+
+  request.set_requested_output_format(requested_output);
+
+  RunTest(test_name, request, &response);
+
+  TestAllTypes test_message;
+
+  switch (response.result_case()) {
+    case ConformanceResponse::kParseError:
+    case ConformanceResponse::kRuntimeError:
+      ReportFailure(test_name, request, response,
+                    "Failed to parse valid JSON input.");
+      return;
+
+    case ConformanceResponse::kSkipped:
+      ReportSkip(test_name, request, response);
+      return;
+
+    case ConformanceResponse::kJsonPayload: {
+      if (requested_output != conformance::JSON) {
+        ReportFailure(
+            test_name, request, response,
+            "Test was asked for protobuf output but provided JSON instead.");
+        return;
+      }
+      string binary_protobuf;
+      Status status =
+          JsonToBinaryString(type_resolver_.get(), type_url_,
+                             response.json_payload(), &binary_protobuf);
+      if (!status.ok()) {
+        ReportFailure(test_name, request, response,
+                      "JSON output we received from test was unparseable.");
+        return;
+      }
+
+      GOOGLE_CHECK(test_message.ParseFromString(binary_protobuf));
+      break;
+    }
+
+    case ConformanceResponse::kProtobufPayload: {
+      if (requested_output != conformance::PROTOBUF) {
+        ReportFailure(
+            test_name, request, response,
+            "Test was asked for JSON output but provided protobuf instead.");
+        return;
+      }
+
+      if (!test_message.ParseFromString(response.protobuf_payload())) {
+        ReportFailure(test_name, request, response,
+                      "Protobuf output we received from test was unparseable.");
+        return;
+      }
+
+      break;
+    }
+  }
+
+  MessageDifferencer differencer;
+  string differences;
+  differencer.ReportDifferencesToString(&differences);
+
+  if (differencer.Equals(reference_message, test_message)) {
+    ReportSuccess(test_name);
+  } else {
+    ReportFailure(test_name, request, response,
+                  "Output was not equivalent to reference message: %s.",
+                  differences.c_str());
+  }
+}
+
+// Expect that this precise protobuf will cause a parse error.
+void ConformanceTestSuite::ExpectParseFailureForProto(
+    const string& proto, const string& test_name) {
+  ConformanceRequest request;
+  ConformanceResponse response;
+  request.set_protobuf_payload(proto);
+  string effective_test_name = "ProtobufInput." + test_name;
+
+  // We don't expect output, but if the program erroneously accepts the protobuf
+  // we let it send its response as this.  We must not leave it unspecified.
+  request.set_requested_output_format(conformance::PROTOBUF);
+
+  RunTest(effective_test_name, request, &response);
+  if (response.result_case() == ConformanceResponse::kParseError) {
+    ReportSuccess(effective_test_name);
+  } else {
+    ReportFailure(effective_test_name, request, response,
+                  "Should have failed to parse, but didn't.");
+  }
+}
+
+// Expect that this protobuf will cause a parse error, even if it is followed
+// by valid protobuf data.  We can try running this twice: once with this
+// data verbatim and once with this data followed by some valid data.
+//
+// TODO(haberman): implement the second of these.
+void ConformanceTestSuite::ExpectHardParseFailureForProto(
+    const string& proto, const string& test_name) {
+  return ExpectParseFailureForProto(proto, test_name);
+}
+
+void ConformanceTestSuite::RunValidJsonTest(
+    const string& test_name, const string& input_json,
+    const string& equivalent_text_format) {
+  RunValidInputTest("JsonInput." + test_name + ".JsonOutput", input_json,
+                    conformance::JSON, equivalent_text_format,
+                    conformance::PROTOBUF);
+  RunValidInputTest("JsonInput." + test_name + ".ProtobufOutput", input_json, conformance::JSON,
+                    equivalent_text_format, conformance::JSON);
+}
+
+void ConformanceTestSuite::TestPrematureEOFForType(FieldDescriptor::Type type) {
+  // Incomplete values for each wire type.
+  static const string incompletes[6] = {
+    string("\x80"),     // VARINT
+    string("abcdefg"),  // 64BIT
+    string("\x80"),     // DELIMITED (partial length)
+    string(),           // START_GROUP (no value required)
+    string(),           // END_GROUP (no value required)
+    string("abc")       // 32BIT
+  };
+
+  uint32_t fieldnum = GetFieldNumberForType(type, false);
+  uint32_t rep_fieldnum = GetFieldNumberForType(type, true);
+  WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType(
+      static_cast<WireFormatLite::FieldType>(type));
+  const string& incomplete = incompletes[wire_type];
+  const string type_name =
+      UpperCase(string(".") + FieldDescriptor::TypeName(type));
+
+  ExpectParseFailureForProto(
+      tag(fieldnum, wire_type),
+      "PrematureEofBeforeKnownNonRepeatedValue" + type_name);
+
+  ExpectParseFailureForProto(
+      tag(rep_fieldnum, wire_type),
+      "PrematureEofBeforeKnownRepeatedValue" + type_name);
+
+  ExpectParseFailureForProto(
+      tag(UNKNOWN_FIELD, wire_type),
+      "PrematureEofBeforeUnknownValue" + type_name);
+
+  ExpectParseFailureForProto(
+      cat( tag(fieldnum, wire_type), incomplete ),
+      "PrematureEofInsideKnownNonRepeatedValue" + type_name);
+
+  ExpectParseFailureForProto(
+      cat( tag(rep_fieldnum, wire_type), incomplete ),
+      "PrematureEofInsideKnownRepeatedValue" + type_name);
+
+  ExpectParseFailureForProto(
+      cat( tag(UNKNOWN_FIELD, wire_type), incomplete ),
+      "PrematureEofInsideUnknownValue" + type_name);
+
+  if (wire_type == WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+    ExpectParseFailureForProto(
+        cat( tag(fieldnum, wire_type), varint(1) ),
+        "PrematureEofInDelimitedDataForKnownNonRepeatedValue" + type_name);
+
+    ExpectParseFailureForProto(
+        cat( tag(rep_fieldnum, wire_type), varint(1) ),
+        "PrematureEofInDelimitedDataForKnownRepeatedValue" + type_name);
+
+    // EOF in the middle of delimited data for unknown value.
+    ExpectParseFailureForProto(
+        cat( tag(UNKNOWN_FIELD, wire_type), varint(1) ),
+        "PrematureEofInDelimitedDataForUnknownValue" + type_name);
+
+    if (type == FieldDescriptor::TYPE_MESSAGE) {
+      // Submessage ends in the middle of a value.
+      string incomplete_submsg =
+          cat( tag(WireFormatLite::TYPE_INT32, WireFormatLite::WIRETYPE_VARINT),
+                incompletes[WireFormatLite::WIRETYPE_VARINT] );
+      ExpectHardParseFailureForProto(
+          cat( tag(fieldnum, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
+               varint(incomplete_submsg.size()),
+               incomplete_submsg ),
+          "PrematureEofInSubmessageValue" + type_name);
+    }
+  } else if (type != FieldDescriptor::TYPE_GROUP) {
+    // Non-delimited, non-group: eligible for packing.
+
+    // Packed region ends in the middle of a value.
+    ExpectHardParseFailureForProto(
+        cat( tag(rep_fieldnum, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
+             varint(incomplete.size()),
+             incomplete ),
+        "PrematureEofInPackedFieldValue" + type_name);
+
+    // EOF in the middle of packed region.
+    ExpectParseFailureForProto(
+        cat( tag(rep_fieldnum, WireFormatLite::WIRETYPE_LENGTH_DELIMITED),
+             varint(1) ),
+        "PrematureEofInPackedField" + type_name);
+  }
+}
+
+void ConformanceTestSuite::SetFailureList(const vector<string>& failure_list) {
+  expected_to_fail_.clear();
+  std::copy(failure_list.begin(), failure_list.end(),
+            std::inserter(expected_to_fail_, expected_to_fail_.end()));
+}
+
+bool ConformanceTestSuite::CheckSetEmpty(const set<string>& set_to_check,
+                                         const char* msg) {
+  if (set_to_check.empty()) {
+    return true;
+  } else {
+    StringAppendF(&output_, "\n");
+    StringAppendF(&output_, "%s:\n", msg);
+    for (set<string>::const_iterator iter = set_to_check.begin();
+         iter != set_to_check.end(); ++iter) {
+      StringAppendF(&output_, "  %s\n", iter->c_str());
+    }
+    StringAppendF(&output_, "\n");
+    return false;
+  }
+}
+
+bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
+                                    std::string* output) {
+  runner_ = runner;
+  successes_ = 0;
+  expected_failures_ = 0;
+  skipped_.clear();
+  test_names_.clear();
+  unexpected_failing_tests_.clear();
+  unexpected_succeeding_tests_.clear();
+  type_resolver_.reset(NewTypeResolverForDescriptorPool(
+      kTypeUrlPrefix, DescriptorPool::generated_pool()));
+  type_url_ = GetTypeUrl(TestAllTypes::descriptor());
+
+  output_ = "\nCONFORMANCE TEST BEGIN ====================================\n\n";
+
+  for (int i = 1; i <= FieldDescriptor::MAX_TYPE; i++) {
+    if (i == FieldDescriptor::TYPE_GROUP) continue;
+    TestPrematureEOFForType(static_cast<FieldDescriptor::Type>(i));
+  }
+
+  RunValidJsonTest("HelloWorld", "{\"optionalString\":\"Hello, World!\"}",
+                   "optional_string: 'Hello, World!'");
+
+  bool ok =
+      CheckSetEmpty(expected_to_fail_,
+                    "These tests were listed in the failure list, but they "
+                    "don't exist.  Remove them from the failure list") &&
+
+      CheckSetEmpty(unexpected_failing_tests_,
+                    "These tests failed.  If they can't be fixed right now, "
+                    "you can add them to the failure list so the overall "
+                    "suite can succeed") &&
+
+      CheckSetEmpty(unexpected_succeeding_tests_,
+                    "These tests succeeded, even though they were listed in "
+                    "the failure list.  Remove them from the failure list");
+
+  CheckSetEmpty(skipped_,
+                "These tests were skipped (probably because support for some "
+                "features is not implemented)");
+
+  StringAppendF(&output_,
+                "CONFORMANCE SUITE %s: %d successes, %d skipped, "
+                "%d expected failures, %d unexpected failures.\n",
+                ok ? "PASSED" : "FAILED", successes_, skipped_.size(),
+                expected_failures_, unexpected_failing_tests_.size());
+  StringAppendF(&output_, "\n");
+
+  output->assign(output_);
+
+  return ok;
+}
+
+}  // namespace protobuf
+}  // namespace google

+ 158 - 0
conformance/conformance_test.h

@@ -0,0 +1,158 @@
+// 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 defines a protocol for running the conformance test suite
+// in-process.  In other words, the suite itself will run in the same process as
+// the code under test.
+//
+// For pros and cons of this approach, please see conformance.proto.
+
+#ifndef CONFORMANCE_CONFORMANCE_TEST_H
+#define CONFORMANCE_CONFORMANCE_TEST_H
+
+#include <string>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/wire_format_lite.h>
+
+namespace conformance {
+class ConformanceRequest;
+class ConformanceResponse;
+}  // namespace conformance
+
+namespace google {
+namespace protobuf {
+
+class ConformanceTestRunner {
+ public:
+  // Call to run a single conformance test.
+  //
+  // "input" is a serialized conformance.ConformanceRequest.
+  // "output" should be set to a serialized conformance.ConformanceResponse.
+  //
+  // If there is any error in running the test itself, set "runtime_error" in
+  // the response.
+  virtual void RunTest(const std::string& input, std::string* output) = 0;
+};
+
+// Class representing the test suite itself.  To run it, implement your own
+// class derived from ConformanceTestRunner and then write code like:
+//
+//    class MyConformanceTestRunner : public ConformanceTestRunner {
+//     public:
+//      virtual void RunTest(...) {
+//        // INSERT YOUR FRAMEWORK-SPECIFIC CODE HERE.
+//      }
+//    };
+//
+//    int main() {
+//      MyConformanceTestRunner runner;
+//      google::protobuf::ConformanceTestSuite suite;
+//
+//      std::string output;
+//      suite.RunSuite(&runner, &output);
+//    }
+//
+class ConformanceTestSuite {
+ public:
+  ConformanceTestSuite() : verbose_(false) {}
+
+  void SetVerbose(bool verbose) { verbose_ = verbose; }
+
+  // Sets the list of tests that are expected to fail when RunSuite() is called.
+  // RunSuite() will fail unless the set of failing tests is exactly the same
+  // as this list.
+  void SetFailureList(const std::vector<std::string>& failure_list);
+
+  // Run all the conformance tests against the given test runner.
+  // Test output will be stored in "output".
+  //
+  // Returns true if the set of failing tests was exactly the same as the
+  // failure list.  If SetFailureList() was not called, returns true if all
+  // tests passed.
+  bool RunSuite(ConformanceTestRunner* runner, std::string* output);
+
+ private:
+  void ReportSuccess(const std::string& test_name);
+  void ReportFailure(const string& test_name,
+                     const conformance::ConformanceRequest& request,
+                     const conformance::ConformanceResponse& response,
+                     const char* fmt, ...);
+  void ReportSkip(const string& test_name,
+                  const conformance::ConformanceRequest& request,
+                  const conformance::ConformanceResponse& response);
+  void RunTest(const std::string& test_name,
+               const conformance::ConformanceRequest& request,
+               conformance::ConformanceResponse* response);
+  void RunValidInputTest(const string& test_name, const string& input,
+                         conformance::WireFormat input_format,
+                         const string& equivalent_text_format,
+                         conformance::WireFormat requested_output);
+  void RunValidJsonTest(const string& test_name, const string& input_json,
+                        const string& equivalent_text_format);
+  void ExpectParseFailureForProto(const std::string& proto,
+                                  const std::string& test_name);
+  void ExpectHardParseFailureForProto(const std::string& proto,
+                                      const std::string& test_name);
+  void TestPrematureEOFForType(google::protobuf::FieldDescriptor::Type type);
+  bool CheckSetEmpty(const set<string>& set_to_check, const char* msg);
+  ConformanceTestRunner* runner_;
+  int successes_;
+  int expected_failures_;
+  bool verbose_;
+  std::string output_;
+
+  // The set of test names that are expected to fail in this run, but haven't
+  // failed yet.
+  std::set<std::string> expected_to_fail_;
+
+  // The set of test names that have been run.  Used to ensure that there are no
+  // duplicate names in the suite.
+  std::set<std::string> test_names_;
+
+  // The set of tests that failed, but weren't expected to.
+  std::set<std::string> unexpected_failing_tests_;
+
+  // The set of tests that succeeded, but weren't expected to.
+  std::set<std::string> unexpected_succeeding_tests_;
+
+  // The set of tests that the testee opted out of;
+  std::set<std::string> skipped_;
+
+  google::protobuf::internal::scoped_ptr<google::protobuf::util::TypeResolver>
+      type_resolver_;
+  std::string type_url_;
+};
+
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // CONFORMANCE_CONFORMANCE_TEST_H

+ 252 - 0
conformance/conformance_test_runner.cc

@@ -0,0 +1,252 @@
+// 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 contains a program for running the test suite in a separate
+// process.  The other alternative is to run the suite in-process.  See
+// conformance.proto for pros/cons of these two options.
+//
+// This program will fork the process under test and communicate with it over
+// its stdin/stdout:
+//
+//     +--------+   pipe   +----------+
+//     | tester | <------> | testee   |
+//     |        |          |          |
+//     |  C++   |          | any lang |
+//     +--------+          +----------+
+//
+// The tester contains all of the test cases and their expected output.
+// The testee is a simple program written in the target language that reads
+// each test case and attempts to produce acceptable output for it.
+//
+// Every test consists of a ConformanceRequest/ConformanceResponse
+// request/reply pair.  The protocol on the pipe is simply:
+//
+//   1. tester sends 4-byte length N (little endian)
+//   2. tester sends N bytes representing a ConformanceRequest proto
+//   3. testee sends 4-byte length M (little endian)
+//   4. testee sends M bytes representing a ConformanceResponse proto
+
+#include <errno.h>
+#include <unistd.h>
+#include <fstream>
+#include <vector>
+
+#include "conformance.pb.h"
+#include "conformance_test.h"
+
+using conformance::ConformanceRequest;
+using conformance::ConformanceResponse;
+using google::protobuf::internal::scoped_array;
+using std::string;
+using std::vector;
+
+#define STRINGIFY(x) #x
+#define TOSTRING(x) STRINGIFY(x)
+#define CHECK_SYSCALL(call) \
+  if (call < 0) { \
+    perror(#call " " __FILE__ ":" TOSTRING(__LINE__)); \
+    exit(1); \
+  }
+
+// Test runner that spawns the process being tested and communicates with it
+// over a pipe.
+class ForkPipeRunner : public google::protobuf::ConformanceTestRunner {
+ public:
+  ForkPipeRunner(const std::string &executable)
+      : executable_(executable), running_(false) {}
+
+  void RunTest(const std::string& request, std::string* response) {
+    if (!running_) {
+      SpawnTestProgram();
+    }
+
+    uint32_t len = request.size();
+    CheckedWrite(write_fd_, &len, sizeof(uint32_t));
+    CheckedWrite(write_fd_, request.c_str(), request.size());
+    CheckedRead(read_fd_, &len, sizeof(uint32_t));
+    response->resize(len);
+    CheckedRead(read_fd_, (void*)response->c_str(), len);
+  }
+
+ private:
+  // TODO(haberman): make this work on Windows, instead of using these
+  // UNIX-specific APIs.
+  //
+  // There is a platform-agnostic API in
+  //    src/google/protobuf/compiler/subprocess.h
+  //
+  // However that API only supports sending a single message to the subprocess.
+  // We really want to be able to send messages and receive responses one at a
+  // time:
+  //
+  // 1. Spawning a new process for each test would take way too long for thousands
+  //    of tests and subprocesses like java that can take 100ms or more to start
+  //    up.
+  //
+  // 2. Sending all the tests in one big message and receiving all results in one
+  //    big message would take away our visibility about which test(s) caused a
+  //    crash or other fatal error.  It would also give us only a single failure
+  //    instead of all of them.
+  void SpawnTestProgram() {
+    int toproc_pipe_fd[2];
+    int fromproc_pipe_fd[2];
+    if (pipe(toproc_pipe_fd) < 0 || pipe(fromproc_pipe_fd) < 0) {
+      perror("pipe");
+      exit(1);
+    }
+
+    pid_t pid = fork();
+    if (pid < 0) {
+      perror("fork");
+      exit(1);
+    }
+
+    if (pid) {
+      // Parent.
+      CHECK_SYSCALL(close(toproc_pipe_fd[0]));
+      CHECK_SYSCALL(close(fromproc_pipe_fd[1]));
+      write_fd_ = toproc_pipe_fd[1];
+      read_fd_ = fromproc_pipe_fd[0];
+      running_ = true;
+    } else {
+      // Child.
+      CHECK_SYSCALL(close(STDIN_FILENO));
+      CHECK_SYSCALL(close(STDOUT_FILENO));
+      CHECK_SYSCALL(dup2(toproc_pipe_fd[0], STDIN_FILENO));
+      CHECK_SYSCALL(dup2(fromproc_pipe_fd[1], STDOUT_FILENO));
+
+      CHECK_SYSCALL(close(toproc_pipe_fd[0]));
+      CHECK_SYSCALL(close(fromproc_pipe_fd[1]));
+      CHECK_SYSCALL(close(toproc_pipe_fd[1]));
+      CHECK_SYSCALL(close(fromproc_pipe_fd[0]));
+
+      scoped_array<char> executable(new char[executable_.size() + 1]);
+      memcpy(executable.get(), executable_.c_str(), executable_.size());
+      executable[executable_.size()] = '\0';
+
+      char *const argv[] = {executable.get(), NULL};
+      CHECK_SYSCALL(execv(executable.get(), argv));  // Never returns.
+    }
+  }
+
+  void CheckedWrite(int fd, const void *buf, size_t len) {
+    if (write(fd, buf, len) != len) {
+      GOOGLE_LOG(FATAL) << "Error writing to test program: " << strerror(errno);
+    }
+  }
+
+  void CheckedRead(int fd, void *buf, size_t len) {
+    size_t ofs = 0;
+    while (len > 0) {
+      ssize_t bytes_read = read(fd, (char*)buf + ofs, len);
+
+      if (bytes_read == 0) {
+        GOOGLE_LOG(FATAL) << "Unexpected EOF from test program";
+      } else if (bytes_read < 0) {
+        GOOGLE_LOG(FATAL) << "Error reading from test program: " << strerror(errno);
+      }
+
+      len -= bytes_read;
+      ofs += bytes_read;
+    }
+  }
+
+  int write_fd_;
+  int read_fd_;
+  bool running_;
+  std::string executable_;
+};
+
+void UsageError() {
+  fprintf(stderr,
+          "Usage: conformance-test-runner [options] <test-program>\n");
+  fprintf(stderr, "\n");
+  fprintf(stderr, "Options:\n");
+  fprintf(stderr,
+          "  --failure_list <filename>   Use to specify list of tests\n");
+  fprintf(stderr,
+          "                              that are expected to fail.  File\n");
+  fprintf(stderr,
+          "                              should contain one test name per\n");
+  fprintf(stderr,
+          "                              line.  Use '#' for comments.\n");
+  exit(1);
+}
+
+void ParseFailureList(const char *filename, vector<string>* failure_list) {
+  std::ifstream infile(filename);
+  for (string line; getline(infile, line);) {
+    // Remove whitespace.
+    line.erase(std::remove_if(line.begin(), line.end(), ::isspace),
+               line.end());
+
+    // Remove comments.
+    line = line.substr(0, line.find("#"));
+
+    if (!line.empty()) {
+      failure_list->push_back(line);
+    }
+  }
+}
+
+int main(int argc, char *argv[]) {
+  int arg = 1;
+  char *program;
+  google::protobuf::ConformanceTestSuite suite;
+
+  for (int arg = 1; arg < argc; ++arg) {
+    if (strcmp(argv[arg], "--failure_list") == 0) {
+      if (++arg == argc) UsageError();
+      vector<string> failure_list;
+      ParseFailureList(argv[arg], &failure_list);
+      suite.SetFailureList(failure_list);
+    } else if (strcmp(argv[arg], "--verbose") == 0) {
+      suite.SetVerbose(true);
+    } else if (argv[arg][0] == '-') {
+      fprintf(stderr, "Unknown option: %s\n", argv[arg]);
+      UsageError();
+    } else {
+      if (arg != argc - 1) {
+        fprintf(stderr, "Too many arguments.\n");
+        UsageError();
+      }
+      program = argv[arg];
+    }
+  }
+
+  ForkPipeRunner runner(program);
+
+  std::string output;
+  bool ok = suite.RunSuite(&runner, &output);
+
+  fwrite(output.c_str(), 1, output.size(), stderr);
+
+  return ok ? EXIT_SUCCESS : EXIT_FAILURE;
+}

+ 21 - 0
conformance/failure_list_cpp.txt

@@ -0,0 +1,21 @@
+# This is the list of conformance tests that are known to fail for the C++
+# implementation right now.  These should be fixed.
+#
+# By listing them here we can keep tabs on which ones are failing and be sure
+# that we don't introduce regressions in other tests.
+#
+# TODO(haberman): insert links to corresponding bugs tracking the issue.
+# Should we use GitHub issues or the Google-internal bug tracker?
+
+ProtobufInput.PrematureEofBeforeKnownRepeatedValue.MESSAGE
+ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
+ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
+ProtobufInput.PrematureEofInPackedField.BOOL
+ProtobufInput.PrematureEofInPackedField.ENUM
+ProtobufInput.PrematureEofInPackedField.INT32
+ProtobufInput.PrematureEofInPackedField.INT64
+ProtobufInput.PrematureEofInPackedField.SINT32
+ProtobufInput.PrematureEofInPackedField.SINT64
+ProtobufInput.PrematureEofInPackedField.UINT32
+ProtobufInput.PrematureEofInPackedField.UINT64
+ProtobufInput.PrematureEofInsideKnownRepeatedValue.MESSAGE

+ 0 - 0
conformance/failure_list_csharp.txt


+ 17 - 0
conformance/failure_list_ruby.txt

@@ -0,0 +1,17 @@
+JsonInput.HelloWorld.JsonOutput
+JsonInput.HelloWorld.ProtobufOutput
+ProtobufInput.PrematureEofBeforeUnknownValue.DOUBLE
+ProtobufInput.PrematureEofBeforeUnknownValue.FIXED32
+ProtobufInput.PrematureEofBeforeUnknownValue.FIXED64
+ProtobufInput.PrematureEofBeforeUnknownValue.FLOAT
+ProtobufInput.PrematureEofBeforeUnknownValue.SFIXED32
+ProtobufInput.PrematureEofBeforeUnknownValue.SFIXED64
+ProtobufInput.PrematureEofInDelimitedDataForUnknownValue.BYTES
+ProtobufInput.PrematureEofInDelimitedDataForUnknownValue.MESSAGE
+ProtobufInput.PrematureEofInDelimitedDataForUnknownValue.STRING
+ProtobufInput.PrematureEofInsideUnknownValue.DOUBLE
+ProtobufInput.PrematureEofInsideUnknownValue.FIXED32
+ProtobufInput.PrematureEofInsideUnknownValue.FIXED64
+ProtobufInput.PrematureEofInsideUnknownValue.FLOAT
+ProtobufInput.PrematureEofInsideUnknownValue.SFIXED32
+ProtobufInput.PrematureEofInsideUnknownValue.SFIXED64

+ 35 - 0
csharp/.gitignore

@@ -0,0 +1,35 @@
+#
+# 	Untracked directories
+#
+src/AddressBook/bin
+src/AddressBook/obj
+src/Google.Protobuf/bin/
+src/Google.Protobuf/obj/
+src/Google.Protobuf.Conformance/bin/
+src/Google.Protobuf.Conformance/obj/
+src/Google.Protobuf.Test/bin/
+src/Google.Protobuf.Test/obj/
+src/Google.Protobuf.JsonDump/bin/
+src/Google.Protobuf.JsonDump/obj/
+mono/bin
+mono/tmp
+mono/protoc
+build_output
+build_temp
+build/msbuild*.log
+lib/Microsoft.Silverlight.Testing
+lib/NUnit
+
+#
+# 	Untracked files
+#
+*.user
+*.suo
+*.nupkg
+_ReSharper.*
+*.sln.cache
+mono/TestResult.xml
+mono/.libs
+mono/*.exe
+mono/*.dll
+lib/protoc.exe

+ 148 - 0
csharp/CHANGES.txt

@@ -0,0 +1,148 @@
+===============================================================================
+Welcome to the C# port of Google Protocol Buffers, written by Jon Skeet
+(skeet@pobox.com) based on the work of many talented people.
+
+===============================================================================
+RELEASE NOTES - Code imported into Google's main protobuf repository
+===============================================================================
+
+Everything below note this represents history of protobuf-csharp-port project
+before the code was merged into csharp/ subtree of GitHub google/protobuf
+repository.
+Frozen legacy version of the original project is available in
+https://github.com/jskeet/protobuf-csharp-port.
+
+===============================================================================
+RELEASE NOTES - Version 2.4.1.555
+===============================================================================
+
+Changes:
+- Upgrade solution format to Visual Studio 2012.
+- Add the ability to print a builder (not just a message)
+- TextGenerator introduces a new overload of PrintTo
+- Munge protoc's error format into a VS-C#-compatible output format.
+- Work to make ProtoGen clone that acts as a protoc.exe plugin.
+- Added the AllowPartiallyTrustedCallers attribute
+- Optimized enum parsing.
+
+Fixes:
+- Fix for bug in limited input stream's Position, Introduced Position on 
+  output stream
+- Fix for writing a character to a JSON output overflows allocated buffer
+- Optimize FromBase64String to return Empty when presented with empty string.
+- Use string.Concat instead of operator to avoid potential import problems
+- Issue 81: quoting for NUnit parameters.
+- Issue 56: NuGet package is noisy
+- Issue 70: Portable library project has some invalid Nunit-based code.
+- Issue 71: CodedInputStream.ReadBytes go to slow path unnecessarily
+- Issue 84: warning CS0219: The variable `size' is assigned but never used
+
+===============================================================================
+RELEASE NOTES - Version 2.4.1.521
+===============================================================================
+
+Changes:
+- Add generated_code_attributes option, defaulted to false
+- Added support for Portable library
+- Added 'Unsafe' static type in ByteString to allow direct buffer access
+
+Fixes:
+- Issue 50: The XML serializer will fail to deserialize a message with empty 
+  child message
+- Issue 45: Use of 'item' as a field name causes AmbiguousMatchException
+- Issue 49: Generated nested static Types class should be partial
+- Issue 38: Disable CLSCompliant warnings (3021)
+- Issue 40: proto_path does not work for command-line file names
+- Issue 54: should retire all bytes in buffer (bufferSize)
+- Issue 43: Fix to correct identical 'umbrella_classname' options from trying 
+  to write to the same filename.
+
+===============================================================================
+RELEASE NOTES - Version 2.4.1.473
+===============================================================================
+
+Features:
+- Added option service_generator_type to control service generation with
+  NONE, GENERIC, INTERFACE, or IRPCDISPATCH
+- Added interfaces IRpcDispatch and IRpcServerStub to provide for blocking
+  services and implementations.
+- Added ProtoGen.exe command-line argument "--protoc_dir=" to specify the 
+  location of protoc.exe.
+- Extracted interfaces for ICodedInputStream and ICodedOutputStream to allow
+  custom implementation of writers with both speed and size optimizations.
+- Addition of the "Google.ProtoBuffers.Serialization" assembly to support
+  reading and writing messages to/from XML, JSON, IDictionary<,> and others.
+- Several performance related fixes and tweeks
+- Issue 3:	Add option to mark generated code with attribute
+- Issue 20:	Support for decorating classes [Serializable]
+- Issue 21:	Decorate fields with [deprecated=true] as [System.Obsolete]
+- Issue 22:	Reusable Builder classes
+- Issue 24:	Support for using Json/Xml formats with ICodedInputStream
+- Issue 25: Added support for NuGet packages
+- Issue 31: Upgraded protoc.exe and descriptor to 2.4.1
+
+Fixes:
+- Issue 13:	Message with Field same name as message causes uncompilable .cs
+- Issue 16:	Does not integrate well with other tooling
+- Issue 19:	Support for negative enum values
+- Issue 26:	AddRange in GeneratedBuilder iterates twice.
+- Issue 27:	Remove XML documentation output from test projects to clear 
+  warnings/errors.
+- Issue 28: Circular message dependencies result in null default values for 
+  Message fields.
+- Issue 29: Message classes generated have a public default constructor.  You
+  can disable private ctor generation with the option generate_private_ctor.
+- Issue 35: Fixed a bug in ProtoGen handling of arguments with trailing \
+- Big-endian support for float, and double on Silverlight
+- Packed and Unpacked parsing allow for all repeated, as per version 2.3
+- Fix for leaving Builder a public ctor on internal classes for use with
+  generic "where T: new()" constraints.
+
+Other:
+- Changed the code signing key to a privately held key
+- Reformatted all code and line-endings to C# defaults
+- Reworking of performance benchmarks to produce reliable results, option /v2
+- Issue 34: Silverlight assemblies are now unit tested
+
+===============================================================================
+RELEASE NOTES - Version 2.3.0.277
+===============================================================================
+
+Features:
+- Added cls_compliance option to generate attributes indicating 
+  non-CLS-compliance.
+- Added file_extension option to control the generated output file's extension.
+- Added umbrella_namespace option to place the umbrella class into a nested
+  namespace to address issues with proto files having the same name as a 
+  message it contains.
+- Added output_directory option to set the output path for the source file(s).
+- Added ignore_google_protobuf option to avoid generating code for includes 
+  from the google.protobuf package.
+- Added the LITE framework (Google.ProtoBuffersLite.dll) and the ability to
+  generate code with "option optimize_for = LITE_RUNTIME;".
+- Added ability to invoke protoc.exe from within ProtoGen.exe.
+- Upgraded to protoc.exe (2.3) compiler.
+
+Fixes:
+- Issue 9:	Class cannot be static and sealed error
+- Issue 12:	default value for enumerate fields must be filled out
+
+Other:
+- Rewrite of build using MSBbuild instead of NAnt
+- Moved to NUnit Version 2.2.8.0
+- Changed to using secure .snk for releases
+
+===============================================================================
+RELEASE NOTES - Version 0.9.1
+===============================================================================
+
+Fixes:
+- issue 10:	Incorrect encoding of packed fields when serialized
+
+===============================================================================
+RELEASE NOTES - Version 0.9.0
+===============================================================================
+
+- Initial release
+
+===============================================================================

+ 49 - 0
csharp/README.md

@@ -0,0 +1,49 @@
+This directory contains the C# Protocol Buffers runtime library.
+
+Warning: experimental!
+======================
+
+This code is still under significant churn. Unlike the original port,
+it only supports proto3 (but not *all* of proto3 yet) - there are no
+unknown fields or extensions, for example. protoc will (eventually)
+deliberately fail if it is asked to generate C# code for proto2
+messages other than descriptor.proto, which is still required for
+reflection. (It's currently exposed publicly, but won't be
+eventually.)
+
+Also unlike the original port, the new version embraces mutability -
+there are no builder types. We plan to add "freezing" operations as
+well as cloning, however.
+
+Usage
+=====
+
+Use `protoc` with the `--csharp_out` option to generate C# files in the specified directory.
+Include these in your C# project, and add a reference to the `Google.Protobuf` project. Currently
+there is no NuGet package for this, but we will be building one as soon as the API is stable.
+
+Supported platforms
+===================
+
+The runtime library is built as a portable class library, supporting:
+
+- .NET 4.5
+- Windows 8
+- Windows Phone Silverlight 8
+- Windows Phone 8.1
+- .NET Core (dnxcore)
+
+Building
+========
+
+Open the `src/Google.Protobuf.sln` solution in Visual Studio. Click "Build solution" to build the solution. You should be able to run the NUnit test from Test Explorer (you might need to install NUnit Visual Studio add-in).
+
+Supported Visual Studio versions are VS2013 (update 4) and VS2015. On Linux, you can also use Monodevelop 5.9 (older versions might work fine).
+
+History of C# protobufs
+=======================
+
+This subtree was originally imported from https://github.com/jskeet/protobuf-csharp-port
+and represents the latest development version of C# protobufs, that will now be developed
+and maintained by Google. All the development will be done in open, under this repository
+(https://github.com/google/protobuf).

+ 13 - 0
csharp/build_packages.bat

@@ -0,0 +1,13 @@
+@rem Builds Google.Protobuf NuGet packages
+
+@rem Adjust the location of nuget.exe
+set NUGET=C:\nuget\nuget.exe
+
+@rem Build src/Google.Protobuf.sln solution in Release configuration first.
+%NUGET% pack src\Google.Protobuf\Google.Protobuf.nuspec -Symbols || goto :error
+
+goto :EOF
+
+:error
+echo Failed!
+exit /b %errorlevel%

+ 17 - 0
csharp/buildall.sh

@@ -0,0 +1,17 @@
+#!/bin/bash
+# Use mono to build solution and run all tests.
+
+# Adjust these to reflect the location of nunit-console in your system.
+NUNIT_CONSOLE=nunit-console
+
+# The rest you can leave intact
+CONFIG=Release
+SRC=$(dirname $0)/src
+
+set -ex
+
+echo Building the solution.
+xbuild /p:Configuration=$CONFIG $SRC/Google.Protobuf.sln
+
+echo Running tests.
+$NUNIT_CONSOLE $SRC/Google.Protobuf.Test/bin/$CONFIG/Google.Protobuf.Test.dll

+ 73 - 0
csharp/generate_protos.sh

@@ -0,0 +1,73 @@
+#!/bin/bash
+# Generates C# source files from .proto files.
+# You first need to make sure protoc has been built (see instructions on
+# building protoc in root of this repository)
+
+# This script performs a few fix-ups as part of generation. These are:
+# - descriptor.proto is renamed to descriptor_proto_file.proto before
+#   generation, to avoid the naming collision between the class for the file
+#   descriptor and its Descriptor property
+# - This change also impacts UnittestCustomOptions, which expects to
+#   use a class of Descriptor when it's actually been renamed to
+#   DescriptorProtoFile.
+# - Issue 307 (codegen for double-nested types) breaks Unittest.proto and
+#   its lite equivalents.
+
+set -ex
+
+# cd to repository root
+cd $(dirname $0)/..
+
+# Protocol buffer compiler to use. If the PROTOC variable is set,
+# use that. Otherwise, probe for expected locations under both
+# Windows and Unix.
+if [ -z "$PROTOC" ]; then
+  # TODO(jonskeet): Use an array and a for loop instead?
+  if [ -x cmake/build/Debug/protoc.exe ]; then
+    PROTOC=cmake/build/Debug/protoc.exe
+  elif [ -x cmake/build/Release/protoc.exe ]; then
+    PROTOC=cmake/build/Release/protoc.exe
+  elif [ -x src/protoc ]; then
+    PROTOC=src/protoc
+  else
+    echo "Unable to find protocol buffer compiler."
+    exit 1
+  fi
+fi
+
+# Descriptor proto
+# TODO(jonskeet): Remove fixup
+cp src/google/protobuf/descriptor.proto src/google/protobuf/descriptor_proto_file.proto
+$PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf/Reflection \
+    src/google/protobuf/descriptor_proto_file.proto
+rm src/google/protobuf/descriptor_proto_file.proto
+
+$PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf/WellKnownTypes \
+    src/google/protobuf/any.proto \
+    src/google/protobuf/api.proto \
+    src/google/protobuf/duration.proto \
+    src/google/protobuf/empty.proto \
+    src/google/protobuf/field_mask.proto \
+    src/google/protobuf/source_context.proto \
+    src/google/protobuf/struct.proto \
+    src/google/protobuf/timestamp.proto \
+    src/google/protobuf/type.proto \
+    src/google/protobuf/wrappers.proto
+
+$PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf.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 \
+    src/google/protobuf/unittest_well_known_types.proto
+
+
+$PROTOC -Icsharp/protos --csharp_out=csharp/src/Google.Protobuf.Test/TestProtos \
+    csharp/protos/unittest_issues.proto
+
+# AddressBook sample protos
+$PROTOC -Iexamples --csharp_out=csharp/src/AddressBook \
+    examples/addressbook.proto
+
+$PROTOC -Iconformance --csharp_out=csharp/src/Google.Protobuf.Conformance \
+    conformance/conformance.proto

BIN
csharp/keys/Google.Protobuf.public.snk


+ 5 - 0
csharp/keys/README.md

@@ -0,0 +1,5 @@
+Contents
+--------
+
+- Google.Protobuf.public.snk:
+  Public key to verify strong name of Google.Protobuf assemblies.

+ 119 - 0
csharp/protos/unittest_issues.proto

@@ -0,0 +1,119 @@
+syntax = "proto3";
+
+// These proto descriptors have at one time been reported as an issue or defect.
+// They are kept here to replicate the issue, and continue to verify the fix.
+
+// Issue: Non-"Google.Protobuffers" namespace will ensure that protobuffer library types are qualified
+option csharp_namespace = "UnitTest.Issues.TestProtos";
+
+package unittest_issues;
+option optimize_for = SPEED;
+
+// Issue 307: when generating doubly-nested types, any references
+// should be of the form A.Types.B.Types.C.
+message Issue307 {
+  message NestedOnce {
+    message NestedTwice {
+    }
+  }
+}
+
+// Old issue 13: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=13
+// New issue 309: https://github.com/google/protobuf/issues/309
+ 
+// message A {
+//    optional int32 _A = 1;
+// }
+
+// message B {
+//    optional int32 B_ = 1;
+// }
+
+//message AB {
+//    optional int32 a_b = 1;
+//}
+
+// Similar issue with numeric names
+// Java code failed too, so probably best for this to be a restriction.
+// See https://github.com/google/protobuf/issues/308
+// message NumberField {
+//    optional int32 _01 = 1;
+// }
+
+// issue 19 - negative enum values
+
+enum NegativeEnum {
+    NEGATIVE_ENUM_ZERO = 0;
+    FiveBelow = -5;
+    MinusOne = -1;
+}
+
+message NegativeEnumMessage {
+    NegativeEnum value = 1;
+    repeated NegativeEnum values = 2 [packed = false];
+    repeated NegativeEnum packed_values = 3 [packed=true];
+}
+
+// Issue 21: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=21
+// Decorate fields with [deprecated=true] as [System.Obsolete]
+
+message DeprecatedChild {
+}
+
+enum DeprecatedEnum {
+    DEPRECATED_ZERO = 0;
+    one = 1;
+}
+
+message DeprecatedFieldsMessage {
+    int32 PrimitiveValue = 1 [deprecated = true];
+    repeated int32 PrimitiveArray = 2 [deprecated = true];
+
+    DeprecatedChild MessageValue = 3 [deprecated = true];
+    repeated DeprecatedChild MessageArray = 4 [deprecated = true];
+
+    DeprecatedEnum EnumValue = 5 [deprecated = true];
+    repeated DeprecatedEnum EnumArray = 6 [deprecated = true];
+}
+
+// Issue 45: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=45
+message ItemField {
+  int32 item = 1;
+}
+
+message ReservedNames {
+  // Force a nested type called Types
+  message SomeNestedType {
+  }
+
+  int32 types = 1;
+  int32 descriptor = 2;
+}
+
+message TestJsonFieldOrdering {
+  // These fields are deliberately not declared in numeric
+  // order, and the oneof fields aren't contiguous either.
+  // This allows for reasonably robust tests of JSON output
+  // ordering.
+  // TestFieldOrderings in unittest_proto3.proto is similar,
+  // but doesn't include oneofs.
+  // TODO: Consider adding oneofs to TestFieldOrderings, although
+  // that will require fixing other tests in multiple platforms.
+  // Alternatively, consider just adding this to
+  // unittest_proto3.proto if multiple platforms want it.
+  
+  int32 plain_int32 = 4;
+
+  oneof o1 {
+    string o1_string = 2;
+    int32 o1_int32 = 5;
+  }
+  
+  string plain_string = 1;
+  
+  oneof o2 {
+    int32 o2_int32 = 6;
+    string o2_string = 3;
+  }
+  
+}

+ 132 - 0
csharp/src/AddressBook/AddPerson.cs

@@ -0,0 +1,132 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.IO;
+
+namespace Google.Protobuf.Examples.AddressBook
+{
+    internal class AddPerson
+    {
+        /// <summary>
+        /// Builds a person based on user input
+        /// </summary>
+        private static Person PromptForAddress(TextReader input, TextWriter output)
+        {
+            Person person = new Person();
+
+            output.Write("Enter person ID: ");
+            person.Id = int.Parse(input.ReadLine());
+
+            output.Write("Enter name: ");
+            person.Name = input.ReadLine();
+
+            output.Write("Enter email address (blank for none): ");
+            string email = input.ReadLine();
+            if (email.Length > 0)
+            {
+                person.Email = email;
+            }
+
+            while (true)
+            {
+                output.Write("Enter a phone number (or leave blank to finish): ");
+                string number = input.ReadLine();
+                if (number.Length == 0)
+                {
+                    break;
+                }
+
+                Person.Types.PhoneNumber phoneNumber = new Person.Types.PhoneNumber { Number = number };
+
+                output.Write("Is this a mobile, home, or work phone? ");
+                String type = input.ReadLine();
+                switch (type)
+                {
+                    case "mobile":
+                        phoneNumber.Type = Person.Types.PhoneType.MOBILE;
+                        break;
+                    case "home":
+                        phoneNumber.Type = Person.Types.PhoneType.HOME;
+                        break;
+                    case "work":
+                        phoneNumber.Type = Person.Types.PhoneType.WORK;
+                        break;
+                    default:
+                        output.Write("Unknown phone type. Using default.");
+                        break;
+                }
+
+                person.Phones.Add(phoneNumber);
+            }
+            return person;
+        }
+
+        /// <summary>
+        /// Entry point - loads an existing addressbook or creates a new one,
+        /// then writes it back to the file.
+        /// </summary>
+        public static int Main(string[] args)
+        {
+            if (args.Length != 1)
+            {
+                Console.Error.WriteLine("Usage:  AddPerson ADDRESS_BOOK_FILE");
+                return -1;
+            }
+
+            AddressBook addressBook;
+
+            if (File.Exists(args[0]))
+            {
+                using (Stream file = File.OpenRead(args[0]))
+                {
+                    addressBook = AddressBook.Parser.ParseFrom(file);
+                }
+            }
+            else
+            {
+                Console.WriteLine("{0}: File not found. Creating a new file.", args[0]);
+                addressBook = new AddressBook();
+            }
+
+            // Add an address.
+            addressBook.People.Add(PromptForAddress(Console.In, Console.Out));
+
+            // Write the new address book back to disk.
+            using (Stream output = File.OpenWrite(args[0]))
+            {
+                addressBook.WriteTo(output);
+            }
+            return 0;
+        }
+    }
+}

+ 75 - 0
csharp/src/AddressBook/AddressBook.csproj

@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{A31F5FB2-4FF3-432A-B35B-5CD203606311}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Google.Protobuf.Examples.AddressBook</RootNamespace>
+    <AssemblyName>AddressBook</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <StartupObject>Google.Protobuf.Examples.AddressBook.Program</StartupObject>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <IntermediateOutputPath>obj\Debug\</IntermediateOutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <NoStdLib>true</NoStdLib>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <IntermediateOutputPath>obj\Release\</IntermediateOutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <NoStdLib>true</NoStdLib>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="mscorlib" />
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AddPerson.cs" />
+    <Compile Include="Addressbook.cs" />
+    <Compile Include="SampleUsage.cs" />
+    <Compile Include="ListPeople.cs" />
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Google.Protobuf\Google.Protobuf.csproj">
+      <Project>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</Project>
+      <Name>Google.Protobuf</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="app.config" />
+  </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.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

+ 454 - 0
csharp/src/AddressBook/Addressbook.cs

@@ -0,0 +1,454 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: addressbook.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.Examples.AddressBook {
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class Addressbook {
+
+    #region Descriptor
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static Addressbook() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "ChFhZGRyZXNzYm9vay5wcm90bxIIdHV0b3JpYWwi1QEKBlBlcnNvbhIMCgRu", 
+            "YW1lGAEgASgJEgoKAmlkGAIgASgFEg0KBWVtYWlsGAMgASgJEiwKBnBob25l", 
+            "cxgEIAMoCzIcLnR1dG9yaWFsLlBlcnNvbi5QaG9uZU51bWJlchpHCgtQaG9u", 
+            "ZU51bWJlchIOCgZudW1iZXIYASABKAkSKAoEdHlwZRgCIAEoDjIaLnR1dG9y", 
+            "aWFsLlBlcnNvbi5QaG9uZVR5cGUiKwoJUGhvbmVUeXBlEgoKBk1PQklMRRAA", 
+            "EggKBEhPTUUQARIICgRXT1JLEAIiLwoLQWRkcmVzc0Jvb2sSIAoGcGVvcGxl", 
+            "GAEgAygLMhAudHV0b3JpYWwuUGVyc29uQlAKFGNvbS5leGFtcGxlLnR1dG9y", 
+            "aWFsQhFBZGRyZXNzQm9va1Byb3Rvc6oCJEdvb2dsZS5Qcm90b2J1Zi5FeGFt", 
+            "cGxlcy5BZGRyZXNzQm9va2IGcHJvdG8z"));
+      descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.Person), new[]{ "Name", "Id", "Email", "Phones" }, null, new[]{ typeof(global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType) }, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber), new[]{ "Number", "Type" }, null, null, null)}),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.AddressBook), new[]{ "People" }, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Messages
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Person : pb::IMessage<Person> {
+    private static readonly pb::MessageParser<Person> _parser = new pb::MessageParser<Person>(() => new Person());
+    public static pb::MessageParser<Person> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Examples.AddressBook.Addressbook.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Person() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Person(Person other) : this() {
+      name_ = other.name_;
+      id_ = other.id_;
+      email_ = other.email_;
+      phones_ = other.phones_.Clone();
+    }
+
+    public Person Clone() {
+      return new Person(this);
+    }
+
+    public const int NameFieldNumber = 1;
+    private string name_ = "";
+    public string Name {
+      get { return name_; }
+      set {
+        name_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public const int IdFieldNumber = 2;
+    private int id_;
+    public int Id {
+      get { return id_; }
+      set {
+        id_ = value;
+      }
+    }
+
+    public const int EmailFieldNumber = 3;
+    private string email_ = "";
+    public string Email {
+      get { return email_; }
+      set {
+        email_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public const int PhonesFieldNumber = 4;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber> _repeated_phones_codec
+        = pb::FieldCodec.ForMessage(34, global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber> phones_ = new pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber>();
+    public pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber> Phones {
+      get { return phones_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Person);
+    }
+
+    public bool Equals(Person other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Name != other.Name) return false;
+      if (Id != other.Id) return false;
+      if (Email != other.Email) return false;
+      if(!phones_.Equals(other.phones_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Name.Length != 0) hash ^= Name.GetHashCode();
+      if (Id != 0) hash ^= Id.GetHashCode();
+      if (Email.Length != 0) hash ^= Email.GetHashCode();
+      hash ^= phones_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Name.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Name);
+      }
+      if (Id != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Id);
+      }
+      if (Email.Length != 0) {
+        output.WriteRawTag(26);
+        output.WriteString(Email);
+      }
+      phones_.WriteTo(output, _repeated_phones_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Name.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+      }
+      if (Id != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Id);
+      }
+      if (Email.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Email);
+      }
+      size += phones_.CalculateSize(_repeated_phones_codec);
+      return size;
+    }
+
+    public void MergeFrom(Person other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Name.Length != 0) {
+        Name = other.Name;
+      }
+      if (other.Id != 0) {
+        Id = other.Id;
+      }
+      if (other.Email.Length != 0) {
+        Email = other.Email;
+      }
+      phones_.Add(other.phones_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Name = input.ReadString();
+            break;
+          }
+          case 16: {
+            Id = input.ReadInt32();
+            break;
+          }
+          case 26: {
+            Email = input.ReadString();
+            break;
+          }
+          case 34: {
+            phones_.AddEntriesFrom(input, _repeated_phones_codec);
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      public enum PhoneType {
+        MOBILE = 0,
+        HOME = 1,
+        WORK = 2,
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class PhoneNumber : pb::IMessage<PhoneNumber> {
+        private static readonly pb::MessageParser<PhoneNumber> _parser = new pb::MessageParser<PhoneNumber>(() => new PhoneNumber());
+        public static pb::MessageParser<PhoneNumber> Parser { get { return _parser; } }
+
+        public static pbr::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.Examples.AddressBook.Person.Descriptor.NestedTypes[0]; }
+        }
+
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
+        }
+
+        public PhoneNumber() {
+          OnConstruction();
+        }
+
+        partial void OnConstruction();
+
+        public PhoneNumber(PhoneNumber other) : this() {
+          number_ = other.number_;
+          type_ = other.type_;
+        }
+
+        public PhoneNumber Clone() {
+          return new PhoneNumber(this);
+        }
+
+        public const int NumberFieldNumber = 1;
+        private string number_ = "";
+        public string Number {
+          get { return number_; }
+          set {
+            number_ = pb::Preconditions.CheckNotNull(value, "value");
+          }
+        }
+
+        public const int TypeFieldNumber = 2;
+        private global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType type_ = global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.MOBILE;
+        public global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType Type {
+          get { return type_; }
+          set {
+            type_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as PhoneNumber);
+        }
+
+        public bool Equals(PhoneNumber other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Number != other.Number) return false;
+          if (Type != other.Type) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Number.Length != 0) hash ^= Number.GetHashCode();
+          if (Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.MOBILE) hash ^= Type.GetHashCode();
+          return hash;
+        }
+
+        public override string ToString() {
+          return pb::JsonFormatter.Default.Format(this);
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Number.Length != 0) {
+            output.WriteRawTag(10);
+            output.WriteString(Number);
+          }
+          if (Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.MOBILE) {
+            output.WriteRawTag(16);
+            output.WriteEnum((int) Type);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Number.Length != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeStringSize(Number);
+          }
+          if (Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.MOBILE) {
+            size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type);
+          }
+          return size;
+        }
+
+        public void MergeFrom(PhoneNumber other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Number.Length != 0) {
+            Number = other.Number;
+          }
+          if (other.Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.MOBILE) {
+            Type = other.Type;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                input.SkipLastField();
+                break;
+              case 10: {
+                Number = input.ReadString();
+                break;
+              }
+              case 16: {
+                type_ = (global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType) input.ReadEnum();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class AddressBook : pb::IMessage<AddressBook> {
+    private static readonly pb::MessageParser<AddressBook> _parser = new pb::MessageParser<AddressBook>(() => new AddressBook());
+    public static pb::MessageParser<AddressBook> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Examples.AddressBook.Addressbook.Descriptor.MessageTypes[1]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public AddressBook() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public AddressBook(AddressBook other) : this() {
+      people_ = other.people_.Clone();
+    }
+
+    public AddressBook Clone() {
+      return new AddressBook(this);
+    }
+
+    public const int PeopleFieldNumber = 1;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Examples.AddressBook.Person> _repeated_people_codec
+        = pb::FieldCodec.ForMessage(10, global::Google.Protobuf.Examples.AddressBook.Person.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person> people_ = new pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person>();
+    public pbc::RepeatedField<global::Google.Protobuf.Examples.AddressBook.Person> People {
+      get { return people_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as AddressBook);
+    }
+
+    public bool Equals(AddressBook other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!people_.Equals(other.people_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= people_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      people_.WriteTo(output, _repeated_people_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += people_.CalculateSize(_repeated_people_codec);
+      return size;
+    }
+
+    public void MergeFrom(AddressBook other) {
+      if (other == null) {
+        return;
+      }
+      people_.Add(other.people_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            people_.AddEntriesFrom(input, _repeated_people_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code

+ 99 - 0
csharp/src/AddressBook/ListPeople.cs

@@ -0,0 +1,99 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.IO;
+
+namespace Google.Protobuf.Examples.AddressBook
+{
+    internal class ListPeople
+    {
+        /// <summary>
+        /// Iterates though all people in the AddressBook and prints info about them.
+        /// </summary>
+        private static void Print(AddressBook addressBook)
+        {
+            foreach (Person person in addressBook.People)
+            {
+                Console.WriteLine("Person ID: {0}", person.Id);
+                Console.WriteLine("  Name: {0}", person.Name);
+                if (person.Email != "")
+                {
+                    Console.WriteLine("  E-mail address: {0}", person.Email);
+                }
+
+                foreach (Person.Types.PhoneNumber phoneNumber in person.Phones)
+                {
+                    switch (phoneNumber.Type)
+                    {
+                        case Person.Types.PhoneType.MOBILE:
+                            Console.Write("  Mobile phone #: ");
+                            break;
+                        case Person.Types.PhoneType.HOME:
+                            Console.Write("  Home phone #: ");
+                            break;
+                        case Person.Types.PhoneType.WORK:
+                            Console.Write("  Work phone #: ");
+                            break;
+                    }
+                    Console.WriteLine(phoneNumber.Number);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Entry point - loads the addressbook and then displays it.
+        /// </summary>
+        public static int Main(string[] args)
+        {
+            if (args.Length != 1)
+            {
+                Console.Error.WriteLine("Usage:  ListPeople ADDRESS_BOOK_FILE");
+                return 1;
+            }
+
+            if (!File.Exists(args[0]))
+            {
+                Console.WriteLine("{0} doesn't exist. Add a person to create the file first.", args[0]);
+                return 0;
+            }
+
+            // Read the existing address book.
+            using (Stream stream = File.OpenRead(args[0]))
+            {
+                AddressBook addressBook = AddressBook.Parser.ParseFrom(stream);
+                Print(addressBook);
+            }
+            return 0;
+        }
+    }
+}

+ 95 - 0
csharp/src/AddressBook/Program.cs

@@ -0,0 +1,95 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+
+namespace Google.Protobuf.Examples.AddressBook
+{
+    /// <summary>
+    /// Entry point. Repeatedly prompts user for an action to take, delegating actual behaviour
+    /// to individual actions. Each action has its own Main method, so that it can be used as an
+    /// invidual complete program.
+    /// </summary>
+    internal class Program
+    {
+        private static int Main(string[] args)
+        {
+            if (args.Length > 1)
+            {
+                Console.Error.WriteLine("Usage: AddressBook [file]");
+                Console.Error.WriteLine("If the filename isn't specified, \"addressbook.data\" is used instead.");
+                return 1;
+            }
+            string addressBookFile = args.Length > 0 ? args[0] : "addressbook.data";
+
+            bool stopping = false;
+            while (!stopping)
+            {
+                Console.WriteLine("Options:");
+                Console.WriteLine("  L: List contents");
+                Console.WriteLine("  A: Add new person");
+                Console.WriteLine("  Q: Quit");
+                Console.Write("Action? ");
+                Console.Out.Flush();
+                char choice = Console.ReadKey().KeyChar;
+                Console.WriteLine();
+                try
+                {
+                    switch (choice)
+                    {
+                        case 'A':
+                        case 'a':
+                            AddPerson.Main(new string[] {addressBookFile});
+                            break;
+                        case 'L':
+                        case 'l':
+                            ListPeople.Main(new string[] {addressBookFile});
+                            break;
+                        case 'Q':
+                        case 'q':
+                            stopping = true;
+                            break;
+                        default:
+                            Console.WriteLine("Unknown option: {0}", choice);
+                            break;
+                    }
+                }
+                catch (Exception e)
+                {
+                    Console.WriteLine("Exception executing action: {0}", e);
+                }
+                Console.WriteLine();
+            }
+            return 0;
+        }
+    }
+}

+ 18 - 0
csharp/src/AddressBook/Properties/AssemblyInfo.cs

@@ -0,0 +1,18 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("AddressBook")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("AddressBook")]
+[assembly: AssemblyCopyright("Copyright ©  2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: AssemblyVersion("3.0.0.0")]
+[assembly: AssemblyFileVersion("3.0.0.0")]

+ 70 - 0
csharp/src/AddressBook/SampleUsage.cs

@@ -0,0 +1,70 @@
+#region Copyright notice and license
+// 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.
+#endregion
+    
+using System;
+using System.IO;
+
+namespace Google.Protobuf.Examples.AddressBook
+{
+    internal class SampleUsage
+    {
+        private static void Main()
+        {
+            byte[] bytes;
+            // Create a new person
+            Person person = new Person
+            {
+                Id = 1,
+                Name = "Foo",
+                Email = "foo@bar",
+                Phones = { new Person.Types.PhoneNumber { Number = "555-1212" } }
+            };
+            using (MemoryStream stream = new MemoryStream())
+            {
+                // Save the person to a stream
+                person.WriteTo(stream);
+                bytes = stream.ToArray();
+            }
+            Person copy = Person.Parser.ParseFrom(bytes);
+
+            // A more streamlined approach might look like this:
+            bytes = copy.ToByteArray();
+            // And read the address book back again
+            AddressBook restored = AddressBook.Parser.ParseFrom(bytes);
+            // The message performs a deep-comparison on equality:
+            if (restored.People.Count != 1 || !person.Equals(restored.People[0]))
+            {
+                throw new ApplicationException("There is a bad person in here!");
+            }
+        }
+    }
+}

+ 3 - 0
csharp/src/AddressBook/app.config

@@ -0,0 +1,3 @@
+<?xml version="1.0"?>
+<configuration>
+	<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>

+ 6 - 0
csharp/src/Google.Protobuf.Conformance/App.config

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+    <startup> 
+        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
+    </startup>
+</configuration>

+ 2380 - 0
csharp/src/Google.Protobuf.Conformance/Conformance.cs

@@ -0,0 +1,2380 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: conformance.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Conformance {
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class Conformance {
+
+    #region Descriptor
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static Conformance() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "ChFjb25mb3JtYW5jZS5wcm90bxILY29uZm9ybWFuY2UijQEKEkNvbmZvcm1h", 
+            "bmNlUmVxdWVzdBIaChBwcm90b2J1Zl9wYXlsb2FkGAEgASgMSAASFgoManNv", 
+            "bl9wYXlsb2FkGAIgASgJSAASOAoXcmVxdWVzdGVkX291dHB1dF9mb3JtYXQY", 
+            "AyABKA4yFy5jb25mb3JtYW5jZS5XaXJlRm9ybWF0QgkKB3BheWxvYWQilgEK", 
+            "E0NvbmZvcm1hbmNlUmVzcG9uc2USFQoLcGFyc2VfZXJyb3IYASABKAlIABIX", 
+            "Cg1ydW50aW1lX2Vycm9yGAIgASgJSAASGgoQcHJvdG9idWZfcGF5bG9hZBgD", 
+            "IAEoDEgAEhYKDGpzb25fcGF5bG9hZBgEIAEoCUgAEhEKB3NraXBwZWQYBSAB", 
+            "KAlIAEIICgZyZXN1bHQi6yIKDFRlc3RBbGxUeXBlcxIWCg5vcHRpb25hbF9p", 
+            "bnQzMhgBIAEoBRIWCg5vcHRpb25hbF9pbnQ2NBgCIAEoAxIXCg9vcHRpb25h", 
+            "bF91aW50MzIYAyABKA0SFwoPb3B0aW9uYWxfdWludDY0GAQgASgEEhcKD29w", 
+            "dGlvbmFsX3NpbnQzMhgFIAEoERIXCg9vcHRpb25hbF9zaW50NjQYBiABKBIS", 
+            "GAoQb3B0aW9uYWxfZml4ZWQzMhgHIAEoBxIYChBvcHRpb25hbF9maXhlZDY0", 
+            "GAggASgGEhkKEW9wdGlvbmFsX3NmaXhlZDMyGAkgASgPEhkKEW9wdGlvbmFs", 
+            "X3NmaXhlZDY0GAogASgQEhYKDm9wdGlvbmFsX2Zsb2F0GAsgASgCEhcKD29w", 
+            "dGlvbmFsX2RvdWJsZRgMIAEoARIVCg1vcHRpb25hbF9ib29sGA0gASgIEhcK", 
+            "D29wdGlvbmFsX3N0cmluZxgOIAEoCRIWCg5vcHRpb25hbF9ieXRlcxgPIAEo", 
+            "DBJIChdvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZRgSIAEoCzInLmNvbmZvcm1h", 
+            "bmNlLlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlEj0KGG9wdGlvbmFsX2Zv", 
+            "cmVpZ25fbWVzc2FnZRgTIAEoCzIbLmNvbmZvcm1hbmNlLkZvcmVpZ25NZXNz", 
+            "YWdlEkIKFG9wdGlvbmFsX25lc3RlZF9lbnVtGBUgASgOMiQuY29uZm9ybWFu", 
+            "Y2UuVGVzdEFsbFR5cGVzLk5lc3RlZEVudW0SNwoVb3B0aW9uYWxfZm9yZWln", 
+            "bl9lbnVtGBYgASgOMhguY29uZm9ybWFuY2UuRm9yZWlnbkVudW0SIQoVb3B0", 
+            "aW9uYWxfc3RyaW5nX3BpZWNlGBggASgJQgIIAhIZCg1vcHRpb25hbF9jb3Jk", 
+            "GBkgASgJQgIIARI0ChFyZWN1cnNpdmVfbWVzc2FnZRgbIAEoCzIZLmNvbmZv", 
+            "cm1hbmNlLlRlc3RBbGxUeXBlcxIWCg5yZXBlYXRlZF9pbnQzMhgfIAMoBRIW", 
+            "Cg5yZXBlYXRlZF9pbnQ2NBggIAMoAxIXCg9yZXBlYXRlZF91aW50MzIYISAD", 
+            "KA0SFwoPcmVwZWF0ZWRfdWludDY0GCIgAygEEhcKD3JlcGVhdGVkX3NpbnQz", 
+            "MhgjIAMoERIXCg9yZXBlYXRlZF9zaW50NjQYJCADKBISGAoQcmVwZWF0ZWRf", 
+            "Zml4ZWQzMhglIAMoBxIYChByZXBlYXRlZF9maXhlZDY0GCYgAygGEhkKEXJl", 
+            "cGVhdGVkX3NmaXhlZDMyGCcgAygPEhkKEXJlcGVhdGVkX3NmaXhlZDY0GCgg", 
+            "AygQEhYKDnJlcGVhdGVkX2Zsb2F0GCkgAygCEhcKD3JlcGVhdGVkX2RvdWJs", 
+            "ZRgqIAMoARIVCg1yZXBlYXRlZF9ib29sGCsgAygIEhcKD3JlcGVhdGVkX3N0", 
+            "cmluZxgsIAMoCRIWCg5yZXBlYXRlZF9ieXRlcxgtIAMoDBJIChdyZXBlYXRl", 
+            "ZF9uZXN0ZWRfbWVzc2FnZRgwIAMoCzInLmNvbmZvcm1hbmNlLlRlc3RBbGxU", 
+            "eXBlcy5OZXN0ZWRNZXNzYWdlEj0KGHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2Fn", 
+            "ZRgxIAMoCzIbLmNvbmZvcm1hbmNlLkZvcmVpZ25NZXNzYWdlEkIKFHJlcGVh", 
+            "dGVkX25lc3RlZF9lbnVtGDMgAygOMiQuY29uZm9ybWFuY2UuVGVzdEFsbFR5", 
+            "cGVzLk5lc3RlZEVudW0SNwoVcmVwZWF0ZWRfZm9yZWlnbl9lbnVtGDQgAygO", 
+            "MhguY29uZm9ybWFuY2UuRm9yZWlnbkVudW0SIQoVcmVwZWF0ZWRfc3RyaW5n", 
+            "X3BpZWNlGDYgAygJQgIIAhIZCg1yZXBlYXRlZF9jb3JkGDcgAygJQgIIARJF", 
+            "Cg9tYXBfaW50MzJfaW50MzIYOCADKAsyLC5jb25mb3JtYW5jZS5UZXN0QWxs", 
+            "VHlwZXMuTWFwSW50MzJJbnQzMkVudHJ5EkUKD21hcF9pbnQ2NF9pbnQ2NBg5", 
+            "IAMoCzIsLmNvbmZvcm1hbmNlLlRlc3RBbGxUeXBlcy5NYXBJbnQ2NEludDY0", 
+            "RW50cnkSSQoRbWFwX3VpbnQzMl91aW50MzIYOiADKAsyLi5jb25mb3JtYW5j", 
+            "ZS5UZXN0QWxsVHlwZXMuTWFwVWludDMyVWludDMyRW50cnkSSQoRbWFwX3Vp", 
+            "bnQ2NF91aW50NjQYOyADKAsyLi5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMu", 
+            "TWFwVWludDY0VWludDY0RW50cnkSSQoRbWFwX3NpbnQzMl9zaW50MzIYPCAD", 
+            "KAsyLi5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFwU2ludDMyU2ludDMy", 
+            "RW50cnkSSQoRbWFwX3NpbnQ2NF9zaW50NjQYPSADKAsyLi5jb25mb3JtYW5j", 
+            "ZS5UZXN0QWxsVHlwZXMuTWFwU2ludDY0U2ludDY0RW50cnkSTQoTbWFwX2Zp", 
+            "eGVkMzJfZml4ZWQzMhg+IAMoCzIwLmNvbmZvcm1hbmNlLlRlc3RBbGxUeXBl", 
+            "cy5NYXBGaXhlZDMyRml4ZWQzMkVudHJ5Ek0KE21hcF9maXhlZDY0X2ZpeGVk", 
+            "NjQYPyADKAsyMC5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFwRml4ZWQ2", 
+            "NEZpeGVkNjRFbnRyeRJRChVtYXBfc2ZpeGVkMzJfc2ZpeGVkMzIYQCADKAsy", 
+            "Mi5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFwU2ZpeGVkMzJTZml4ZWQz", 
+            "MkVudHJ5ElEKFW1hcF9zZml4ZWQ2NF9zZml4ZWQ2NBhBIAMoCzIyLmNvbmZv", 
+            "cm1hbmNlLlRlc3RBbGxUeXBlcy5NYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnkS", 
+            "RQoPbWFwX2ludDMyX2Zsb2F0GEIgAygLMiwuY29uZm9ybWFuY2UuVGVzdEFs", 
+            "bFR5cGVzLk1hcEludDMyRmxvYXRFbnRyeRJHChBtYXBfaW50MzJfZG91Ymxl", 
+            "GEMgAygLMi0uY29uZm9ybWFuY2UuVGVzdEFsbFR5cGVzLk1hcEludDMyRG91", 
+            "YmxlRW50cnkSQQoNbWFwX2Jvb2xfYm9vbBhEIAMoCzIqLmNvbmZvcm1hbmNl", 
+            "LlRlc3RBbGxUeXBlcy5NYXBCb29sQm9vbEVudHJ5EkkKEW1hcF9zdHJpbmdf", 
+            "c3RyaW5nGEUgAygLMi4uY29uZm9ybWFuY2UuVGVzdEFsbFR5cGVzLk1hcFN0", 
+            "cmluZ1N0cmluZ0VudHJ5EkcKEG1hcF9zdHJpbmdfYnl0ZXMYRiADKAsyLS5j", 
+            "b25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTWFwU3RyaW5nQnl0ZXNFbnRyeRJY", 
+            "ChltYXBfc3RyaW5nX25lc3RlZF9tZXNzYWdlGEcgAygLMjUuY29uZm9ybWFu", 
+            "Y2UuVGVzdEFsbFR5cGVzLk1hcFN0cmluZ05lc3RlZE1lc3NhZ2VFbnRyeRJa", 
+            "ChptYXBfc3RyaW5nX2ZvcmVpZ25fbWVzc2FnZRhIIAMoCzI2LmNvbmZvcm1h", 
+            "bmNlLlRlc3RBbGxUeXBlcy5NYXBTdHJpbmdGb3JlaWduTWVzc2FnZUVudHJ5", 
+            "ElIKFm1hcF9zdHJpbmdfbmVzdGVkX2VudW0YSSADKAsyMi5jb25mb3JtYW5j", 
+            "ZS5UZXN0QWxsVHlwZXMuTWFwU3RyaW5nTmVzdGVkRW51bUVudHJ5ElQKF21h", 
+            "cF9zdHJpbmdfZm9yZWlnbl9lbnVtGEogAygLMjMuY29uZm9ybWFuY2UuVGVz", 
+            "dEFsbFR5cGVzLk1hcFN0cmluZ0ZvcmVpZ25FbnVtRW50cnkSFgoMb25lb2Zf", 
+            "dWludDMyGG8gASgNSAASRwoUb25lb2ZfbmVzdGVkX21lc3NhZ2UYcCABKAsy", 
+            "Jy5jb25mb3JtYW5jZS5UZXN0QWxsVHlwZXMuTmVzdGVkTWVzc2FnZUgAEhYK", 
+            "DG9uZW9mX3N0cmluZxhxIAEoCUgAEhUKC29uZW9mX2J5dGVzGHIgASgMSAAa", 
+            "SgoNTmVzdGVkTWVzc2FnZRIJCgFhGAEgASgFEi4KC2NvcmVjdXJzaXZlGAIg", 
+            "ASgLMhkuY29uZm9ybWFuY2UuVGVzdEFsbFR5cGVzGjQKEk1hcEludDMySW50", 
+            "MzJFbnRyeRILCgNrZXkYASABKAUSDQoFdmFsdWUYAiABKAU6AjgBGjQKEk1h", 
+            "cEludDY0SW50NjRFbnRyeRILCgNrZXkYASABKAMSDQoFdmFsdWUYAiABKAM6", 
+            "AjgBGjYKFE1hcFVpbnQzMlVpbnQzMkVudHJ5EgsKA2tleRgBIAEoDRINCgV2", 
+            "YWx1ZRgCIAEoDToCOAEaNgoUTWFwVWludDY0VWludDY0RW50cnkSCwoDa2V5", 
+            "GAEgASgEEg0KBXZhbHVlGAIgASgEOgI4ARo2ChRNYXBTaW50MzJTaW50MzJF", 
+            "bnRyeRILCgNrZXkYASABKBESDQoFdmFsdWUYAiABKBE6AjgBGjYKFE1hcFNp", 
+            "bnQ2NFNpbnQ2NEVudHJ5EgsKA2tleRgBIAEoEhINCgV2YWx1ZRgCIAEoEjoC", 
+            "OAEaOAoWTWFwRml4ZWQzMkZpeGVkMzJFbnRyeRILCgNrZXkYASABKAcSDQoF", 
+            "dmFsdWUYAiABKAc6AjgBGjgKFk1hcEZpeGVkNjRGaXhlZDY0RW50cnkSCwoD", 
+            "a2V5GAEgASgGEg0KBXZhbHVlGAIgASgGOgI4ARo6ChhNYXBTZml4ZWQzMlNm", 
+            "aXhlZDMyRW50cnkSCwoDa2V5GAEgASgPEg0KBXZhbHVlGAIgASgPOgI4ARo6", 
+            "ChhNYXBTZml4ZWQ2NFNmaXhlZDY0RW50cnkSCwoDa2V5GAEgASgQEg0KBXZh", 
+            "bHVlGAIgASgQOgI4ARo0ChJNYXBJbnQzMkZsb2F0RW50cnkSCwoDa2V5GAEg", 
+            "ASgFEg0KBXZhbHVlGAIgASgCOgI4ARo1ChNNYXBJbnQzMkRvdWJsZUVudHJ5", 
+            "EgsKA2tleRgBIAEoBRINCgV2YWx1ZRgCIAEoAToCOAEaMgoQTWFwQm9vbEJv", 
+            "b2xFbnRyeRILCgNrZXkYASABKAgSDQoFdmFsdWUYAiABKAg6AjgBGjYKFE1h", 
+            "cFN0cmluZ1N0cmluZ0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEo", 
+            "CToCOAEaNQoTTWFwU3RyaW5nQnl0ZXNFbnRyeRILCgNrZXkYASABKAkSDQoF", 
+            "dmFsdWUYAiABKAw6AjgBGmYKG01hcFN0cmluZ05lc3RlZE1lc3NhZ2VFbnRy", 
+            "eRILCgNrZXkYASABKAkSNgoFdmFsdWUYAiABKAsyJy5jb25mb3JtYW5jZS5U", 
+            "ZXN0QWxsVHlwZXMuTmVzdGVkTWVzc2FnZToCOAEaWwocTWFwU3RyaW5nRm9y", 
+            "ZWlnbk1lc3NhZ2VFbnRyeRILCgNrZXkYASABKAkSKgoFdmFsdWUYAiABKAsy", 
+            "Gy5jb25mb3JtYW5jZS5Gb3JlaWduTWVzc2FnZToCOAEaYAoYTWFwU3RyaW5n", 
+            "TmVzdGVkRW51bUVudHJ5EgsKA2tleRgBIAEoCRIzCgV2YWx1ZRgCIAEoDjIk", 
+            "LmNvbmZvcm1hbmNlLlRlc3RBbGxUeXBlcy5OZXN0ZWRFbnVtOgI4ARpVChlN", 
+            "YXBTdHJpbmdGb3JlaWduRW51bUVudHJ5EgsKA2tleRgBIAEoCRInCgV2YWx1", 
+            "ZRgCIAEoDjIYLmNvbmZvcm1hbmNlLkZvcmVpZ25FbnVtOgI4ASI5CgpOZXN0", 
+            "ZWRFbnVtEgcKA0ZPTxAAEgcKA0JBUhABEgcKA0JBWhACEhAKA05FRxD/////", 
+            "//////8BQg0KC29uZW9mX2ZpZWxkIhsKDkZvcmVpZ25NZXNzYWdlEgkKAWMY", 
+            "ASABKAUqNQoKV2lyZUZvcm1hdBIPCgtVTlNQRUNJRklFRBAAEgwKCFBST1RP", 
+            "QlVGEAESCAoESlNPThACKkAKC0ZvcmVpZ25FbnVtEg8KC0ZPUkVJR05fRk9P", 
+            "EAASDwoLRk9SRUlHTl9CQVIQARIPCgtGT1JFSUdOX0JBWhACQiEKH2NvbS5n", 
+            "b29nbGUucHJvdG9idWYuY29uZm9ybWFuY2ViBnByb3RvMw=="));
+      descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedCodeInfo(new[] {typeof(global::Conformance.WireFormat), typeof(global::Conformance.ForeignEnum), }, new pbr::GeneratedCodeInfo[] {
+            new pbr::GeneratedCodeInfo(typeof(global::Conformance.ConformanceRequest), new[]{ "ProtobufPayload", "JsonPayload", "RequestedOutputFormat" }, new[]{ "Payload" }, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Conformance.ConformanceResponse), new[]{ "ParseError", "RuntimeError", "ProtobufPayload", "JsonPayload", "Skipped" }, new[]{ "Result" }, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Conformance.TestAllTypes), new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalStringPiece", "OptionalCord", "RecursiveMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedStringPiece", "RepeatedCord", "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapStringBytes", "MapStringNestedMessage", "MapStringForeignMessage", "MapStringNestedEnum", "MapStringForeignEnum", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes" }, new[]{ "OneofField" }, new[]{ typeof(global::Conformance.TestAllTypes.Types.NestedEnum) }, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::Conformance.TestAllTypes.Types.NestedMessage), new[]{ "A", "Corecursive" }, null, null, null),
+            null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }),
+            new pbr::GeneratedCodeInfo(typeof(global::Conformance.ForeignMessage), new[]{ "C" }, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Enums
+  public enum WireFormat {
+    UNSPECIFIED = 0,
+    PROTOBUF = 1,
+    JSON = 2,
+  }
+
+  public enum ForeignEnum {
+    FOREIGN_FOO = 0,
+    FOREIGN_BAR = 1,
+    FOREIGN_BAZ = 2,
+  }
+
+  #endregion
+
+  #region Messages
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ConformanceRequest : pb::IMessage<ConformanceRequest> {
+    private static readonly pb::MessageParser<ConformanceRequest> _parser = new pb::MessageParser<ConformanceRequest>(() => new ConformanceRequest());
+    public static pb::MessageParser<ConformanceRequest> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Conformance.Conformance.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ConformanceRequest() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ConformanceRequest(ConformanceRequest other) : this() {
+      requestedOutputFormat_ = other.requestedOutputFormat_;
+      switch (other.PayloadCase) {
+        case PayloadOneofCase.ProtobufPayload:
+          ProtobufPayload = other.ProtobufPayload;
+          break;
+        case PayloadOneofCase.JsonPayload:
+          JsonPayload = other.JsonPayload;
+          break;
+      }
+
+    }
+
+    public ConformanceRequest Clone() {
+      return new ConformanceRequest(this);
+    }
+
+    public const int ProtobufPayloadFieldNumber = 1;
+    public pb::ByteString ProtobufPayload {
+      get { return payloadCase_ == PayloadOneofCase.ProtobufPayload ? (pb::ByteString) payload_ : pb::ByteString.Empty; }
+      set {
+        payload_ = pb::Preconditions.CheckNotNull(value, "value");
+        payloadCase_ = PayloadOneofCase.ProtobufPayload;
+      }
+    }
+
+    public const int JsonPayloadFieldNumber = 2;
+    public string JsonPayload {
+      get { return payloadCase_ == PayloadOneofCase.JsonPayload ? (string) payload_ : ""; }
+      set {
+        payload_ = pb::Preconditions.CheckNotNull(value, "value");
+        payloadCase_ = PayloadOneofCase.JsonPayload;
+      }
+    }
+
+    public const int RequestedOutputFormatFieldNumber = 3;
+    private global::Conformance.WireFormat requestedOutputFormat_ = global::Conformance.WireFormat.UNSPECIFIED;
+    public global::Conformance.WireFormat RequestedOutputFormat {
+      get { return requestedOutputFormat_; }
+      set {
+        requestedOutputFormat_ = value;
+      }
+    }
+
+    private object payload_;
+    public enum PayloadOneofCase {
+      None = 0,
+      ProtobufPayload = 1,
+      JsonPayload = 2,
+    }
+    private PayloadOneofCase payloadCase_ = PayloadOneofCase.None;
+    public PayloadOneofCase PayloadCase {
+      get { return payloadCase_; }
+    }
+
+    public void ClearPayload() {
+      payloadCase_ = PayloadOneofCase.None;
+      payload_ = null;
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ConformanceRequest);
+    }
+
+    public bool Equals(ConformanceRequest other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (ProtobufPayload != other.ProtobufPayload) return false;
+      if (JsonPayload != other.JsonPayload) return false;
+      if (RequestedOutputFormat != other.RequestedOutputFormat) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (payloadCase_ == PayloadOneofCase.ProtobufPayload) hash ^= ProtobufPayload.GetHashCode();
+      if (payloadCase_ == PayloadOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode();
+      if (RequestedOutputFormat != global::Conformance.WireFormat.UNSPECIFIED) hash ^= RequestedOutputFormat.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (payloadCase_ == PayloadOneofCase.ProtobufPayload) {
+        output.WriteRawTag(10);
+        output.WriteBytes(ProtobufPayload);
+      }
+      if (payloadCase_ == PayloadOneofCase.JsonPayload) {
+        output.WriteRawTag(18);
+        output.WriteString(JsonPayload);
+      }
+      if (RequestedOutputFormat != global::Conformance.WireFormat.UNSPECIFIED) {
+        output.WriteRawTag(24);
+        output.WriteEnum((int) RequestedOutputFormat);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (payloadCase_ == PayloadOneofCase.ProtobufPayload) {
+        size += 1 + pb::CodedOutputStream.ComputeBytesSize(ProtobufPayload);
+      }
+      if (payloadCase_ == PayloadOneofCase.JsonPayload) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(JsonPayload);
+      }
+      if (RequestedOutputFormat != global::Conformance.WireFormat.UNSPECIFIED) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) RequestedOutputFormat);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ConformanceRequest other) {
+      if (other == null) {
+        return;
+      }
+      if (other.RequestedOutputFormat != global::Conformance.WireFormat.UNSPECIFIED) {
+        RequestedOutputFormat = other.RequestedOutputFormat;
+      }
+      switch (other.PayloadCase) {
+        case PayloadOneofCase.ProtobufPayload:
+          ProtobufPayload = other.ProtobufPayload;
+          break;
+        case PayloadOneofCase.JsonPayload:
+          JsonPayload = other.JsonPayload;
+          break;
+      }
+
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            ProtobufPayload = input.ReadBytes();
+            break;
+          }
+          case 18: {
+            JsonPayload = input.ReadString();
+            break;
+          }
+          case 24: {
+            requestedOutputFormat_ = (global::Conformance.WireFormat) input.ReadEnum();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ConformanceResponse : pb::IMessage<ConformanceResponse> {
+    private static readonly pb::MessageParser<ConformanceResponse> _parser = new pb::MessageParser<ConformanceResponse>(() => new ConformanceResponse());
+    public static pb::MessageParser<ConformanceResponse> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Conformance.Conformance.Descriptor.MessageTypes[1]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ConformanceResponse() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ConformanceResponse(ConformanceResponse other) : this() {
+      switch (other.ResultCase) {
+        case ResultOneofCase.ParseError:
+          ParseError = other.ParseError;
+          break;
+        case ResultOneofCase.RuntimeError:
+          RuntimeError = other.RuntimeError;
+          break;
+        case ResultOneofCase.ProtobufPayload:
+          ProtobufPayload = other.ProtobufPayload;
+          break;
+        case ResultOneofCase.JsonPayload:
+          JsonPayload = other.JsonPayload;
+          break;
+        case ResultOneofCase.Skipped:
+          Skipped = other.Skipped;
+          break;
+      }
+
+    }
+
+    public ConformanceResponse Clone() {
+      return new ConformanceResponse(this);
+    }
+
+    public const int ParseErrorFieldNumber = 1;
+    public string ParseError {
+      get { return resultCase_ == ResultOneofCase.ParseError ? (string) result_ : ""; }
+      set {
+        result_ = pb::Preconditions.CheckNotNull(value, "value");
+        resultCase_ = ResultOneofCase.ParseError;
+      }
+    }
+
+    public const int RuntimeErrorFieldNumber = 2;
+    public string RuntimeError {
+      get { return resultCase_ == ResultOneofCase.RuntimeError ? (string) result_ : ""; }
+      set {
+        result_ = pb::Preconditions.CheckNotNull(value, "value");
+        resultCase_ = ResultOneofCase.RuntimeError;
+      }
+    }
+
+    public const int ProtobufPayloadFieldNumber = 3;
+    public pb::ByteString ProtobufPayload {
+      get { return resultCase_ == ResultOneofCase.ProtobufPayload ? (pb::ByteString) result_ : pb::ByteString.Empty; }
+      set {
+        result_ = pb::Preconditions.CheckNotNull(value, "value");
+        resultCase_ = ResultOneofCase.ProtobufPayload;
+      }
+    }
+
+    public const int JsonPayloadFieldNumber = 4;
+    public string JsonPayload {
+      get { return resultCase_ == ResultOneofCase.JsonPayload ? (string) result_ : ""; }
+      set {
+        result_ = pb::Preconditions.CheckNotNull(value, "value");
+        resultCase_ = ResultOneofCase.JsonPayload;
+      }
+    }
+
+    public const int SkippedFieldNumber = 5;
+    public string Skipped {
+      get { return resultCase_ == ResultOneofCase.Skipped ? (string) result_ : ""; }
+      set {
+        result_ = pb::Preconditions.CheckNotNull(value, "value");
+        resultCase_ = ResultOneofCase.Skipped;
+      }
+    }
+
+    private object result_;
+    public enum ResultOneofCase {
+      None = 0,
+      ParseError = 1,
+      RuntimeError = 2,
+      ProtobufPayload = 3,
+      JsonPayload = 4,
+      Skipped = 5,
+    }
+    private ResultOneofCase resultCase_ = ResultOneofCase.None;
+    public ResultOneofCase ResultCase {
+      get { return resultCase_; }
+    }
+
+    public void ClearResult() {
+      resultCase_ = ResultOneofCase.None;
+      result_ = null;
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ConformanceResponse);
+    }
+
+    public bool Equals(ConformanceResponse other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (ParseError != other.ParseError) return false;
+      if (RuntimeError != other.RuntimeError) return false;
+      if (ProtobufPayload != other.ProtobufPayload) return false;
+      if (JsonPayload != other.JsonPayload) return false;
+      if (Skipped != other.Skipped) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (resultCase_ == ResultOneofCase.ParseError) hash ^= ParseError.GetHashCode();
+      if (resultCase_ == ResultOneofCase.RuntimeError) hash ^= RuntimeError.GetHashCode();
+      if (resultCase_ == ResultOneofCase.ProtobufPayload) hash ^= ProtobufPayload.GetHashCode();
+      if (resultCase_ == ResultOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode();
+      if (resultCase_ == ResultOneofCase.Skipped) hash ^= Skipped.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (resultCase_ == ResultOneofCase.ParseError) {
+        output.WriteRawTag(10);
+        output.WriteString(ParseError);
+      }
+      if (resultCase_ == ResultOneofCase.RuntimeError) {
+        output.WriteRawTag(18);
+        output.WriteString(RuntimeError);
+      }
+      if (resultCase_ == ResultOneofCase.ProtobufPayload) {
+        output.WriteRawTag(26);
+        output.WriteBytes(ProtobufPayload);
+      }
+      if (resultCase_ == ResultOneofCase.JsonPayload) {
+        output.WriteRawTag(34);
+        output.WriteString(JsonPayload);
+      }
+      if (resultCase_ == ResultOneofCase.Skipped) {
+        output.WriteRawTag(42);
+        output.WriteString(Skipped);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (resultCase_ == ResultOneofCase.ParseError) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(ParseError);
+      }
+      if (resultCase_ == ResultOneofCase.RuntimeError) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(RuntimeError);
+      }
+      if (resultCase_ == ResultOneofCase.ProtobufPayload) {
+        size += 1 + pb::CodedOutputStream.ComputeBytesSize(ProtobufPayload);
+      }
+      if (resultCase_ == ResultOneofCase.JsonPayload) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(JsonPayload);
+      }
+      if (resultCase_ == ResultOneofCase.Skipped) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Skipped);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ConformanceResponse other) {
+      if (other == null) {
+        return;
+      }
+      switch (other.ResultCase) {
+        case ResultOneofCase.ParseError:
+          ParseError = other.ParseError;
+          break;
+        case ResultOneofCase.RuntimeError:
+          RuntimeError = other.RuntimeError;
+          break;
+        case ResultOneofCase.ProtobufPayload:
+          ProtobufPayload = other.ProtobufPayload;
+          break;
+        case ResultOneofCase.JsonPayload:
+          JsonPayload = other.JsonPayload;
+          break;
+        case ResultOneofCase.Skipped:
+          Skipped = other.Skipped;
+          break;
+      }
+
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            ParseError = input.ReadString();
+            break;
+          }
+          case 18: {
+            RuntimeError = input.ReadString();
+            break;
+          }
+          case 26: {
+            ProtobufPayload = input.ReadBytes();
+            break;
+          }
+          case 34: {
+            JsonPayload = input.ReadString();
+            break;
+          }
+          case 42: {
+            Skipped = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestAllTypes : pb::IMessage<TestAllTypes> {
+    private static readonly pb::MessageParser<TestAllTypes> _parser = new pb::MessageParser<TestAllTypes>(() => new TestAllTypes());
+    public static pb::MessageParser<TestAllTypes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Conformance.Conformance.Descriptor.MessageTypes[2]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestAllTypes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestAllTypes(TestAllTypes other) : this() {
+      optionalInt32_ = other.optionalInt32_;
+      optionalInt64_ = other.optionalInt64_;
+      optionalUint32_ = other.optionalUint32_;
+      optionalUint64_ = other.optionalUint64_;
+      optionalSint32_ = other.optionalSint32_;
+      optionalSint64_ = other.optionalSint64_;
+      optionalFixed32_ = other.optionalFixed32_;
+      optionalFixed64_ = other.optionalFixed64_;
+      optionalSfixed32_ = other.optionalSfixed32_;
+      optionalSfixed64_ = other.optionalSfixed64_;
+      optionalFloat_ = other.optionalFloat_;
+      optionalDouble_ = other.optionalDouble_;
+      optionalBool_ = other.optionalBool_;
+      optionalString_ = other.optionalString_;
+      optionalBytes_ = other.optionalBytes_;
+      OptionalNestedMessage = other.optionalNestedMessage_ != null ? other.OptionalNestedMessage.Clone() : null;
+      OptionalForeignMessage = other.optionalForeignMessage_ != null ? other.OptionalForeignMessage.Clone() : null;
+      optionalNestedEnum_ = other.optionalNestedEnum_;
+      optionalForeignEnum_ = other.optionalForeignEnum_;
+      optionalStringPiece_ = other.optionalStringPiece_;
+      optionalCord_ = other.optionalCord_;
+      RecursiveMessage = other.recursiveMessage_ != null ? other.RecursiveMessage.Clone() : null;
+      repeatedInt32_ = other.repeatedInt32_.Clone();
+      repeatedInt64_ = other.repeatedInt64_.Clone();
+      repeatedUint32_ = other.repeatedUint32_.Clone();
+      repeatedUint64_ = other.repeatedUint64_.Clone();
+      repeatedSint32_ = other.repeatedSint32_.Clone();
+      repeatedSint64_ = other.repeatedSint64_.Clone();
+      repeatedFixed32_ = other.repeatedFixed32_.Clone();
+      repeatedFixed64_ = other.repeatedFixed64_.Clone();
+      repeatedSfixed32_ = other.repeatedSfixed32_.Clone();
+      repeatedSfixed64_ = other.repeatedSfixed64_.Clone();
+      repeatedFloat_ = other.repeatedFloat_.Clone();
+      repeatedDouble_ = other.repeatedDouble_.Clone();
+      repeatedBool_ = other.repeatedBool_.Clone();
+      repeatedString_ = other.repeatedString_.Clone();
+      repeatedBytes_ = other.repeatedBytes_.Clone();
+      repeatedNestedMessage_ = other.repeatedNestedMessage_.Clone();
+      repeatedForeignMessage_ = other.repeatedForeignMessage_.Clone();
+      repeatedNestedEnum_ = other.repeatedNestedEnum_.Clone();
+      repeatedForeignEnum_ = other.repeatedForeignEnum_.Clone();
+      repeatedStringPiece_ = other.repeatedStringPiece_.Clone();
+      repeatedCord_ = other.repeatedCord_.Clone();
+      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();
+      mapStringBytes_ = other.mapStringBytes_.Clone();
+      mapStringNestedMessage_ = other.mapStringNestedMessage_.Clone();
+      mapStringForeignMessage_ = other.mapStringForeignMessage_.Clone();
+      mapStringNestedEnum_ = other.mapStringNestedEnum_.Clone();
+      mapStringForeignEnum_ = other.mapStringForeignEnum_.Clone();
+      switch (other.OneofFieldCase) {
+        case OneofFieldOneofCase.OneofUint32:
+          OneofUint32 = other.OneofUint32;
+          break;
+        case OneofFieldOneofCase.OneofNestedMessage:
+          OneofNestedMessage = other.OneofNestedMessage.Clone();
+          break;
+        case OneofFieldOneofCase.OneofString:
+          OneofString = other.OneofString;
+          break;
+        case OneofFieldOneofCase.OneofBytes:
+          OneofBytes = other.OneofBytes;
+          break;
+      }
+
+    }
+
+    public TestAllTypes Clone() {
+      return new TestAllTypes(this);
+    }
+
+    public const int OptionalInt32FieldNumber = 1;
+    private int optionalInt32_;
+    public int OptionalInt32 {
+      get { return optionalInt32_; }
+      set {
+        optionalInt32_ = value;
+      }
+    }
+
+    public const int OptionalInt64FieldNumber = 2;
+    private long optionalInt64_;
+    public long OptionalInt64 {
+      get { return optionalInt64_; }
+      set {
+        optionalInt64_ = value;
+      }
+    }
+
+    public const int OptionalUint32FieldNumber = 3;
+    private uint optionalUint32_;
+    public uint OptionalUint32 {
+      get { return optionalUint32_; }
+      set {
+        optionalUint32_ = value;
+      }
+    }
+
+    public const int OptionalUint64FieldNumber = 4;
+    private ulong optionalUint64_;
+    public ulong OptionalUint64 {
+      get { return optionalUint64_; }
+      set {
+        optionalUint64_ = value;
+      }
+    }
+
+    public const int OptionalSint32FieldNumber = 5;
+    private int optionalSint32_;
+    public int OptionalSint32 {
+      get { return optionalSint32_; }
+      set {
+        optionalSint32_ = value;
+      }
+    }
+
+    public const int OptionalSint64FieldNumber = 6;
+    private long optionalSint64_;
+    public long OptionalSint64 {
+      get { return optionalSint64_; }
+      set {
+        optionalSint64_ = value;
+      }
+    }
+
+    public const int OptionalFixed32FieldNumber = 7;
+    private uint optionalFixed32_;
+    public uint OptionalFixed32 {
+      get { return optionalFixed32_; }
+      set {
+        optionalFixed32_ = value;
+      }
+    }
+
+    public const int OptionalFixed64FieldNumber = 8;
+    private ulong optionalFixed64_;
+    public ulong OptionalFixed64 {
+      get { return optionalFixed64_; }
+      set {
+        optionalFixed64_ = value;
+      }
+    }
+
+    public const int OptionalSfixed32FieldNumber = 9;
+    private int optionalSfixed32_;
+    public int OptionalSfixed32 {
+      get { return optionalSfixed32_; }
+      set {
+        optionalSfixed32_ = value;
+      }
+    }
+
+    public const int OptionalSfixed64FieldNumber = 10;
+    private long optionalSfixed64_;
+    public long OptionalSfixed64 {
+      get { return optionalSfixed64_; }
+      set {
+        optionalSfixed64_ = value;
+      }
+    }
+
+    public const int OptionalFloatFieldNumber = 11;
+    private float optionalFloat_;
+    public float OptionalFloat {
+      get { return optionalFloat_; }
+      set {
+        optionalFloat_ = value;
+      }
+    }
+
+    public const int OptionalDoubleFieldNumber = 12;
+    private double optionalDouble_;
+    public double OptionalDouble {
+      get { return optionalDouble_; }
+      set {
+        optionalDouble_ = value;
+      }
+    }
+
+    public const int OptionalBoolFieldNumber = 13;
+    private bool optionalBool_;
+    public bool OptionalBool {
+      get { return optionalBool_; }
+      set {
+        optionalBool_ = value;
+      }
+    }
+
+    public const int OptionalStringFieldNumber = 14;
+    private string optionalString_ = "";
+    public string OptionalString {
+      get { return optionalString_; }
+      set {
+        optionalString_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public const int OptionalBytesFieldNumber = 15;
+    private pb::ByteString optionalBytes_ = pb::ByteString.Empty;
+    public pb::ByteString OptionalBytes {
+      get { return optionalBytes_; }
+      set {
+        optionalBytes_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public const int OptionalNestedMessageFieldNumber = 18;
+    private global::Conformance.TestAllTypes.Types.NestedMessage optionalNestedMessage_;
+    public global::Conformance.TestAllTypes.Types.NestedMessage OptionalNestedMessage {
+      get { return optionalNestedMessage_; }
+      set {
+        optionalNestedMessage_ = value;
+      }
+    }
+
+    public const int OptionalForeignMessageFieldNumber = 19;
+    private global::Conformance.ForeignMessage optionalForeignMessage_;
+    public global::Conformance.ForeignMessage OptionalForeignMessage {
+      get { return optionalForeignMessage_; }
+      set {
+        optionalForeignMessage_ = value;
+      }
+    }
+
+    public const int OptionalNestedEnumFieldNumber = 21;
+    private global::Conformance.TestAllTypes.Types.NestedEnum optionalNestedEnum_ = global::Conformance.TestAllTypes.Types.NestedEnum.FOO;
+    public global::Conformance.TestAllTypes.Types.NestedEnum OptionalNestedEnum {
+      get { return optionalNestedEnum_; }
+      set {
+        optionalNestedEnum_ = value;
+      }
+    }
+
+    public const int OptionalForeignEnumFieldNumber = 22;
+    private global::Conformance.ForeignEnum optionalForeignEnum_ = global::Conformance.ForeignEnum.FOREIGN_FOO;
+    public global::Conformance.ForeignEnum OptionalForeignEnum {
+      get { return optionalForeignEnum_; }
+      set {
+        optionalForeignEnum_ = value;
+      }
+    }
+
+    public const int OptionalStringPieceFieldNumber = 24;
+    private string optionalStringPiece_ = "";
+    public string OptionalStringPiece {
+      get { return optionalStringPiece_; }
+      set {
+        optionalStringPiece_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public const int OptionalCordFieldNumber = 25;
+    private string optionalCord_ = "";
+    public string OptionalCord {
+      get { return optionalCord_; }
+      set {
+        optionalCord_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public const int RecursiveMessageFieldNumber = 27;
+    private global::Conformance.TestAllTypes recursiveMessage_;
+    public global::Conformance.TestAllTypes RecursiveMessage {
+      get { return recursiveMessage_; }
+      set {
+        recursiveMessage_ = value;
+      }
+    }
+
+    public const int RepeatedInt32FieldNumber = 31;
+    private static readonly pb::FieldCodec<int> _repeated_repeatedInt32_codec
+        = pb::FieldCodec.ForInt32(250);
+    private readonly pbc::RepeatedField<int> repeatedInt32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> RepeatedInt32 {
+      get { return repeatedInt32_; }
+    }
+
+    public const int RepeatedInt64FieldNumber = 32;
+    private static readonly pb::FieldCodec<long> _repeated_repeatedInt64_codec
+        = pb::FieldCodec.ForInt64(258);
+    private readonly pbc::RepeatedField<long> repeatedInt64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> RepeatedInt64 {
+      get { return repeatedInt64_; }
+    }
+
+    public const int RepeatedUint32FieldNumber = 33;
+    private static readonly pb::FieldCodec<uint> _repeated_repeatedUint32_codec
+        = pb::FieldCodec.ForUInt32(266);
+    private readonly pbc::RepeatedField<uint> repeatedUint32_ = new pbc::RepeatedField<uint>();
+    public pbc::RepeatedField<uint> RepeatedUint32 {
+      get { return repeatedUint32_; }
+    }
+
+    public const int RepeatedUint64FieldNumber = 34;
+    private static readonly pb::FieldCodec<ulong> _repeated_repeatedUint64_codec
+        = pb::FieldCodec.ForUInt64(274);
+    private readonly pbc::RepeatedField<ulong> repeatedUint64_ = new pbc::RepeatedField<ulong>();
+    public pbc::RepeatedField<ulong> RepeatedUint64 {
+      get { return repeatedUint64_; }
+    }
+
+    public const int RepeatedSint32FieldNumber = 35;
+    private static readonly pb::FieldCodec<int> _repeated_repeatedSint32_codec
+        = pb::FieldCodec.ForSInt32(282);
+    private readonly pbc::RepeatedField<int> repeatedSint32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> RepeatedSint32 {
+      get { return repeatedSint32_; }
+    }
+
+    public const int RepeatedSint64FieldNumber = 36;
+    private static readonly pb::FieldCodec<long> _repeated_repeatedSint64_codec
+        = pb::FieldCodec.ForSInt64(290);
+    private readonly pbc::RepeatedField<long> repeatedSint64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> RepeatedSint64 {
+      get { return repeatedSint64_; }
+    }
+
+    public const int RepeatedFixed32FieldNumber = 37;
+    private static readonly pb::FieldCodec<uint> _repeated_repeatedFixed32_codec
+        = pb::FieldCodec.ForFixed32(298);
+    private readonly pbc::RepeatedField<uint> repeatedFixed32_ = new pbc::RepeatedField<uint>();
+    public pbc::RepeatedField<uint> RepeatedFixed32 {
+      get { return repeatedFixed32_; }
+    }
+
+    public const int RepeatedFixed64FieldNumber = 38;
+    private static readonly pb::FieldCodec<ulong> _repeated_repeatedFixed64_codec
+        = pb::FieldCodec.ForFixed64(306);
+    private readonly pbc::RepeatedField<ulong> repeatedFixed64_ = new pbc::RepeatedField<ulong>();
+    public pbc::RepeatedField<ulong> RepeatedFixed64 {
+      get { return repeatedFixed64_; }
+    }
+
+    public const int RepeatedSfixed32FieldNumber = 39;
+    private static readonly pb::FieldCodec<int> _repeated_repeatedSfixed32_codec
+        = pb::FieldCodec.ForSFixed32(314);
+    private readonly pbc::RepeatedField<int> repeatedSfixed32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> RepeatedSfixed32 {
+      get { return repeatedSfixed32_; }
+    }
+
+    public const int RepeatedSfixed64FieldNumber = 40;
+    private static readonly pb::FieldCodec<long> _repeated_repeatedSfixed64_codec
+        = pb::FieldCodec.ForSFixed64(322);
+    private readonly pbc::RepeatedField<long> repeatedSfixed64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> RepeatedSfixed64 {
+      get { return repeatedSfixed64_; }
+    }
+
+    public const int RepeatedFloatFieldNumber = 41;
+    private static readonly pb::FieldCodec<float> _repeated_repeatedFloat_codec
+        = pb::FieldCodec.ForFloat(330);
+    private readonly pbc::RepeatedField<float> repeatedFloat_ = new pbc::RepeatedField<float>();
+    public pbc::RepeatedField<float> RepeatedFloat {
+      get { return repeatedFloat_; }
+    }
+
+    public const int RepeatedDoubleFieldNumber = 42;
+    private static readonly pb::FieldCodec<double> _repeated_repeatedDouble_codec
+        = pb::FieldCodec.ForDouble(338);
+    private readonly pbc::RepeatedField<double> repeatedDouble_ = new pbc::RepeatedField<double>();
+    public pbc::RepeatedField<double> RepeatedDouble {
+      get { return repeatedDouble_; }
+    }
+
+    public const int RepeatedBoolFieldNumber = 43;
+    private static readonly pb::FieldCodec<bool> _repeated_repeatedBool_codec
+        = pb::FieldCodec.ForBool(346);
+    private readonly pbc::RepeatedField<bool> repeatedBool_ = new pbc::RepeatedField<bool>();
+    public pbc::RepeatedField<bool> RepeatedBool {
+      get { return repeatedBool_; }
+    }
+
+    public const int RepeatedStringFieldNumber = 44;
+    private static readonly pb::FieldCodec<string> _repeated_repeatedString_codec
+        = pb::FieldCodec.ForString(354);
+    private readonly pbc::RepeatedField<string> repeatedString_ = new pbc::RepeatedField<string>();
+    public pbc::RepeatedField<string> RepeatedString {
+      get { return repeatedString_; }
+    }
+
+    public const int RepeatedBytesFieldNumber = 45;
+    private static readonly pb::FieldCodec<pb::ByteString> _repeated_repeatedBytes_codec
+        = pb::FieldCodec.ForBytes(362);
+    private readonly pbc::RepeatedField<pb::ByteString> repeatedBytes_ = new pbc::RepeatedField<pb::ByteString>();
+    public pbc::RepeatedField<pb::ByteString> RepeatedBytes {
+      get { return repeatedBytes_; }
+    }
+
+    public const int RepeatedNestedMessageFieldNumber = 48;
+    private static readonly pb::FieldCodec<global::Conformance.TestAllTypes.Types.NestedMessage> _repeated_repeatedNestedMessage_codec
+        = pb::FieldCodec.ForMessage(386, global::Conformance.TestAllTypes.Types.NestedMessage.Parser);
+    private readonly pbc::RepeatedField<global::Conformance.TestAllTypes.Types.NestedMessage> repeatedNestedMessage_ = new pbc::RepeatedField<global::Conformance.TestAllTypes.Types.NestedMessage>();
+    public pbc::RepeatedField<global::Conformance.TestAllTypes.Types.NestedMessage> RepeatedNestedMessage {
+      get { return repeatedNestedMessage_; }
+    }
+
+    public const int RepeatedForeignMessageFieldNumber = 49;
+    private static readonly pb::FieldCodec<global::Conformance.ForeignMessage> _repeated_repeatedForeignMessage_codec
+        = pb::FieldCodec.ForMessage(394, global::Conformance.ForeignMessage.Parser);
+    private readonly pbc::RepeatedField<global::Conformance.ForeignMessage> repeatedForeignMessage_ = new pbc::RepeatedField<global::Conformance.ForeignMessage>();
+    public pbc::RepeatedField<global::Conformance.ForeignMessage> RepeatedForeignMessage {
+      get { return repeatedForeignMessage_; }
+    }
+
+    public const int RepeatedNestedEnumFieldNumber = 51;
+    private static readonly pb::FieldCodec<global::Conformance.TestAllTypes.Types.NestedEnum> _repeated_repeatedNestedEnum_codec
+        = pb::FieldCodec.ForEnum(410, x => (int) x, x => (global::Conformance.TestAllTypes.Types.NestedEnum) x);
+    private readonly pbc::RepeatedField<global::Conformance.TestAllTypes.Types.NestedEnum> repeatedNestedEnum_ = new pbc::RepeatedField<global::Conformance.TestAllTypes.Types.NestedEnum>();
+    public pbc::RepeatedField<global::Conformance.TestAllTypes.Types.NestedEnum> RepeatedNestedEnum {
+      get { return repeatedNestedEnum_; }
+    }
+
+    public const int RepeatedForeignEnumFieldNumber = 52;
+    private static readonly pb::FieldCodec<global::Conformance.ForeignEnum> _repeated_repeatedForeignEnum_codec
+        = pb::FieldCodec.ForEnum(418, x => (int) x, x => (global::Conformance.ForeignEnum) x);
+    private readonly pbc::RepeatedField<global::Conformance.ForeignEnum> repeatedForeignEnum_ = new pbc::RepeatedField<global::Conformance.ForeignEnum>();
+    public pbc::RepeatedField<global::Conformance.ForeignEnum> RepeatedForeignEnum {
+      get { return repeatedForeignEnum_; }
+    }
+
+    public const int RepeatedStringPieceFieldNumber = 54;
+    private static readonly pb::FieldCodec<string> _repeated_repeatedStringPiece_codec
+        = pb::FieldCodec.ForString(434);
+    private readonly pbc::RepeatedField<string> repeatedStringPiece_ = new pbc::RepeatedField<string>();
+    public pbc::RepeatedField<string> RepeatedStringPiece {
+      get { return repeatedStringPiece_; }
+    }
+
+    public const int RepeatedCordFieldNumber = 55;
+    private static readonly pb::FieldCodec<string> _repeated_repeatedCord_codec
+        = pb::FieldCodec.ForString(442);
+    private readonly pbc::RepeatedField<string> repeatedCord_ = new pbc::RepeatedField<string>();
+    public pbc::RepeatedField<string> RepeatedCord {
+      get { return repeatedCord_; }
+    }
+
+    public const int MapInt32Int32FieldNumber = 56;
+    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), 450);
+    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 = 57;
+    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), 458);
+    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 = 58;
+    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), 466);
+    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 = 59;
+    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), 474);
+    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 = 60;
+    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), 482);
+    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 = 61;
+    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), 490);
+    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 = 62;
+    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), 498);
+    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 = 63;
+    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), 506);
+    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 = 64;
+    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), 514);
+    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 = 65;
+    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), 522);
+    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 = 66;
+    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), 530);
+    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 = 67;
+    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), 538);
+    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 = 68;
+    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), 546);
+    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 = 69;
+    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), 554);
+    private readonly pbc::MapField<string, string> mapStringString_ = new pbc::MapField<string, string>();
+    public pbc::MapField<string, string> MapStringString {
+      get { return mapStringString_; }
+    }
+
+    public const int MapStringBytesFieldNumber = 70;
+    private static readonly pbc::MapField<string, pb::ByteString>.Codec _map_mapStringBytes_codec
+        = new pbc::MapField<string, pb::ByteString>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForBytes(18), 562);
+    private readonly pbc::MapField<string, pb::ByteString> mapStringBytes_ = new pbc::MapField<string, pb::ByteString>();
+    public pbc::MapField<string, pb::ByteString> MapStringBytes {
+      get { return mapStringBytes_; }
+    }
+
+    public const int MapStringNestedMessageFieldNumber = 71;
+    private static readonly pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedMessage>.Codec _map_mapStringNestedMessage_codec
+        = new pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedMessage>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForMessage(18, global::Conformance.TestAllTypes.Types.NestedMessage.Parser), 570);
+    private readonly pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedMessage> mapStringNestedMessage_ = new pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedMessage>();
+    public pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedMessage> MapStringNestedMessage {
+      get { return mapStringNestedMessage_; }
+    }
+
+    public const int MapStringForeignMessageFieldNumber = 72;
+    private static readonly pbc::MapField<string, global::Conformance.ForeignMessage>.Codec _map_mapStringForeignMessage_codec
+        = new pbc::MapField<string, global::Conformance.ForeignMessage>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForMessage(18, global::Conformance.ForeignMessage.Parser), 578);
+    private readonly pbc::MapField<string, global::Conformance.ForeignMessage> mapStringForeignMessage_ = new pbc::MapField<string, global::Conformance.ForeignMessage>();
+    public pbc::MapField<string, global::Conformance.ForeignMessage> MapStringForeignMessage {
+      get { return mapStringForeignMessage_; }
+    }
+
+    public const int MapStringNestedEnumFieldNumber = 73;
+    private static readonly pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedEnum>.Codec _map_mapStringNestedEnum_codec
+        = new pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedEnum>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::Conformance.TestAllTypes.Types.NestedEnum) x), 586);
+    private readonly pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedEnum> mapStringNestedEnum_ = new pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedEnum>();
+    public pbc::MapField<string, global::Conformance.TestAllTypes.Types.NestedEnum> MapStringNestedEnum {
+      get { return mapStringNestedEnum_; }
+    }
+
+    public const int MapStringForeignEnumFieldNumber = 74;
+    private static readonly pbc::MapField<string, global::Conformance.ForeignEnum>.Codec _map_mapStringForeignEnum_codec
+        = new pbc::MapField<string, global::Conformance.ForeignEnum>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::Conformance.ForeignEnum) x), 594);
+    private readonly pbc::MapField<string, global::Conformance.ForeignEnum> mapStringForeignEnum_ = new pbc::MapField<string, global::Conformance.ForeignEnum>();
+    public pbc::MapField<string, global::Conformance.ForeignEnum> MapStringForeignEnum {
+      get { return mapStringForeignEnum_; }
+    }
+
+    public const int OneofUint32FieldNumber = 111;
+    public uint OneofUint32 {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32 ? (uint) oneofField_ : 0; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = OneofFieldOneofCase.OneofUint32;
+      }
+    }
+
+    public const int OneofNestedMessageFieldNumber = 112;
+    public global::Conformance.TestAllTypes.Types.NestedMessage OneofNestedMessage {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Conformance.TestAllTypes.Types.NestedMessage) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.OneofNestedMessage;
+      }
+    }
+
+    public const int OneofStringFieldNumber = 113;
+    public string OneofString {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) oneofField_ : ""; }
+      set {
+        oneofField_ = pb::Preconditions.CheckNotNull(value, "value");
+        oneofFieldCase_ = OneofFieldOneofCase.OneofString;
+      }
+    }
+
+    public const int OneofBytesFieldNumber = 114;
+    public pb::ByteString OneofBytes {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; }
+      set {
+        oneofField_ = pb::Preconditions.CheckNotNull(value, "value");
+        oneofFieldCase_ = OneofFieldOneofCase.OneofBytes;
+      }
+    }
+
+    private object oneofField_;
+    public enum OneofFieldOneofCase {
+      None = 0,
+      OneofUint32 = 111,
+      OneofNestedMessage = 112,
+      OneofString = 113,
+      OneofBytes = 114,
+    }
+    private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None;
+    public OneofFieldOneofCase OneofFieldCase {
+      get { return oneofFieldCase_; }
+    }
+
+    public void ClearOneofField() {
+      oneofFieldCase_ = OneofFieldOneofCase.None;
+      oneofField_ = null;
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestAllTypes);
+    }
+
+    public bool Equals(TestAllTypes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (OptionalInt32 != other.OptionalInt32) return false;
+      if (OptionalInt64 != other.OptionalInt64) return false;
+      if (OptionalUint32 != other.OptionalUint32) return false;
+      if (OptionalUint64 != other.OptionalUint64) return false;
+      if (OptionalSint32 != other.OptionalSint32) return false;
+      if (OptionalSint64 != other.OptionalSint64) return false;
+      if (OptionalFixed32 != other.OptionalFixed32) return false;
+      if (OptionalFixed64 != other.OptionalFixed64) return false;
+      if (OptionalSfixed32 != other.OptionalSfixed32) return false;
+      if (OptionalSfixed64 != other.OptionalSfixed64) return false;
+      if (OptionalFloat != other.OptionalFloat) return false;
+      if (OptionalDouble != other.OptionalDouble) return false;
+      if (OptionalBool != other.OptionalBool) return false;
+      if (OptionalString != other.OptionalString) return false;
+      if (OptionalBytes != other.OptionalBytes) return false;
+      if (!object.Equals(OptionalNestedMessage, other.OptionalNestedMessage)) return false;
+      if (!object.Equals(OptionalForeignMessage, other.OptionalForeignMessage)) return false;
+      if (OptionalNestedEnum != other.OptionalNestedEnum) return false;
+      if (OptionalForeignEnum != other.OptionalForeignEnum) return false;
+      if (OptionalStringPiece != other.OptionalStringPiece) return false;
+      if (OptionalCord != other.OptionalCord) return false;
+      if (!object.Equals(RecursiveMessage, other.RecursiveMessage)) return false;
+      if(!repeatedInt32_.Equals(other.repeatedInt32_)) return false;
+      if(!repeatedInt64_.Equals(other.repeatedInt64_)) return false;
+      if(!repeatedUint32_.Equals(other.repeatedUint32_)) return false;
+      if(!repeatedUint64_.Equals(other.repeatedUint64_)) return false;
+      if(!repeatedSint32_.Equals(other.repeatedSint32_)) return false;
+      if(!repeatedSint64_.Equals(other.repeatedSint64_)) return false;
+      if(!repeatedFixed32_.Equals(other.repeatedFixed32_)) return false;
+      if(!repeatedFixed64_.Equals(other.repeatedFixed64_)) return false;
+      if(!repeatedSfixed32_.Equals(other.repeatedSfixed32_)) return false;
+      if(!repeatedSfixed64_.Equals(other.repeatedSfixed64_)) return false;
+      if(!repeatedFloat_.Equals(other.repeatedFloat_)) return false;
+      if(!repeatedDouble_.Equals(other.repeatedDouble_)) return false;
+      if(!repeatedBool_.Equals(other.repeatedBool_)) return false;
+      if(!repeatedString_.Equals(other.repeatedString_)) return false;
+      if(!repeatedBytes_.Equals(other.repeatedBytes_)) return false;
+      if(!repeatedNestedMessage_.Equals(other.repeatedNestedMessage_)) return false;
+      if(!repeatedForeignMessage_.Equals(other.repeatedForeignMessage_)) return false;
+      if(!repeatedNestedEnum_.Equals(other.repeatedNestedEnum_)) return false;
+      if(!repeatedForeignEnum_.Equals(other.repeatedForeignEnum_)) return false;
+      if(!repeatedStringPiece_.Equals(other.repeatedStringPiece_)) return false;
+      if(!repeatedCord_.Equals(other.repeatedCord_)) return false;
+      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 (!MapStringBytes.Equals(other.MapStringBytes)) return false;
+      if (!MapStringNestedMessage.Equals(other.MapStringNestedMessage)) return false;
+      if (!MapStringForeignMessage.Equals(other.MapStringForeignMessage)) return false;
+      if (!MapStringNestedEnum.Equals(other.MapStringNestedEnum)) return false;
+      if (!MapStringForeignEnum.Equals(other.MapStringForeignEnum)) return false;
+      if (OneofUint32 != other.OneofUint32) return false;
+      if (!object.Equals(OneofNestedMessage, other.OneofNestedMessage)) return false;
+      if (OneofString != other.OneofString) return false;
+      if (OneofBytes != other.OneofBytes) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (OptionalInt32 != 0) hash ^= OptionalInt32.GetHashCode();
+      if (OptionalInt64 != 0L) hash ^= OptionalInt64.GetHashCode();
+      if (OptionalUint32 != 0) hash ^= OptionalUint32.GetHashCode();
+      if (OptionalUint64 != 0UL) hash ^= OptionalUint64.GetHashCode();
+      if (OptionalSint32 != 0) hash ^= OptionalSint32.GetHashCode();
+      if (OptionalSint64 != 0L) hash ^= OptionalSint64.GetHashCode();
+      if (OptionalFixed32 != 0) hash ^= OptionalFixed32.GetHashCode();
+      if (OptionalFixed64 != 0UL) hash ^= OptionalFixed64.GetHashCode();
+      if (OptionalSfixed32 != 0) hash ^= OptionalSfixed32.GetHashCode();
+      if (OptionalSfixed64 != 0L) hash ^= OptionalSfixed64.GetHashCode();
+      if (OptionalFloat != 0F) hash ^= OptionalFloat.GetHashCode();
+      if (OptionalDouble != 0D) hash ^= OptionalDouble.GetHashCode();
+      if (OptionalBool != false) hash ^= OptionalBool.GetHashCode();
+      if (OptionalString.Length != 0) hash ^= OptionalString.GetHashCode();
+      if (OptionalBytes.Length != 0) hash ^= OptionalBytes.GetHashCode();
+      if (optionalNestedMessage_ != null) hash ^= OptionalNestedMessage.GetHashCode();
+      if (optionalForeignMessage_ != null) hash ^= OptionalForeignMessage.GetHashCode();
+      if (OptionalNestedEnum != global::Conformance.TestAllTypes.Types.NestedEnum.FOO) hash ^= OptionalNestedEnum.GetHashCode();
+      if (OptionalForeignEnum != global::Conformance.ForeignEnum.FOREIGN_FOO) hash ^= OptionalForeignEnum.GetHashCode();
+      if (OptionalStringPiece.Length != 0) hash ^= OptionalStringPiece.GetHashCode();
+      if (OptionalCord.Length != 0) hash ^= OptionalCord.GetHashCode();
+      if (recursiveMessage_ != null) hash ^= RecursiveMessage.GetHashCode();
+      hash ^= repeatedInt32_.GetHashCode();
+      hash ^= repeatedInt64_.GetHashCode();
+      hash ^= repeatedUint32_.GetHashCode();
+      hash ^= repeatedUint64_.GetHashCode();
+      hash ^= repeatedSint32_.GetHashCode();
+      hash ^= repeatedSint64_.GetHashCode();
+      hash ^= repeatedFixed32_.GetHashCode();
+      hash ^= repeatedFixed64_.GetHashCode();
+      hash ^= repeatedSfixed32_.GetHashCode();
+      hash ^= repeatedSfixed64_.GetHashCode();
+      hash ^= repeatedFloat_.GetHashCode();
+      hash ^= repeatedDouble_.GetHashCode();
+      hash ^= repeatedBool_.GetHashCode();
+      hash ^= repeatedString_.GetHashCode();
+      hash ^= repeatedBytes_.GetHashCode();
+      hash ^= repeatedNestedMessage_.GetHashCode();
+      hash ^= repeatedForeignMessage_.GetHashCode();
+      hash ^= repeatedNestedEnum_.GetHashCode();
+      hash ^= repeatedForeignEnum_.GetHashCode();
+      hash ^= repeatedStringPiece_.GetHashCode();
+      hash ^= repeatedCord_.GetHashCode();
+      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 ^= MapStringBytes.GetHashCode();
+      hash ^= MapStringNestedMessage.GetHashCode();
+      hash ^= MapStringForeignMessage.GetHashCode();
+      hash ^= MapStringNestedEnum.GetHashCode();
+      hash ^= MapStringForeignEnum.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) hash ^= OneofUint32.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) hash ^= OneofNestedMessage.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) hash ^= OneofString.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) hash ^= OneofBytes.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (OptionalInt32 != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(OptionalInt32);
+      }
+      if (OptionalInt64 != 0L) {
+        output.WriteRawTag(16);
+        output.WriteInt64(OptionalInt64);
+      }
+      if (OptionalUint32 != 0) {
+        output.WriteRawTag(24);
+        output.WriteUInt32(OptionalUint32);
+      }
+      if (OptionalUint64 != 0UL) {
+        output.WriteRawTag(32);
+        output.WriteUInt64(OptionalUint64);
+      }
+      if (OptionalSint32 != 0) {
+        output.WriteRawTag(40);
+        output.WriteSInt32(OptionalSint32);
+      }
+      if (OptionalSint64 != 0L) {
+        output.WriteRawTag(48);
+        output.WriteSInt64(OptionalSint64);
+      }
+      if (OptionalFixed32 != 0) {
+        output.WriteRawTag(61);
+        output.WriteFixed32(OptionalFixed32);
+      }
+      if (OptionalFixed64 != 0UL) {
+        output.WriteRawTag(65);
+        output.WriteFixed64(OptionalFixed64);
+      }
+      if (OptionalSfixed32 != 0) {
+        output.WriteRawTag(77);
+        output.WriteSFixed32(OptionalSfixed32);
+      }
+      if (OptionalSfixed64 != 0L) {
+        output.WriteRawTag(81);
+        output.WriteSFixed64(OptionalSfixed64);
+      }
+      if (OptionalFloat != 0F) {
+        output.WriteRawTag(93);
+        output.WriteFloat(OptionalFloat);
+      }
+      if (OptionalDouble != 0D) {
+        output.WriteRawTag(97);
+        output.WriteDouble(OptionalDouble);
+      }
+      if (OptionalBool != false) {
+        output.WriteRawTag(104);
+        output.WriteBool(OptionalBool);
+      }
+      if (OptionalString.Length != 0) {
+        output.WriteRawTag(114);
+        output.WriteString(OptionalString);
+      }
+      if (OptionalBytes.Length != 0) {
+        output.WriteRawTag(122);
+        output.WriteBytes(OptionalBytes);
+      }
+      if (optionalNestedMessage_ != null) {
+        output.WriteRawTag(146, 1);
+        output.WriteMessage(OptionalNestedMessage);
+      }
+      if (optionalForeignMessage_ != null) {
+        output.WriteRawTag(154, 1);
+        output.WriteMessage(OptionalForeignMessage);
+      }
+      if (OptionalNestedEnum != global::Conformance.TestAllTypes.Types.NestedEnum.FOO) {
+        output.WriteRawTag(168, 1);
+        output.WriteEnum((int) OptionalNestedEnum);
+      }
+      if (OptionalForeignEnum != global::Conformance.ForeignEnum.FOREIGN_FOO) {
+        output.WriteRawTag(176, 1);
+        output.WriteEnum((int) OptionalForeignEnum);
+      }
+      if (OptionalStringPiece.Length != 0) {
+        output.WriteRawTag(194, 1);
+        output.WriteString(OptionalStringPiece);
+      }
+      if (OptionalCord.Length != 0) {
+        output.WriteRawTag(202, 1);
+        output.WriteString(OptionalCord);
+      }
+      if (recursiveMessage_ != null) {
+        output.WriteRawTag(218, 1);
+        output.WriteMessage(RecursiveMessage);
+      }
+      repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec);
+      repeatedInt64_.WriteTo(output, _repeated_repeatedInt64_codec);
+      repeatedUint32_.WriteTo(output, _repeated_repeatedUint32_codec);
+      repeatedUint64_.WriteTo(output, _repeated_repeatedUint64_codec);
+      repeatedSint32_.WriteTo(output, _repeated_repeatedSint32_codec);
+      repeatedSint64_.WriteTo(output, _repeated_repeatedSint64_codec);
+      repeatedFixed32_.WriteTo(output, _repeated_repeatedFixed32_codec);
+      repeatedFixed64_.WriteTo(output, _repeated_repeatedFixed64_codec);
+      repeatedSfixed32_.WriteTo(output, _repeated_repeatedSfixed32_codec);
+      repeatedSfixed64_.WriteTo(output, _repeated_repeatedSfixed64_codec);
+      repeatedFloat_.WriteTo(output, _repeated_repeatedFloat_codec);
+      repeatedDouble_.WriteTo(output, _repeated_repeatedDouble_codec);
+      repeatedBool_.WriteTo(output, _repeated_repeatedBool_codec);
+      repeatedString_.WriteTo(output, _repeated_repeatedString_codec);
+      repeatedBytes_.WriteTo(output, _repeated_repeatedBytes_codec);
+      repeatedNestedMessage_.WriteTo(output, _repeated_repeatedNestedMessage_codec);
+      repeatedForeignMessage_.WriteTo(output, _repeated_repeatedForeignMessage_codec);
+      repeatedNestedEnum_.WriteTo(output, _repeated_repeatedNestedEnum_codec);
+      repeatedForeignEnum_.WriteTo(output, _repeated_repeatedForeignEnum_codec);
+      repeatedStringPiece_.WriteTo(output, _repeated_repeatedStringPiece_codec);
+      repeatedCord_.WriteTo(output, _repeated_repeatedCord_codec);
+      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);
+      mapStringBytes_.WriteTo(output, _map_mapStringBytes_codec);
+      mapStringNestedMessage_.WriteTo(output, _map_mapStringNestedMessage_codec);
+      mapStringForeignMessage_.WriteTo(output, _map_mapStringForeignMessage_codec);
+      mapStringNestedEnum_.WriteTo(output, _map_mapStringNestedEnum_codec);
+      mapStringForeignEnum_.WriteTo(output, _map_mapStringForeignEnum_codec);
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) {
+        output.WriteRawTag(248, 6);
+        output.WriteUInt32(OneofUint32);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
+        output.WriteRawTag(130, 7);
+        output.WriteMessage(OneofNestedMessage);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) {
+        output.WriteRawTag(138, 7);
+        output.WriteString(OneofString);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) {
+        output.WriteRawTag(146, 7);
+        output.WriteBytes(OneofBytes);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (OptionalInt32 != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(OptionalInt32);
+      }
+      if (OptionalInt64 != 0L) {
+        size += 1 + pb::CodedOutputStream.ComputeInt64Size(OptionalInt64);
+      }
+      if (OptionalUint32 != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeUInt32Size(OptionalUint32);
+      }
+      if (OptionalUint64 != 0UL) {
+        size += 1 + pb::CodedOutputStream.ComputeUInt64Size(OptionalUint64);
+      }
+      if (OptionalSint32 != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeSInt32Size(OptionalSint32);
+      }
+      if (OptionalSint64 != 0L) {
+        size += 1 + pb::CodedOutputStream.ComputeSInt64Size(OptionalSint64);
+      }
+      if (OptionalFixed32 != 0) {
+        size += 1 + 4;
+      }
+      if (OptionalFixed64 != 0UL) {
+        size += 1 + 8;
+      }
+      if (OptionalSfixed32 != 0) {
+        size += 1 + 4;
+      }
+      if (OptionalSfixed64 != 0L) {
+        size += 1 + 8;
+      }
+      if (OptionalFloat != 0F) {
+        size += 1 + 4;
+      }
+      if (OptionalDouble != 0D) {
+        size += 1 + 8;
+      }
+      if (OptionalBool != false) {
+        size += 1 + 1;
+      }
+      if (OptionalString.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(OptionalString);
+      }
+      if (OptionalBytes.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeBytesSize(OptionalBytes);
+      }
+      if (optionalNestedMessage_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalNestedMessage);
+      }
+      if (optionalForeignMessage_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalForeignMessage);
+      }
+      if (OptionalNestedEnum != global::Conformance.TestAllTypes.Types.NestedEnum.FOO) {
+        size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalNestedEnum);
+      }
+      if (OptionalForeignEnum != global::Conformance.ForeignEnum.FOREIGN_FOO) {
+        size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) OptionalForeignEnum);
+      }
+      if (OptionalStringPiece.Length != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalStringPiece);
+      }
+      if (OptionalCord.Length != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalCord);
+      }
+      if (recursiveMessage_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(RecursiveMessage);
+      }
+      size += repeatedInt32_.CalculateSize(_repeated_repeatedInt32_codec);
+      size += repeatedInt64_.CalculateSize(_repeated_repeatedInt64_codec);
+      size += repeatedUint32_.CalculateSize(_repeated_repeatedUint32_codec);
+      size += repeatedUint64_.CalculateSize(_repeated_repeatedUint64_codec);
+      size += repeatedSint32_.CalculateSize(_repeated_repeatedSint32_codec);
+      size += repeatedSint64_.CalculateSize(_repeated_repeatedSint64_codec);
+      size += repeatedFixed32_.CalculateSize(_repeated_repeatedFixed32_codec);
+      size += repeatedFixed64_.CalculateSize(_repeated_repeatedFixed64_codec);
+      size += repeatedSfixed32_.CalculateSize(_repeated_repeatedSfixed32_codec);
+      size += repeatedSfixed64_.CalculateSize(_repeated_repeatedSfixed64_codec);
+      size += repeatedFloat_.CalculateSize(_repeated_repeatedFloat_codec);
+      size += repeatedDouble_.CalculateSize(_repeated_repeatedDouble_codec);
+      size += repeatedBool_.CalculateSize(_repeated_repeatedBool_codec);
+      size += repeatedString_.CalculateSize(_repeated_repeatedString_codec);
+      size += repeatedBytes_.CalculateSize(_repeated_repeatedBytes_codec);
+      size += repeatedNestedMessage_.CalculateSize(_repeated_repeatedNestedMessage_codec);
+      size += repeatedForeignMessage_.CalculateSize(_repeated_repeatedForeignMessage_codec);
+      size += repeatedNestedEnum_.CalculateSize(_repeated_repeatedNestedEnum_codec);
+      size += repeatedForeignEnum_.CalculateSize(_repeated_repeatedForeignEnum_codec);
+      size += repeatedStringPiece_.CalculateSize(_repeated_repeatedStringPiece_codec);
+      size += repeatedCord_.CalculateSize(_repeated_repeatedCord_codec);
+      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 += mapStringBytes_.CalculateSize(_map_mapStringBytes_codec);
+      size += mapStringNestedMessage_.CalculateSize(_map_mapStringNestedMessage_codec);
+      size += mapStringForeignMessage_.CalculateSize(_map_mapStringForeignMessage_codec);
+      size += mapStringNestedEnum_.CalculateSize(_map_mapStringNestedEnum_codec);
+      size += mapStringForeignEnum_.CalculateSize(_map_mapStringForeignEnum_codec);
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) {
+        size += 2 + pb::CodedOutputStream.ComputeUInt32Size(OneofUint32);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(OneofNestedMessage);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) {
+        size += 2 + pb::CodedOutputStream.ComputeStringSize(OneofString);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) {
+        size += 2 + pb::CodedOutputStream.ComputeBytesSize(OneofBytes);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestAllTypes other) {
+      if (other == null) {
+        return;
+      }
+      if (other.OptionalInt32 != 0) {
+        OptionalInt32 = other.OptionalInt32;
+      }
+      if (other.OptionalInt64 != 0L) {
+        OptionalInt64 = other.OptionalInt64;
+      }
+      if (other.OptionalUint32 != 0) {
+        OptionalUint32 = other.OptionalUint32;
+      }
+      if (other.OptionalUint64 != 0UL) {
+        OptionalUint64 = other.OptionalUint64;
+      }
+      if (other.OptionalSint32 != 0) {
+        OptionalSint32 = other.OptionalSint32;
+      }
+      if (other.OptionalSint64 != 0L) {
+        OptionalSint64 = other.OptionalSint64;
+      }
+      if (other.OptionalFixed32 != 0) {
+        OptionalFixed32 = other.OptionalFixed32;
+      }
+      if (other.OptionalFixed64 != 0UL) {
+        OptionalFixed64 = other.OptionalFixed64;
+      }
+      if (other.OptionalSfixed32 != 0) {
+        OptionalSfixed32 = other.OptionalSfixed32;
+      }
+      if (other.OptionalSfixed64 != 0L) {
+        OptionalSfixed64 = other.OptionalSfixed64;
+      }
+      if (other.OptionalFloat != 0F) {
+        OptionalFloat = other.OptionalFloat;
+      }
+      if (other.OptionalDouble != 0D) {
+        OptionalDouble = other.OptionalDouble;
+      }
+      if (other.OptionalBool != false) {
+        OptionalBool = other.OptionalBool;
+      }
+      if (other.OptionalString.Length != 0) {
+        OptionalString = other.OptionalString;
+      }
+      if (other.OptionalBytes.Length != 0) {
+        OptionalBytes = other.OptionalBytes;
+      }
+      if (other.optionalNestedMessage_ != null) {
+        if (optionalNestedMessage_ == null) {
+          optionalNestedMessage_ = new global::Conformance.TestAllTypes.Types.NestedMessage();
+        }
+        OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage);
+      }
+      if (other.optionalForeignMessage_ != null) {
+        if (optionalForeignMessage_ == null) {
+          optionalForeignMessage_ = new global::Conformance.ForeignMessage();
+        }
+        OptionalForeignMessage.MergeFrom(other.OptionalForeignMessage);
+      }
+      if (other.OptionalNestedEnum != global::Conformance.TestAllTypes.Types.NestedEnum.FOO) {
+        OptionalNestedEnum = other.OptionalNestedEnum;
+      }
+      if (other.OptionalForeignEnum != global::Conformance.ForeignEnum.FOREIGN_FOO) {
+        OptionalForeignEnum = other.OptionalForeignEnum;
+      }
+      if (other.OptionalStringPiece.Length != 0) {
+        OptionalStringPiece = other.OptionalStringPiece;
+      }
+      if (other.OptionalCord.Length != 0) {
+        OptionalCord = other.OptionalCord;
+      }
+      if (other.recursiveMessage_ != null) {
+        if (recursiveMessage_ == null) {
+          recursiveMessage_ = new global::Conformance.TestAllTypes();
+        }
+        RecursiveMessage.MergeFrom(other.RecursiveMessage);
+      }
+      repeatedInt32_.Add(other.repeatedInt32_);
+      repeatedInt64_.Add(other.repeatedInt64_);
+      repeatedUint32_.Add(other.repeatedUint32_);
+      repeatedUint64_.Add(other.repeatedUint64_);
+      repeatedSint32_.Add(other.repeatedSint32_);
+      repeatedSint64_.Add(other.repeatedSint64_);
+      repeatedFixed32_.Add(other.repeatedFixed32_);
+      repeatedFixed64_.Add(other.repeatedFixed64_);
+      repeatedSfixed32_.Add(other.repeatedSfixed32_);
+      repeatedSfixed64_.Add(other.repeatedSfixed64_);
+      repeatedFloat_.Add(other.repeatedFloat_);
+      repeatedDouble_.Add(other.repeatedDouble_);
+      repeatedBool_.Add(other.repeatedBool_);
+      repeatedString_.Add(other.repeatedString_);
+      repeatedBytes_.Add(other.repeatedBytes_);
+      repeatedNestedMessage_.Add(other.repeatedNestedMessage_);
+      repeatedForeignMessage_.Add(other.repeatedForeignMessage_);
+      repeatedNestedEnum_.Add(other.repeatedNestedEnum_);
+      repeatedForeignEnum_.Add(other.repeatedForeignEnum_);
+      repeatedStringPiece_.Add(other.repeatedStringPiece_);
+      repeatedCord_.Add(other.repeatedCord_);
+      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_);
+      mapStringBytes_.Add(other.mapStringBytes_);
+      mapStringNestedMessage_.Add(other.mapStringNestedMessage_);
+      mapStringForeignMessage_.Add(other.mapStringForeignMessage_);
+      mapStringNestedEnum_.Add(other.mapStringNestedEnum_);
+      mapStringForeignEnum_.Add(other.mapStringForeignEnum_);
+      switch (other.OneofFieldCase) {
+        case OneofFieldOneofCase.OneofUint32:
+          OneofUint32 = other.OneofUint32;
+          break;
+        case OneofFieldOneofCase.OneofNestedMessage:
+          OneofNestedMessage = other.OneofNestedMessage;
+          break;
+        case OneofFieldOneofCase.OneofString:
+          OneofString = other.OneofString;
+          break;
+        case OneofFieldOneofCase.OneofBytes:
+          OneofBytes = other.OneofBytes;
+          break;
+      }
+
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            OptionalInt32 = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            OptionalInt64 = input.ReadInt64();
+            break;
+          }
+          case 24: {
+            OptionalUint32 = input.ReadUInt32();
+            break;
+          }
+          case 32: {
+            OptionalUint64 = input.ReadUInt64();
+            break;
+          }
+          case 40: {
+            OptionalSint32 = input.ReadSInt32();
+            break;
+          }
+          case 48: {
+            OptionalSint64 = input.ReadSInt64();
+            break;
+          }
+          case 61: {
+            OptionalFixed32 = input.ReadFixed32();
+            break;
+          }
+          case 65: {
+            OptionalFixed64 = input.ReadFixed64();
+            break;
+          }
+          case 77: {
+            OptionalSfixed32 = input.ReadSFixed32();
+            break;
+          }
+          case 81: {
+            OptionalSfixed64 = input.ReadSFixed64();
+            break;
+          }
+          case 93: {
+            OptionalFloat = input.ReadFloat();
+            break;
+          }
+          case 97: {
+            OptionalDouble = input.ReadDouble();
+            break;
+          }
+          case 104: {
+            OptionalBool = input.ReadBool();
+            break;
+          }
+          case 114: {
+            OptionalString = input.ReadString();
+            break;
+          }
+          case 122: {
+            OptionalBytes = input.ReadBytes();
+            break;
+          }
+          case 146: {
+            if (optionalNestedMessage_ == null) {
+              optionalNestedMessage_ = new global::Conformance.TestAllTypes.Types.NestedMessage();
+            }
+            input.ReadMessage(optionalNestedMessage_);
+            break;
+          }
+          case 154: {
+            if (optionalForeignMessage_ == null) {
+              optionalForeignMessage_ = new global::Conformance.ForeignMessage();
+            }
+            input.ReadMessage(optionalForeignMessage_);
+            break;
+          }
+          case 168: {
+            optionalNestedEnum_ = (global::Conformance.TestAllTypes.Types.NestedEnum) input.ReadEnum();
+            break;
+          }
+          case 176: {
+            optionalForeignEnum_ = (global::Conformance.ForeignEnum) input.ReadEnum();
+            break;
+          }
+          case 194: {
+            OptionalStringPiece = input.ReadString();
+            break;
+          }
+          case 202: {
+            OptionalCord = input.ReadString();
+            break;
+          }
+          case 218: {
+            if (recursiveMessage_ == null) {
+              recursiveMessage_ = new global::Conformance.TestAllTypes();
+            }
+            input.ReadMessage(recursiveMessage_);
+            break;
+          }
+          case 250:
+          case 248: {
+            repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec);
+            break;
+          }
+          case 258:
+          case 256: {
+            repeatedInt64_.AddEntriesFrom(input, _repeated_repeatedInt64_codec);
+            break;
+          }
+          case 266:
+          case 264: {
+            repeatedUint32_.AddEntriesFrom(input, _repeated_repeatedUint32_codec);
+            break;
+          }
+          case 274:
+          case 272: {
+            repeatedUint64_.AddEntriesFrom(input, _repeated_repeatedUint64_codec);
+            break;
+          }
+          case 282:
+          case 280: {
+            repeatedSint32_.AddEntriesFrom(input, _repeated_repeatedSint32_codec);
+            break;
+          }
+          case 290:
+          case 288: {
+            repeatedSint64_.AddEntriesFrom(input, _repeated_repeatedSint64_codec);
+            break;
+          }
+          case 298:
+          case 301: {
+            repeatedFixed32_.AddEntriesFrom(input, _repeated_repeatedFixed32_codec);
+            break;
+          }
+          case 306:
+          case 305: {
+            repeatedFixed64_.AddEntriesFrom(input, _repeated_repeatedFixed64_codec);
+            break;
+          }
+          case 314:
+          case 317: {
+            repeatedSfixed32_.AddEntriesFrom(input, _repeated_repeatedSfixed32_codec);
+            break;
+          }
+          case 322:
+          case 321: {
+            repeatedSfixed64_.AddEntriesFrom(input, _repeated_repeatedSfixed64_codec);
+            break;
+          }
+          case 330:
+          case 333: {
+            repeatedFloat_.AddEntriesFrom(input, _repeated_repeatedFloat_codec);
+            break;
+          }
+          case 338:
+          case 337: {
+            repeatedDouble_.AddEntriesFrom(input, _repeated_repeatedDouble_codec);
+            break;
+          }
+          case 346:
+          case 344: {
+            repeatedBool_.AddEntriesFrom(input, _repeated_repeatedBool_codec);
+            break;
+          }
+          case 354: {
+            repeatedString_.AddEntriesFrom(input, _repeated_repeatedString_codec);
+            break;
+          }
+          case 362: {
+            repeatedBytes_.AddEntriesFrom(input, _repeated_repeatedBytes_codec);
+            break;
+          }
+          case 386: {
+            repeatedNestedMessage_.AddEntriesFrom(input, _repeated_repeatedNestedMessage_codec);
+            break;
+          }
+          case 394: {
+            repeatedForeignMessage_.AddEntriesFrom(input, _repeated_repeatedForeignMessage_codec);
+            break;
+          }
+          case 410:
+          case 408: {
+            repeatedNestedEnum_.AddEntriesFrom(input, _repeated_repeatedNestedEnum_codec);
+            break;
+          }
+          case 418:
+          case 416: {
+            repeatedForeignEnum_.AddEntriesFrom(input, _repeated_repeatedForeignEnum_codec);
+            break;
+          }
+          case 434: {
+            repeatedStringPiece_.AddEntriesFrom(input, _repeated_repeatedStringPiece_codec);
+            break;
+          }
+          case 442: {
+            repeatedCord_.AddEntriesFrom(input, _repeated_repeatedCord_codec);
+            break;
+          }
+          case 450: {
+            mapInt32Int32_.AddEntriesFrom(input, _map_mapInt32Int32_codec);
+            break;
+          }
+          case 458: {
+            mapInt64Int64_.AddEntriesFrom(input, _map_mapInt64Int64_codec);
+            break;
+          }
+          case 466: {
+            mapUint32Uint32_.AddEntriesFrom(input, _map_mapUint32Uint32_codec);
+            break;
+          }
+          case 474: {
+            mapUint64Uint64_.AddEntriesFrom(input, _map_mapUint64Uint64_codec);
+            break;
+          }
+          case 482: {
+            mapSint32Sint32_.AddEntriesFrom(input, _map_mapSint32Sint32_codec);
+            break;
+          }
+          case 490: {
+            mapSint64Sint64_.AddEntriesFrom(input, _map_mapSint64Sint64_codec);
+            break;
+          }
+          case 498: {
+            mapFixed32Fixed32_.AddEntriesFrom(input, _map_mapFixed32Fixed32_codec);
+            break;
+          }
+          case 506: {
+            mapFixed64Fixed64_.AddEntriesFrom(input, _map_mapFixed64Fixed64_codec);
+            break;
+          }
+          case 514: {
+            mapSfixed32Sfixed32_.AddEntriesFrom(input, _map_mapSfixed32Sfixed32_codec);
+            break;
+          }
+          case 522: {
+            mapSfixed64Sfixed64_.AddEntriesFrom(input, _map_mapSfixed64Sfixed64_codec);
+            break;
+          }
+          case 530: {
+            mapInt32Float_.AddEntriesFrom(input, _map_mapInt32Float_codec);
+            break;
+          }
+          case 538: {
+            mapInt32Double_.AddEntriesFrom(input, _map_mapInt32Double_codec);
+            break;
+          }
+          case 546: {
+            mapBoolBool_.AddEntriesFrom(input, _map_mapBoolBool_codec);
+            break;
+          }
+          case 554: {
+            mapStringString_.AddEntriesFrom(input, _map_mapStringString_codec);
+            break;
+          }
+          case 562: {
+            mapStringBytes_.AddEntriesFrom(input, _map_mapStringBytes_codec);
+            break;
+          }
+          case 570: {
+            mapStringNestedMessage_.AddEntriesFrom(input, _map_mapStringNestedMessage_codec);
+            break;
+          }
+          case 578: {
+            mapStringForeignMessage_.AddEntriesFrom(input, _map_mapStringForeignMessage_codec);
+            break;
+          }
+          case 586: {
+            mapStringNestedEnum_.AddEntriesFrom(input, _map_mapStringNestedEnum_codec);
+            break;
+          }
+          case 594: {
+            mapStringForeignEnum_.AddEntriesFrom(input, _map_mapStringForeignEnum_codec);
+            break;
+          }
+          case 888: {
+            OneofUint32 = input.ReadUInt32();
+            break;
+          }
+          case 898: {
+            global::Conformance.TestAllTypes.Types.NestedMessage subBuilder = new global::Conformance.TestAllTypes.Types.NestedMessage();
+            if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
+              subBuilder.MergeFrom(OneofNestedMessage);
+            }
+            input.ReadMessage(subBuilder);
+            OneofNestedMessage = subBuilder;
+            break;
+          }
+          case 906: {
+            OneofString = input.ReadString();
+            break;
+          }
+          case 914: {
+            OneofBytes = input.ReadBytes();
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      public enum NestedEnum {
+        FOO = 0,
+        BAR = 1,
+        BAZ = 2,
+        NEG = -1,
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class NestedMessage : pb::IMessage<NestedMessage> {
+        private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
+        public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
+
+        public static pbr::MessageDescriptor Descriptor {
+          get { return global::Conformance.TestAllTypes.Descriptor.NestedTypes[0]; }
+        }
+
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
+        }
+
+        public NestedMessage() {
+          OnConstruction();
+        }
+
+        partial void OnConstruction();
+
+        public NestedMessage(NestedMessage other) : this() {
+          a_ = other.a_;
+          Corecursive = other.corecursive_ != null ? other.Corecursive.Clone() : null;
+        }
+
+        public NestedMessage Clone() {
+          return new NestedMessage(this);
+        }
+
+        public const int AFieldNumber = 1;
+        private int a_;
+        public int A {
+          get { return a_; }
+          set {
+            a_ = value;
+          }
+        }
+
+        public const int CorecursiveFieldNumber = 2;
+        private global::Conformance.TestAllTypes corecursive_;
+        public global::Conformance.TestAllTypes Corecursive {
+          get { return corecursive_; }
+          set {
+            corecursive_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as NestedMessage);
+        }
+
+        public bool Equals(NestedMessage other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (A != other.A) return false;
+          if (!object.Equals(Corecursive, other.Corecursive)) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (A != 0) hash ^= A.GetHashCode();
+          if (corecursive_ != null) hash ^= Corecursive.GetHashCode();
+          return hash;
+        }
+
+        public override string ToString() {
+          return pb::JsonFormatter.Default.Format(this);
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (A != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(A);
+          }
+          if (corecursive_ != null) {
+            output.WriteRawTag(18);
+            output.WriteMessage(Corecursive);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (A != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(A);
+          }
+          if (corecursive_ != null) {
+            size += 1 + pb::CodedOutputStream.ComputeMessageSize(Corecursive);
+          }
+          return size;
+        }
+
+        public void MergeFrom(NestedMessage other) {
+          if (other == null) {
+            return;
+          }
+          if (other.A != 0) {
+            A = other.A;
+          }
+          if (other.corecursive_ != null) {
+            if (corecursive_ == null) {
+              corecursive_ = new global::Conformance.TestAllTypes();
+            }
+            Corecursive.MergeFrom(other.Corecursive);
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                input.SkipLastField();
+                break;
+              case 8: {
+                A = input.ReadInt32();
+                break;
+              }
+              case 18: {
+                if (corecursive_ == null) {
+                  corecursive_ = new global::Conformance.TestAllTypes();
+                }
+                input.ReadMessage(corecursive_);
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ForeignMessage : pb::IMessage<ForeignMessage> {
+    private static readonly pb::MessageParser<ForeignMessage> _parser = new pb::MessageParser<ForeignMessage>(() => new ForeignMessage());
+    public static pb::MessageParser<ForeignMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Conformance.Conformance.Descriptor.MessageTypes[3]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ForeignMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ForeignMessage(ForeignMessage other) : this() {
+      c_ = other.c_;
+    }
+
+    public ForeignMessage Clone() {
+      return new ForeignMessage(this);
+    }
+
+    public const int CFieldNumber = 1;
+    private int c_;
+    public int C {
+      get { return c_; }
+      set {
+        c_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ForeignMessage);
+    }
+
+    public bool Equals(ForeignMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (C != other.C) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (C != 0) hash ^= C.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (C != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(C);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (C != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(C);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ForeignMessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.C != 0) {
+        C = other.C;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            C = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code

+ 61 - 0
csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj

@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{0607D1B8-80D6-4B35-9857-1263C1B32B94}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Google.Protobuf.Conformance</RootNamespace>
+    <AssemblyName>Google.Protobuf.Conformance</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="Microsoft.CSharp" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Conformance.cs" />
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Google.Protobuf\Google.Protobuf.csproj">
+      <Project>{6908bdce-d925-43f3-94ac-a531e6df2591}</Project>
+      <Name>Google.Protobuf</Name>
+    </ProjectReference>
+  </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.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

+ 126 - 0
csharp/src/Google.Protobuf.Conformance/Program.cs

@@ -0,0 +1,126 @@
+#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 Conformance;
+using System;
+using System.IO;
+
+namespace Google.Protobuf.Conformance
+{
+    /// <summary>
+    /// Conformance tests. The test runner will provide JSON or proto data on stdin,
+    /// and this program will produce its output on stdout.
+    /// </summary>
+    class Program
+    {
+        private static void Main(string[] args)
+        {
+            // This way we get the binary streams instead of readers/writers.
+            var input = new BinaryReader(Console.OpenStandardInput());
+            var output = new BinaryWriter(Console.OpenStandardOutput());
+
+            int count = 0;
+            while (RunTest(input, output))
+            {
+                count++;
+            }
+            Console.Error.WriteLine("Received EOF after {0} tests", count);
+        }
+
+        private static bool RunTest(BinaryReader input, BinaryWriter output)
+        {
+            int? size = ReadInt32(input);
+            if (size == null)
+            {
+                return false;
+            }
+            byte[] inputData = input.ReadBytes(size.Value);
+            if (inputData.Length != size.Value)
+            {
+                throw new EndOfStreamException("Read " + inputData.Length + " bytes of data when expecting " + size);
+            }
+            ConformanceRequest request = ConformanceRequest.Parser.ParseFrom(inputData);
+            ConformanceResponse response = PerformRequest(request);
+            byte[] outputData = response.ToByteArray();
+            output.Write(outputData.Length);
+            output.Write(outputData);
+            // Ready for another test...
+            return true;
+        }
+
+        private static ConformanceResponse PerformRequest(ConformanceRequest request)
+        {
+            TestAllTypes message;
+            switch (request.PayloadCase)
+            {
+                case ConformanceRequest.PayloadOneofCase.JsonPayload:
+                    return new ConformanceResponse { Skipped = "JSON parsing not implemented in C# yet" };
+                case ConformanceRequest.PayloadOneofCase.ProtobufPayload:
+                    try
+                    {
+                        message = TestAllTypes.Parser.ParseFrom(request.ProtobufPayload);
+                    }
+                    catch (InvalidProtocolBufferException e)
+                    {
+                        return new ConformanceResponse { ParseError = e.Message };
+                    }
+                    break;
+                default:
+                    throw new Exception("Unsupported request payload: " + request.PayloadCase);
+            }
+            switch (request.RequestedOutputFormat)
+            {
+                case global::Conformance.WireFormat.JSON:
+                    return new ConformanceResponse { JsonPayload = JsonFormatter.Default.Format(message) };
+                case global::Conformance.WireFormat.PROTOBUF:
+                    return new ConformanceResponse { ProtobufPayload = message.ToByteString() };
+                default:
+                    throw new Exception("Unsupported request output format: " + request.PayloadCase);
+            }
+        }
+
+        private static int? ReadInt32(BinaryReader input)
+        {
+            byte[] bytes = input.ReadBytes(4);
+            if (bytes.Length == 0)
+            {
+                // Cleanly reached the end of the stream
+                return null;
+            }
+            if (bytes.Length != 4)
+            {
+                throw new EndOfStreamException("Read " + bytes.Length + " bytes of size when expecting 4");
+            }
+            return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
+        }
+    }
+}

+ 48 - 0
csharp/src/Google.Protobuf.Conformance/Properties/AssemblyInfo.cs

@@ -0,0 +1,48 @@
+#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.Reflection;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Google.Protobuf.Conformance")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Google.Protobuf.Conformance")]
+[assembly: AssemblyCopyright("Copyright ©  2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: AssemblyVersion("3.0.0.0")]
+[assembly: AssemblyFileVersion("3.0.0.0")]

+ 68 - 0
csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj

@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{D7282E99-2DC3-405B-946F-177DB2FD2AE2}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Google.Protobuf.JsonDump</RootNamespace>
+    <AssemblyName>Google.Protobuf.JsonDump</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <IntermediateOutputPath>obj\Debug\</IntermediateOutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <NoStdLib>true</NoStdLib>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <IntermediateOutputPath>obj\Release\</IntermediateOutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <NoStdLib>true</NoStdLib>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="mscorlib" />
+    <Reference Include="System" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Google.Protobuf\Google.Protobuf.csproj">
+      <Project>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</Project>
+      <Name>Google.Protobuf</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="app.config" />
+  </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.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

+ 72 - 0
csharp/src/Google.Protobuf.JsonDump/Program.cs

@@ -0,0 +1,72 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.IO;
+
+namespace Google.Protobuf.ProtoDump
+{
+    /// <summary>
+    /// Small utility to load a binary message and dump it in JSON format.
+    /// </summary>
+    internal class Program
+    {
+        private static int Main(string[] args)
+        {
+            if (args.Length != 2)
+            {
+                Console.Error.WriteLine("Usage: Google.Protobuf.JsonDump <descriptor type name> <input data>");
+                Console.Error.WriteLine("The descriptor type name is the fully-qualified message name,");
+                Console.Error.WriteLine("including assembly e.g. ProjectNamespace.Message,Company.Project");
+                return 1;
+            }
+            Type type = Type.GetType(args[0]);
+            if (type == null)
+            {
+                Console.Error.WriteLine("Unable to load type {0}.", args[0]);
+                return 1;
+            }
+            if (!typeof(IMessage).IsAssignableFrom(type))
+            {
+                Console.Error.WriteLine("Type {0} doesn't implement IMessage.", args[0]);
+                return 1;
+            }
+            IMessage message = (IMessage) Activator.CreateInstance(type);
+            using (var input = File.OpenRead(args[1]))
+            {
+                message.MergeFrom(input);
+            }
+            Console.WriteLine(message);
+            return 0;
+        }
+    }
+}

+ 19 - 0
csharp/src/Google.Protobuf.JsonDump/Properties/AssemblyInfo.cs

@@ -0,0 +1,19 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("ProtoDump")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ProtoDump")]
+[assembly: AssemblyCopyright("Copyright ©  2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: AssemblyVersion("3.0.0.0")]
+[assembly: AssemblyFileVersion("3.0.0.0")]

+ 3 - 0
csharp/src/Google.Protobuf.JsonDump/app.config

@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>

+ 171 - 0
csharp/src/Google.Protobuf.Test/ByteStringTest.cs

@@ -0,0 +1,171 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.Text;
+using NUnit.Framework;
+
+namespace Google.Protobuf
+{
+    public class ByteStringTest
+    {
+        [Test]
+        public void Equality()
+        {
+            ByteString b1 = ByteString.CopyFrom(1, 2, 3);
+            ByteString b2 = ByteString.CopyFrom(1, 2, 3);
+            ByteString b3 = ByteString.CopyFrom(1, 2, 4);
+            ByteString b4 = ByteString.CopyFrom(1, 2, 3, 4);
+            EqualityTester.AssertEquality(b1, b1);
+            EqualityTester.AssertEquality(b1, b2);
+            EqualityTester.AssertInequality(b1, b3);
+            EqualityTester.AssertInequality(b1, b4);
+            EqualityTester.AssertInequality(b1, null);
+#pragma warning disable 1718 // Deliberately calling ==(b1, b1) and !=(b1, b1)
+            Assert.IsTrue(b1 == b1);
+            Assert.IsTrue(b1 == b2);
+            Assert.IsFalse(b1 == b3);
+            Assert.IsFalse(b1 == b4);
+            Assert.IsFalse(b1 == null);
+            Assert.IsTrue((ByteString) null == null);
+            Assert.IsFalse(b1 != b1);
+            Assert.IsFalse(b1 != b2);
+#pragma warning disable 1718
+            Assert.IsTrue(b1 != b3);
+            Assert.IsTrue(b1 != b4);
+            Assert.IsTrue(b1 != null);
+            Assert.IsFalse((ByteString) null != null);
+        }
+
+        [Test]
+        public void EmptyByteStringHasZeroSize()
+        {
+            Assert.AreEqual(0, ByteString.Empty.Length);
+        }
+
+        [Test]
+        public void CopyFromStringWithExplicitEncoding()
+        {
+            ByteString bs = ByteString.CopyFrom("AB", Encoding.Unicode);
+            Assert.AreEqual(4, bs.Length);
+            Assert.AreEqual(65, bs[0]);
+            Assert.AreEqual(0, bs[1]);
+            Assert.AreEqual(66, bs[2]);
+            Assert.AreEqual(0, bs[3]);
+        }
+
+        [Test]
+        public void IsEmptyWhenEmpty()
+        {
+            Assert.IsTrue(ByteString.CopyFromUtf8("").IsEmpty);
+        }
+
+        [Test]
+        public void IsEmptyWhenNotEmpty()
+        {
+            Assert.IsFalse(ByteString.CopyFromUtf8("X").IsEmpty);
+        }
+
+        [Test]
+        public void CopyFromByteArrayCopiesContents()
+        {
+            byte[] data = new byte[1];
+            data[0] = 10;
+            ByteString bs = ByteString.CopyFrom(data);
+            Assert.AreEqual(10, bs[0]);
+            data[0] = 5;
+            Assert.AreEqual(10, bs[0]);
+        }
+
+        [Test]
+        public void ToByteArrayCopiesContents()
+        {
+            ByteString bs = ByteString.CopyFromUtf8("Hello");
+            byte[] data = bs.ToByteArray();
+            Assert.AreEqual((byte)'H', data[0]);
+            Assert.AreEqual((byte)'H', bs[0]);
+            data[0] = 0;
+            Assert.AreEqual(0, data[0]);
+            Assert.AreEqual((byte)'H', bs[0]);
+        }
+
+        [Test]
+        public void CopyFromUtf8UsesUtf8()
+        {
+            ByteString bs = ByteString.CopyFromUtf8("\u20ac");
+            Assert.AreEqual(3, bs.Length);
+            Assert.AreEqual(0xe2, bs[0]);
+            Assert.AreEqual(0x82, bs[1]);
+            Assert.AreEqual(0xac, bs[2]);
+        }
+
+        [Test]
+        public void CopyFromPortion()
+        {
+            byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6};
+            ByteString bs = ByteString.CopyFrom(data, 2, 3);
+            Assert.AreEqual(3, bs.Length);
+            Assert.AreEqual(2, bs[0]);
+            Assert.AreEqual(3, bs[1]);
+        }
+
+        [Test]
+        public void ToStringUtf8()
+        {
+            ByteString bs = ByteString.CopyFromUtf8("\u20ac");
+            Assert.AreEqual("\u20ac", bs.ToStringUtf8());
+        }
+
+        [Test]
+        public void ToStringWithExplicitEncoding()
+        {
+            ByteString bs = ByteString.CopyFrom("\u20ac", Encoding.Unicode);
+            Assert.AreEqual("\u20ac", bs.ToString(Encoding.Unicode));
+        }
+
+        [Test]
+        public void FromBase64_WithText()
+        {
+            byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6};
+            string base64 = Convert.ToBase64String(data);
+            ByteString bs = ByteString.FromBase64(base64);
+            Assert.AreEqual(data, bs.ToByteArray());
+        }
+
+        [Test]
+        public void FromBase64_Empty()
+        {
+            // Optimization which also fixes issue 61.
+            Assert.AreSame(ByteString.Empty, ByteString.FromBase64(""));
+        }
+    }
+}

+ 53 - 0
csharp/src/Google.Protobuf.Test/CodedInputStreamExtensions.cs

@@ -0,0 +1,53 @@
+#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 NUnit.Framework;
+
+namespace Google.Protobuf
+{
+    internal static class CodedInputStreamExtensions
+    {
+        public static void AssertNextTag(this CodedInputStream input, uint expectedTag)
+        {
+            uint tag = input.ReadTag();
+            Assert.AreEqual(expectedTag, tag);
+        }
+
+        public static T ReadMessage<T>(this CodedInputStream stream, MessageParser<T> parser)
+            where T : IMessage<T>
+        {
+            var message = parser.CreateTemplate();
+            stream.ReadMessage(message);
+            return message;
+        }
+    }
+}

+ 530 - 0
csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs

@@ -0,0 +1,530 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.IO;
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+
+namespace Google.Protobuf
+{
+    public class CodedInputStreamTest
+    {
+        /// <summary>
+        /// Helper to construct a byte array from a bunch of bytes.  The inputs are
+        /// actually ints so that I can use hex notation and not get stupid errors
+        /// about precision.
+        /// </summary>
+        private static byte[] Bytes(params int[] bytesAsInts)
+        {
+            byte[] bytes = new byte[bytesAsInts.Length];
+            for (int i = 0; i < bytesAsInts.Length; i++)
+            {
+                bytes[i] = (byte) bytesAsInts[i];
+            }
+            return bytes;
+        }
+
+        /// <summary>
+        /// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64()
+        /// </summary>
+        private static void AssertReadVarint(byte[] data, ulong value)
+        {
+            CodedInputStream input = new CodedInputStream(data);
+            Assert.AreEqual((uint) value, input.ReadRawVarint32());
+
+            input = new CodedInputStream(data);
+            Assert.AreEqual(value, input.ReadRawVarint64());
+            Assert.IsTrue(input.IsAtEnd);
+
+            // Try different block sizes.
+            for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2)
+            {
+                input = new CodedInputStream(new SmallBlockInputStream(data, bufferSize));
+                Assert.AreEqual((uint) value, input.ReadRawVarint32());
+
+                input = new CodedInputStream(new SmallBlockInputStream(data, bufferSize));
+                Assert.AreEqual(value, input.ReadRawVarint64());
+                Assert.IsTrue(input.IsAtEnd);
+            }
+
+            // Try reading directly from a MemoryStream. We want to verify that it
+            // doesn't read past the end of the input, so write an extra byte - this
+            // lets us test the position at the end.
+            MemoryStream memoryStream = new MemoryStream();
+            memoryStream.Write(data, 0, data.Length);
+            memoryStream.WriteByte(0);
+            memoryStream.Position = 0;
+            Assert.AreEqual((uint) value, CodedInputStream.ReadRawVarint32(memoryStream));
+            Assert.AreEqual(data.Length, memoryStream.Position);
+        }
+
+        /// <summary>
+        /// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64() and
+        /// expects them to fail with an InvalidProtocolBufferException whose
+        /// description matches the given one.
+        /// </summary>
+        private static void AssertReadVarintFailure(InvalidProtocolBufferException expected, byte[] data)
+        {
+            CodedInputStream input = new CodedInputStream(data);
+            var exception = Assert.Throws<InvalidProtocolBufferException>(() => input.ReadRawVarint32());
+            Assert.AreEqual(expected.Message, exception.Message);
+
+            input = new CodedInputStream(data);
+            exception = Assert.Throws<InvalidProtocolBufferException>(() => input.ReadRawVarint64());
+            Assert.AreEqual(expected.Message, exception.Message);
+
+            // Make sure we get the same error when reading directly from a Stream.
+            exception = Assert.Throws<InvalidProtocolBufferException>(() => CodedInputStream.ReadRawVarint32(new MemoryStream(data)));
+            Assert.AreEqual(expected.Message, exception.Message);
+        }
+
+        [Test]
+        public void ReadVarint()
+        {
+            AssertReadVarint(Bytes(0x00), 0);
+            AssertReadVarint(Bytes(0x01), 1);
+            AssertReadVarint(Bytes(0x7f), 127);
+            // 14882
+            AssertReadVarint(Bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7));
+            // 2961488830
+            AssertReadVarint(Bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b),
+                             (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
+                             (0x0bL << 28));
+
+            // 64-bit
+            // 7256456126
+            AssertReadVarint(Bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b),
+                             (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
+                             (0x1bL << 28));
+            // 41256202580718336
+            AssertReadVarint(Bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49),
+                             (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
+                             (0x43L << 28) | (0x49L << 35) | (0x24L << 42) | (0x49L << 49));
+            // 11964378330978735131
+            AssertReadVarint(Bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
+                             (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
+                             (0x3bUL << 28) | (0x56UL << 35) | (0x00UL << 42) |
+                             (0x05UL << 49) | (0x26UL << 56) | (0x01UL << 63));
+
+            // Failures
+            AssertReadVarintFailure(
+                InvalidProtocolBufferException.MalformedVarint(),
+                Bytes(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+                      0x00));
+            AssertReadVarintFailure(
+                InvalidProtocolBufferException.TruncatedMessage(),
+                Bytes(0x80));
+        }
+
+        /// <summary>
+        /// Parses the given bytes using ReadRawLittleEndian32() and checks
+        /// that the result matches the given value.
+        /// </summary>
+        private static void AssertReadLittleEndian32(byte[] data, uint value)
+        {
+            CodedInputStream input = new CodedInputStream(data);
+            Assert.AreEqual(value, input.ReadRawLittleEndian32());
+            Assert.IsTrue(input.IsAtEnd);
+
+            // Try different block sizes.
+            for (int blockSize = 1; blockSize <= 16; blockSize *= 2)
+            {
+                input = new CodedInputStream(
+                    new SmallBlockInputStream(data, blockSize));
+                Assert.AreEqual(value, input.ReadRawLittleEndian32());
+                Assert.IsTrue(input.IsAtEnd);
+            }
+        }
+
+        /// <summary>
+        /// Parses the given bytes using ReadRawLittleEndian64() and checks
+        /// that the result matches the given value.
+        /// </summary>
+        private static void AssertReadLittleEndian64(byte[] data, ulong value)
+        {
+            CodedInputStream input = new CodedInputStream(data);
+            Assert.AreEqual(value, input.ReadRawLittleEndian64());
+            Assert.IsTrue(input.IsAtEnd);
+
+            // Try different block sizes.
+            for (int blockSize = 1; blockSize <= 16; blockSize *= 2)
+            {
+                input = new CodedInputStream(
+                    new SmallBlockInputStream(data, blockSize));
+                Assert.AreEqual(value, input.ReadRawLittleEndian64());
+                Assert.IsTrue(input.IsAtEnd);
+            }
+        }
+
+        [Test]
+        public void ReadLittleEndian()
+        {
+            AssertReadLittleEndian32(Bytes(0x78, 0x56, 0x34, 0x12), 0x12345678);
+            AssertReadLittleEndian32(Bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0);
+
+            AssertReadLittleEndian64(Bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12),
+                                     0x123456789abcdef0L);
+            AssertReadLittleEndian64(
+                Bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef012345678UL);
+        }
+
+        [Test]
+        public void DecodeZigZag32()
+        {
+            Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(0));
+            Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(1));
+            Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(2));
+            Assert.AreEqual(-2, CodedInputStream.DecodeZigZag32(3));
+            Assert.AreEqual(0x3FFFFFFF, CodedInputStream.DecodeZigZag32(0x7FFFFFFE));
+            Assert.AreEqual(unchecked((int) 0xC0000000), CodedInputStream.DecodeZigZag32(0x7FFFFFFF));
+            Assert.AreEqual(0x7FFFFFFF, CodedInputStream.DecodeZigZag32(0xFFFFFFFE));
+            Assert.AreEqual(unchecked((int) 0x80000000), CodedInputStream.DecodeZigZag32(0xFFFFFFFF));
+        }
+
+        [Test]
+        public void DecodeZigZag64()
+        {
+            Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(0));
+            Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(1));
+            Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(2));
+            Assert.AreEqual(-2, CodedInputStream.DecodeZigZag64(3));
+            Assert.AreEqual(0x000000003FFFFFFFL, CodedInputStream.DecodeZigZag64(0x000000007FFFFFFEL));
+            Assert.AreEqual(unchecked((long) 0xFFFFFFFFC0000000L), CodedInputStream.DecodeZigZag64(0x000000007FFFFFFFL));
+            Assert.AreEqual(0x000000007FFFFFFFL, CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFEL));
+            Assert.AreEqual(unchecked((long) 0xFFFFFFFF80000000L), CodedInputStream.DecodeZigZag64(0x00000000FFFFFFFFL));
+            Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL));
+            Assert.AreEqual(unchecked((long) 0x8000000000000000L), CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL));
+        }
+        
+        [Test]
+        public void ReadWholeMessage_VaryingBlockSizes()
+        {
+            TestAllTypes message = SampleMessages.CreateFullTestAllTypes();
+
+            byte[] rawBytes = message.ToByteArray();
+            Assert.AreEqual(rawBytes.Length, message.CalculateSize());
+            TestAllTypes message2 = TestAllTypes.Parser.ParseFrom(rawBytes);
+            Assert.AreEqual(message, message2);
+
+            // Try different block sizes.
+            for (int blockSize = 1; blockSize < 256; blockSize *= 2)
+            {
+                message2 = TestAllTypes.Parser.ParseFrom(new SmallBlockInputStream(rawBytes, blockSize));
+                Assert.AreEqual(message, message2);
+            }
+        }
+                
+        [Test]
+        public void ReadHugeBlob()
+        {
+            // Allocate and initialize a 1MB blob.
+            byte[] blob = new byte[1 << 20];
+            for (int i = 0; i < blob.Length; i++)
+            {
+                blob[i] = (byte) i;
+            }
+
+            // Make a message containing it.
+            var message = new TestAllTypes { SingleBytes = ByteString.CopyFrom(blob) };
+
+            // Serialize and parse it.  Make sure to parse from an InputStream, not
+            // directly from a ByteString, so that CodedInputStream uses buffered
+            // reading.
+            TestAllTypes message2 = TestAllTypes.Parser.ParseFrom(message.ToByteString());
+
+            Assert.AreEqual(message, message2);
+        }
+
+        [Test]
+        public void ReadMaliciouslyLargeBlob()
+        {
+            MemoryStream ms = new MemoryStream();
+            CodedOutputStream output = new CodedOutputStream(ms);
+
+            uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
+            output.WriteRawVarint32(tag);
+            output.WriteRawVarint32(0x7FFFFFFF);
+            output.WriteRawBytes(new byte[32]); // Pad with a few random bytes.
+            output.Flush();
+            ms.Position = 0;
+
+            CodedInputStream input = new CodedInputStream(ms);
+            Assert.AreEqual(tag, input.ReadTag());
+
+            Assert.Throws<InvalidProtocolBufferException>(() => input.ReadBytes());
+        }
+
+        private static TestRecursiveMessage MakeRecursiveMessage(int depth)
+        {
+            if (depth == 0)
+            {
+                return new TestRecursiveMessage { I = 5 };
+            }
+            else
+            {
+                return new TestRecursiveMessage { A = MakeRecursiveMessage(depth - 1) };
+            }
+        }
+
+        private static void AssertMessageDepth(TestRecursiveMessage message, int depth)
+        {
+            if (depth == 0)
+            {
+                Assert.IsNull(message.A);
+                Assert.AreEqual(5, message.I);
+            }
+            else
+            {
+                Assert.IsNotNull(message.A);
+                AssertMessageDepth(message.A, depth - 1);
+            }
+        }
+
+        [Test]
+        public void MaliciousRecursion()
+        {
+            ByteString data64 = MakeRecursiveMessage(64).ToByteString();
+            ByteString data65 = MakeRecursiveMessage(65).ToByteString();
+
+            AssertMessageDepth(TestRecursiveMessage.Parser.ParseFrom(data64), 64);
+
+            Assert.Throws<InvalidProtocolBufferException>(() => TestRecursiveMessage.Parser.ParseFrom(data65));
+
+            CodedInputStream input = CodedInputStream.CreateWithLimits(new MemoryStream(data64.ToByteArray()), 1000000, 63);
+            Assert.Throws<InvalidProtocolBufferException>(() => TestRecursiveMessage.Parser.ParseFrom(input));
+        }
+
+        [Test]
+        public void SizeLimit()
+        {
+            // Have to use a Stream rather than ByteString.CreateCodedInput as SizeLimit doesn't
+            // apply to the latter case.
+            MemoryStream ms = new MemoryStream(SampleMessages.CreateFullTestAllTypes().ToByteArray());
+            CodedInputStream input = CodedInputStream.CreateWithLimits(ms, 16, 100);
+            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseFrom(input));
+        }
+
+        /// <summary>
+        /// Tests that if we read an string that contains invalid UTF-8, no exception
+        /// is thrown.  Instead, the invalid bytes are replaced with the Unicode
+        /// "replacement character" U+FFFD.
+        /// </summary>
+        [Test]
+        public void ReadInvalidUtf8()
+        {
+            MemoryStream ms = new MemoryStream();
+            CodedOutputStream output = new CodedOutputStream(ms);
+
+            uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
+            output.WriteRawVarint32(tag);
+            output.WriteRawVarint32(1);
+            output.WriteRawBytes(new byte[] {0x80});
+            output.Flush();
+            ms.Position = 0;
+
+            CodedInputStream input = new CodedInputStream(ms);
+
+            Assert.AreEqual(tag, input.ReadTag());
+            string text = input.ReadString();
+            Assert.AreEqual('\ufffd', text[0]);
+        }
+
+        /// <summary>
+        /// A stream which limits the number of bytes it reads at a time.
+        /// We use this to make sure that CodedInputStream doesn't screw up when
+        /// reading in small blocks.
+        /// </summary>
+        private sealed class SmallBlockInputStream : MemoryStream
+        {
+            private readonly int blockSize;
+
+            public SmallBlockInputStream(byte[] data, int blockSize)
+                : base(data)
+            {
+                this.blockSize = blockSize;
+            }
+
+            public override int Read(byte[] buffer, int offset, int count)
+            {
+                return base.Read(buffer, offset, Math.Min(count, blockSize));
+            }
+        }
+
+        [Test]
+        public void TestNegativeEnum()
+        {
+            byte[] bytes = { 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01 };
+            CodedInputStream input = new CodedInputStream(bytes);
+            Assert.AreEqual((int)SampleEnum.NegativeValue, input.ReadEnum());
+            Assert.IsTrue(input.IsAtEnd);
+        }
+
+        //Issue 71:	CodedInputStream.ReadBytes go to slow path unnecessarily
+        [Test]
+        public void TestSlowPathAvoidance()
+        {
+            using (var ms = new MemoryStream())
+            {
+                CodedOutputStream output = new CodedOutputStream(ms);
+                output.WriteTag(1, WireFormat.WireType.LengthDelimited);
+                output.WriteBytes(ByteString.CopyFrom(new byte[100]));
+                output.WriteTag(2, WireFormat.WireType.LengthDelimited);
+                output.WriteBytes(ByteString.CopyFrom(new byte[100]));
+                output.Flush();
+
+                ms.Position = 0;
+                CodedInputStream input = new CodedInputStream(ms, new byte[ms.Length / 2], 0, 0);
+
+                uint tag = input.ReadTag();
+                Assert.AreEqual(1, WireFormat.GetTagFieldNumber(tag));
+                Assert.AreEqual(100, input.ReadBytes().Length);
+
+                tag = input.ReadTag();
+                Assert.AreEqual(2, WireFormat.GetTagFieldNumber(tag));
+                Assert.AreEqual(100, input.ReadBytes().Length);
+            }
+        }
+
+        [Test]
+        public void Tag0Throws()
+        {
+            var input = new CodedInputStream(new byte[] { 0 });
+            Assert.Throws<InvalidProtocolBufferException>(() => input.ReadTag());
+        }
+
+        [Test]
+        public void SkipGroup()
+        {
+            // Create an output stream with a group in:
+            // Field 1: string "field 1"
+            // Field 2: group containing:
+            //   Field 1: fixed int32 value 100
+            //   Field 2: string "ignore me"
+            //   Field 3: nested group containing
+            //      Field 1: fixed int64 value 1000
+            // Field 3: string "field 3"
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            output.WriteTag(1, WireFormat.WireType.LengthDelimited);
+            output.WriteString("field 1");
+            
+            // The outer group...
+            output.WriteTag(2, WireFormat.WireType.StartGroup);
+            output.WriteTag(1, WireFormat.WireType.Fixed32);
+            output.WriteFixed32(100);
+            output.WriteTag(2, WireFormat.WireType.LengthDelimited);
+            output.WriteString("ignore me");
+            // The nested group...
+            output.WriteTag(3, WireFormat.WireType.StartGroup);
+            output.WriteTag(1, WireFormat.WireType.Fixed64);
+            output.WriteFixed64(1000);
+            // Note: Not sure the field number is relevant for end group...
+            output.WriteTag(3, WireFormat.WireType.EndGroup);
+
+            // End the outer group
+            output.WriteTag(2, WireFormat.WireType.EndGroup);
+
+            output.WriteTag(3, WireFormat.WireType.LengthDelimited);
+            output.WriteString("field 3");
+            output.Flush();
+            stream.Position = 0;
+
+            // Now act like a generated client
+            var input = new CodedInputStream(stream);
+            Assert.AreEqual(WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited), input.ReadTag());
+            Assert.AreEqual("field 1", input.ReadString());
+            Assert.AreEqual(WireFormat.MakeTag(2, WireFormat.WireType.StartGroup), input.ReadTag());
+            input.SkipLastField(); // Should consume the whole group, including the nested one.
+            Assert.AreEqual(WireFormat.MakeTag(3, WireFormat.WireType.LengthDelimited), input.ReadTag());
+            Assert.AreEqual("field 3", input.ReadString());
+        }
+
+        [Test]
+        public void EndOfStreamReachedWhileSkippingGroup()
+        {
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            output.WriteTag(1, WireFormat.WireType.StartGroup);
+            output.WriteTag(2, WireFormat.WireType.StartGroup);
+            output.WriteTag(2, WireFormat.WireType.EndGroup);
+
+            output.Flush();
+            stream.Position = 0;
+
+            // Now act like a generated client
+            var input = new CodedInputStream(stream);
+            input.ReadTag();
+            Assert.Throws<InvalidProtocolBufferException>(() => input.SkipLastField());
+        }
+
+        [Test]
+        public void RecursionLimitAppliedWhileSkippingGroup()
+        {
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            for (int i = 0; i < CodedInputStream.DefaultRecursionLimit + 1; i++)
+            {
+                output.WriteTag(1, WireFormat.WireType.StartGroup);
+            }
+            for (int i = 0; i < CodedInputStream.DefaultRecursionLimit + 1; i++)
+            {
+                output.WriteTag(1, WireFormat.WireType.EndGroup);
+            }
+            output.Flush();
+            stream.Position = 0;
+
+            // Now act like a generated client
+            var input = new CodedInputStream(stream);
+            Assert.AreEqual(WireFormat.MakeTag(1, WireFormat.WireType.StartGroup), input.ReadTag());
+            Assert.Throws<InvalidProtocolBufferException>(() => input.SkipLastField());
+        }
+
+        [Test]
+        public void Construction_Invalid()
+        {
+            Assert.Throws<ArgumentNullException>(() => new CodedInputStream((byte[]) null));
+            Assert.Throws<ArgumentNullException>(() => new CodedInputStream(null, 0, 0));
+            Assert.Throws<ArgumentNullException>(() => new CodedInputStream((Stream) null));
+            Assert.Throws<ArgumentOutOfRangeException>(() => new CodedInputStream(new byte[10], 100, 0));
+            Assert.Throws<ArgumentOutOfRangeException>(() => new CodedInputStream(new byte[10], 5, 10));
+        }
+
+        [Test]
+        public void CreateWithLimits_InvalidLimits()
+        {
+            var stream = new MemoryStream();
+            Assert.Throws<ArgumentOutOfRangeException>(() => CodedInputStream.CreateWithLimits(stream, 0, 1));
+            Assert.Throws<ArgumentOutOfRangeException>(() => CodedInputStream.CreateWithLimits(stream, 1, 0));
+        }
+    }
+}

+ 391 - 0
csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs

@@ -0,0 +1,391 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.IO;
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+
+namespace Google.Protobuf
+{
+    public class CodedOutputStreamTest
+    {
+        /// <summary>
+        /// Writes the given value using WriteRawVarint32() and WriteRawVarint64() and
+        /// checks that the result matches the given bytes
+        /// </summary>
+        private static void AssertWriteVarint(byte[] data, ulong value)
+        {
+            // Only do 32-bit write if the value fits in 32 bits.
+            if ((value >> 32) == 0)
+            {
+                MemoryStream rawOutput = new MemoryStream();
+                CodedOutputStream output = new CodedOutputStream(rawOutput);
+                output.WriteRawVarint32((uint) value);
+                output.Flush();
+                Assert.AreEqual(data, rawOutput.ToArray());
+                // Also try computing size.
+                Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint32Size((uint) value));
+            }
+
+            {
+                MemoryStream rawOutput = new MemoryStream();
+                CodedOutputStream output = new CodedOutputStream(rawOutput);
+                output.WriteRawVarint64(value);
+                output.Flush();
+                Assert.AreEqual(data, rawOutput.ToArray());
+
+                // Also try computing size.
+                Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint64Size(value));
+            }
+
+            // Try different buffer sizes.
+            for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2)
+            {
+                // Only do 32-bit write if the value fits in 32 bits.
+                if ((value >> 32) == 0)
+                {
+                    MemoryStream rawOutput = new MemoryStream();
+                    CodedOutputStream output =
+                        new CodedOutputStream(rawOutput, bufferSize);
+                    output.WriteRawVarint32((uint) value);
+                    output.Flush();
+                    Assert.AreEqual(data, rawOutput.ToArray());
+                }
+
+                {
+                    MemoryStream rawOutput = new MemoryStream();
+                    CodedOutputStream output = new CodedOutputStream(rawOutput, bufferSize);
+                    output.WriteRawVarint64(value);
+                    output.Flush();
+                    Assert.AreEqual(data, rawOutput.ToArray());
+                }
+            }
+        }
+
+        /// <summary>
+        /// Tests WriteRawVarint32() and WriteRawVarint64()
+        /// </summary>
+        [Test]
+        public void WriteVarint()
+        {
+            AssertWriteVarint(new byte[] {0x00}, 0);
+            AssertWriteVarint(new byte[] {0x01}, 1);
+            AssertWriteVarint(new byte[] {0x7f}, 127);
+            // 14882
+            AssertWriteVarint(new byte[] {0xa2, 0x74}, (0x22 << 0) | (0x74 << 7));
+            // 2961488830
+            AssertWriteVarint(new byte[] {0xbe, 0xf7, 0x92, 0x84, 0x0b},
+                              (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
+                              (0x0bL << 28));
+
+            // 64-bit
+            // 7256456126
+            AssertWriteVarint(new byte[] {0xbe, 0xf7, 0x92, 0x84, 0x1b},
+                              (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
+                              (0x1bL << 28));
+            // 41256202580718336
+            AssertWriteVarint(
+                new byte[] {0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49},
+                (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
+                (0x43UL << 28) | (0x49L << 35) | (0x24UL << 42) | (0x49UL << 49));
+            // 11964378330978735131
+            AssertWriteVarint(
+                new byte[] {0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01},
+                unchecked((ulong)
+                          ((0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
+                           (0x3bL << 28) | (0x56L << 35) | (0x00L << 42) |
+                           (0x05L << 49) | (0x26L << 56) | (0x01L << 63))));
+        }
+
+        /// <summary>
+        /// Parses the given bytes using WriteRawLittleEndian32() and checks
+        /// that the result matches the given value.
+        /// </summary>
+        private static void AssertWriteLittleEndian32(byte[] data, uint value)
+        {
+            MemoryStream rawOutput = new MemoryStream();
+            CodedOutputStream output = new CodedOutputStream(rawOutput);
+            output.WriteRawLittleEndian32(value);
+            output.Flush();
+            Assert.AreEqual(data, rawOutput.ToArray());
+
+            // Try different buffer sizes.
+            for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2)
+            {
+                rawOutput = new MemoryStream();
+                output = new CodedOutputStream(rawOutput, bufferSize);
+                output.WriteRawLittleEndian32(value);
+                output.Flush();
+                Assert.AreEqual(data, rawOutput.ToArray());
+            }
+        }
+
+        /// <summary>
+        /// Parses the given bytes using WriteRawLittleEndian64() and checks
+        /// that the result matches the given value.
+        /// </summary>
+        private static void AssertWriteLittleEndian64(byte[] data, ulong value)
+        {
+            MemoryStream rawOutput = new MemoryStream();
+            CodedOutputStream output = new CodedOutputStream(rawOutput);
+            output.WriteRawLittleEndian64(value);
+            output.Flush();
+            Assert.AreEqual(data, rawOutput.ToArray());
+
+            // Try different block sizes.
+            for (int blockSize = 1; blockSize <= 16; blockSize *= 2)
+            {
+                rawOutput = new MemoryStream();
+                output = new CodedOutputStream(rawOutput, blockSize);
+                output.WriteRawLittleEndian64(value);
+                output.Flush();
+                Assert.AreEqual(data, rawOutput.ToArray());
+            }
+        }
+
+        /// <summary>
+        /// Tests writeRawLittleEndian32() and writeRawLittleEndian64().
+        /// </summary>
+        [Test]
+        public void WriteLittleEndian()
+        {
+            AssertWriteLittleEndian32(new byte[] {0x78, 0x56, 0x34, 0x12}, 0x12345678);
+            AssertWriteLittleEndian32(new byte[] {0xf0, 0xde, 0xbc, 0x9a}, 0x9abcdef0);
+
+            AssertWriteLittleEndian64(
+                new byte[] {0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12},
+                0x123456789abcdef0L);
+            AssertWriteLittleEndian64(
+                new byte[] {0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a},
+                0x9abcdef012345678UL);
+        }
+
+        [Test]
+        public void WriteWholeMessage_VaryingBlockSizes()
+        {
+            TestAllTypes message = SampleMessages.CreateFullTestAllTypes();
+
+            byte[] rawBytes = message.ToByteArray();
+
+            // Try different block sizes.
+            for (int blockSize = 1; blockSize < 256; blockSize *= 2)
+            {
+                MemoryStream rawOutput = new MemoryStream();
+                CodedOutputStream output = new CodedOutputStream(rawOutput, blockSize);
+                message.WriteTo(output);
+                output.Flush();
+                Assert.AreEqual(rawBytes, rawOutput.ToArray());
+            }
+        }
+        
+        [Test]
+        public void EncodeZigZag32()
+        {
+            Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag32(0));
+            Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag32(-1));
+            Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag32(1));
+            Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag32(-2));
+            Assert.AreEqual(0x7FFFFFFEu, CodedOutputStream.EncodeZigZag32(0x3FFFFFFF));
+            Assert.AreEqual(0x7FFFFFFFu, CodedOutputStream.EncodeZigZag32(unchecked((int) 0xC0000000)));
+            Assert.AreEqual(0xFFFFFFFEu, CodedOutputStream.EncodeZigZag32(0x7FFFFFFF));
+            Assert.AreEqual(0xFFFFFFFFu, CodedOutputStream.EncodeZigZag32(unchecked((int) 0x80000000)));
+        }
+
+        [Test]
+        public void EncodeZigZag64()
+        {
+            Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag64(0));
+            Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag64(-1));
+            Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag64(1));
+            Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag64(-2));
+            Assert.AreEqual(0x000000007FFFFFFEuL,
+                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000003FFFFFFFUL)));
+            Assert.AreEqual(0x000000007FFFFFFFuL,
+                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFFC0000000UL)));
+            Assert.AreEqual(0x00000000FFFFFFFEuL,
+                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000007FFFFFFFUL)));
+            Assert.AreEqual(0x00000000FFFFFFFFuL,
+                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFF80000000UL)));
+            Assert.AreEqual(0xFFFFFFFFFFFFFFFEL,
+                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0x7FFFFFFFFFFFFFFFUL)));
+            Assert.AreEqual(0xFFFFFFFFFFFFFFFFL,
+                            CodedOutputStream.EncodeZigZag64(unchecked((long) 0x8000000000000000UL)));
+        }
+
+        [Test]
+        public void RoundTripZigZag32()
+        {
+            // Some easier-to-verify round-trip tests.  The inputs (other than 0, 1, -1)
+            // were chosen semi-randomly via keyboard bashing.
+            Assert.AreEqual(0, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(0)));
+            Assert.AreEqual(1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(1)));
+            Assert.AreEqual(-1, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-1)));
+            Assert.AreEqual(14927, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(14927)));
+            Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-3612)));
+        }
+
+        [Test]
+        public void RoundTripZigZag64()
+        {
+            Assert.AreEqual(0, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(0)));
+            Assert.AreEqual(1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(1)));
+            Assert.AreEqual(-1, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-1)));
+            Assert.AreEqual(14927, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(14927)));
+            Assert.AreEqual(-3612, CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-3612)));
+
+            Assert.AreEqual(856912304801416L,
+                            CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(856912304801416L)));
+            Assert.AreEqual(-75123905439571256L,
+                            CodedInputStream.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-75123905439571256L)));
+        }
+
+        [Test]
+        public void TestNegativeEnumNoTag()
+        {
+            Assert.AreEqual(10, CodedOutputStream.ComputeInt32Size(-2));
+            Assert.AreEqual(10, CodedOutputStream.ComputeEnumSize((int) SampleEnum.NegativeValue));
+
+            byte[] bytes = new byte[10];
+            CodedOutputStream output = new CodedOutputStream(bytes);
+            output.WriteEnum((int) SampleEnum.NegativeValue);
+
+            Assert.AreEqual(0, output.SpaceLeft);
+            Assert.AreEqual("FE-FF-FF-FF-FF-FF-FF-FF-FF-01", BitConverter.ToString(bytes));
+        }
+
+        [Test]
+        public void TestCodedInputOutputPosition()
+        {
+            byte[] content = new byte[110];
+            for (int i = 0; i < content.Length; i++)
+                content[i] = (byte)i;
+
+            byte[] child = new byte[120];
+            {
+                MemoryStream ms = new MemoryStream(child);
+                CodedOutputStream cout = new CodedOutputStream(ms, 20);
+                // Field 11: numeric value: 500
+                cout.WriteTag(11, WireFormat.WireType.Varint);
+                Assert.AreEqual(1, cout.Position);
+                cout.WriteInt32(500);
+                Assert.AreEqual(3, cout.Position);
+                //Field 12: length delimited 120 bytes
+                cout.WriteTag(12, WireFormat.WireType.LengthDelimited);
+                Assert.AreEqual(4, cout.Position);
+                cout.WriteBytes(ByteString.CopyFrom(content));
+                Assert.AreEqual(115, cout.Position);
+                // Field 13: fixed numeric value: 501
+                cout.WriteTag(13, WireFormat.WireType.Fixed32);
+                Assert.AreEqual(116, cout.Position);
+                cout.WriteSFixed32(501);
+                Assert.AreEqual(120, cout.Position);
+                cout.Flush();
+            }
+
+            byte[] bytes = new byte[130];
+            {
+                CodedOutputStream cout = new CodedOutputStream(bytes);
+                // Field 1: numeric value: 500
+                cout.WriteTag(1, WireFormat.WireType.Varint);
+                Assert.AreEqual(1, cout.Position);
+                cout.WriteInt32(500);
+                Assert.AreEqual(3, cout.Position);
+                //Field 2: length delimited 120 bytes
+                cout.WriteTag(2, WireFormat.WireType.LengthDelimited);
+                Assert.AreEqual(4, cout.Position);
+                cout.WriteBytes(ByteString.CopyFrom(child));
+                Assert.AreEqual(125, cout.Position);
+                // Field 3: fixed numeric value: 500
+                cout.WriteTag(3, WireFormat.WireType.Fixed32);
+                Assert.AreEqual(126, cout.Position);
+                cout.WriteSFixed32(501);
+                Assert.AreEqual(130, cout.Position);
+                cout.Flush();
+            }
+            // Now test Input stream:
+            {
+                CodedInputStream cin = new CodedInputStream(new MemoryStream(bytes), new byte[50], 0, 0);
+                Assert.AreEqual(0, cin.Position);
+                // Field 1:
+                uint tag = cin.ReadTag();
+                Assert.AreEqual(1, tag >> 3);
+                Assert.AreEqual(1, cin.Position);
+                Assert.AreEqual(500, cin.ReadInt32());
+                Assert.AreEqual(3, cin.Position);
+                //Field 2:
+                tag = cin.ReadTag();
+                Assert.AreEqual(2, tag >> 3);
+                Assert.AreEqual(4, cin.Position);
+                int childlen = cin.ReadLength();
+                Assert.AreEqual(120, childlen);
+                Assert.AreEqual(5, cin.Position);
+                int oldlimit = cin.PushLimit((int)childlen);
+                Assert.AreEqual(5, cin.Position);
+                // Now we are reading child message
+                {
+                    // Field 11: numeric value: 500
+                    tag = cin.ReadTag();
+                    Assert.AreEqual(11, tag >> 3);
+                    Assert.AreEqual(6, cin.Position);
+                    Assert.AreEqual(500, cin.ReadInt32());
+                    Assert.AreEqual(8, cin.Position);
+                    //Field 12: length delimited 120 bytes
+                    tag = cin.ReadTag();
+                    Assert.AreEqual(12, tag >> 3);
+                    Assert.AreEqual(9, cin.Position);
+                    ByteString bstr = cin.ReadBytes();
+                    Assert.AreEqual(110, bstr.Length);
+                    Assert.AreEqual((byte) 109, bstr[109]);
+                    Assert.AreEqual(120, cin.Position);
+                    // Field 13: fixed numeric value: 501
+                    tag = cin.ReadTag();
+                    Assert.AreEqual(13, tag >> 3);
+                    // ROK - Previously broken here, this returned 126 failing to account for bufferSizeAfterLimit
+                    Assert.AreEqual(121, cin.Position);
+                    Assert.AreEqual(501, cin.ReadSFixed32());
+                    Assert.AreEqual(125, cin.Position);
+                    Assert.IsTrue(cin.IsAtEnd);
+                }
+                cin.PopLimit(oldlimit);
+                Assert.AreEqual(125, cin.Position);
+                // Field 3: fixed numeric value: 501
+                tag = cin.ReadTag();
+                Assert.AreEqual(3, tag >> 3);
+                Assert.AreEqual(126, cin.Position);
+                Assert.AreEqual(501, cin.ReadSFixed32());
+                Assert.AreEqual(130, cin.Position);
+                Assert.IsTrue(cin.IsAtEnd);
+            }
+        }
+    }
+}

+ 570 - 0
csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs

@@ -0,0 +1,570 @@
+#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;
+using System.Collections;
+using System.Linq;
+
+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
+    {
+        [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 NullValues()
+        {
+            TestNullValues<int?>(0);
+            TestNullValues("");
+            TestNullValues(new TestAllTypes());
+        }
+
+        private void TestNullValues<T>(T nonNullValue)
+        {
+            var map = new MapField<int, T>(false);
+            var nullValue = (T) (object) null;
+            Assert.Throws<ArgumentNullException>(() => map.Add(0, nullValue));
+            Assert.Throws<ArgumentNullException>(() => map[0] = nullValue);
+            map.Add(1, nonNullValue);
+            map[1] = nonNullValue;
+
+            // Doesn't throw...
+            map = new MapField<int, T>(true);
+            map.Add(0, nullValue);
+            map[0] = nullValue;
+            map.Add(1, nonNullValue);
+            map[1] = nonNullValue;
+        }
+
+        [Test]
+        public void Add_ForbidsNullKeys()
+        {
+            var map = new MapField<string, ForeignMessage>();
+            Assert.Throws<ArgumentNullException>(() => map.Add(null, new ForeignMessage()));
+        }
+
+        [Test]
+        public void Indexer_ForbidsNullKeys()
+        {
+            var map = new MapField<string, ForeignMessage>();
+            Assert.Throws<ArgumentNullException>(() => map[null] = new ForeignMessage());
+        }
+        
+        [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 Equality_Simple()
+        {
+            var map = new MapField<string, string>();
+            EqualityTester.AssertEquality(map, map);
+            EqualityTester.AssertInequality(map, null);
+            Assert.IsFalse(map.Equals(new object()));
+        }
+
+        [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);
+            Assert.Throws<ArgumentNullException>(() => map.Remove(null));
+        }
+
+        [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"]);
+        }
+
+        [Test]
+        public void GetEnumerator_NonGeneric()
+        {
+            IEnumerable map = new MapField<string, string> { { "x", "y" } };
+            CollectionAssert.AreEqual(new[] { new KeyValuePair<string, string>("x", "y") },
+                map.Cast<object>().ToList());
+        }
+
+        // Test for the explicitly-implemented non-generic IDictionary interface
+        [Test]
+        public void IDictionary_GetEnumerator()
+        {
+            IDictionary map = new MapField<string, string> { { "x", "y" } };
+            var enumerator = map.GetEnumerator();
+
+            // Commented assertions show an ideal situation - it looks like
+            // the LinkedList enumerator doesn't throw when you ask for the current entry
+            // at an inappropriate time; fixing this would be more work than it's worth.
+            // Assert.Throws<InvalidOperationException>(() => enumerator.Current.GetHashCode());
+            Assert.IsTrue(enumerator.MoveNext());
+            Assert.AreEqual("x", enumerator.Key);
+            Assert.AreEqual("y", enumerator.Value);
+            Assert.AreEqual(new DictionaryEntry("x", "y"), enumerator.Current);
+            Assert.AreEqual(new DictionaryEntry("x", "y"), enumerator.Entry);
+            Assert.IsFalse(enumerator.MoveNext());
+            // Assert.Throws<InvalidOperationException>(() => enumerator.Current.GetHashCode());
+            enumerator.Reset();
+            // Assert.Throws<InvalidOperationException>(() => enumerator.Current.GetHashCode());
+            Assert.IsTrue(enumerator.MoveNext());
+            Assert.AreEqual("x", enumerator.Key); // Assume the rest are okay
+        }
+
+        [Test]
+        public void IDictionary_Add()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            IDictionary dictionary = map;
+            dictionary.Add("a", "b");
+            Assert.AreEqual("b", map["a"]);
+            Assert.Throws<ArgumentException>(() => dictionary.Add("a", "duplicate"));
+            Assert.Throws<InvalidCastException>(() => dictionary.Add(new object(), "key is bad"));
+            Assert.Throws<InvalidCastException>(() => dictionary.Add("value is bad", new object()));
+        }
+
+        [Test]
+        public void IDictionary_Contains()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            IDictionary dictionary = map;
+
+            Assert.IsFalse(dictionary.Contains("a"));
+            Assert.IsFalse(dictionary.Contains(5));
+            // Surprising, but IDictionary.Contains is only about keys.
+            Assert.IsFalse(dictionary.Contains(new DictionaryEntry("x", "y")));
+            Assert.IsTrue(dictionary.Contains("x"));
+        }
+
+        [Test]
+        public void IDictionary_Remove()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            IDictionary dictionary = map;
+            dictionary.Remove("a");
+            Assert.AreEqual(1, dictionary.Count);
+            dictionary.Remove(5);
+            Assert.AreEqual(1, dictionary.Count);
+            dictionary.Remove(new DictionaryEntry("x", "y"));
+            Assert.AreEqual(1, dictionary.Count);
+            dictionary.Remove("x");
+            Assert.AreEqual(0, dictionary.Count);
+            Assert.Throws<ArgumentNullException>(() => dictionary.Remove(null));
+        }
+
+        [Test]
+        public void IDictionary_CopyTo()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            IDictionary dictionary = map;
+            var array = new DictionaryEntry[3];
+            dictionary.CopyTo(array, 1);
+            CollectionAssert.AreEqual(new[] { default(DictionaryEntry), new DictionaryEntry("x", "y"), default(DictionaryEntry) },
+                array);
+            var objectArray = new object[3];
+            dictionary.CopyTo(objectArray, 1);
+            CollectionAssert.AreEqual(new object[] { null, new DictionaryEntry("x", "y"), null },
+                objectArray);
+        }
+
+        [Test]
+        public void IDictionary_IsFixedSize()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            IDictionary dictionary = map;
+            Assert.IsFalse(dictionary.IsFixedSize);
+        }
+
+        [Test]
+        public void IDictionary_Keys()
+        {
+            IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
+            CollectionAssert.AreEqual(new[] { "x" }, dictionary.Keys);
+        }
+
+        [Test]
+        public void IDictionary_Values()
+        {
+            IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
+            CollectionAssert.AreEqual(new[] { "y" }, dictionary.Values);
+        }
+
+        [Test]
+        public void IDictionary_IsSynchronized()
+        {
+            IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
+            Assert.IsFalse(dictionary.IsSynchronized);
+        }
+
+        [Test]
+        public void IDictionary_SyncRoot()
+        {
+            IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
+            Assert.AreSame(dictionary, dictionary.SyncRoot);
+        }
+
+        [Test]
+        public void IDictionary_Indexer_Get()
+        {
+            IDictionary dictionary = new MapField<string, string> { { "x", "y" } };
+            Assert.AreEqual("y", dictionary["x"]);
+            Assert.IsNull(dictionary["a"]);
+            Assert.IsNull(dictionary[5]);
+            Assert.Throws<ArgumentNullException>(() => dictionary[null].GetHashCode());
+        }
+
+        [Test]
+        public void IDictionary_Indexer_Set()
+        {
+            var map = new MapField<string, string> { { "x", "y" } };
+            IDictionary dictionary = map;
+            map["a"] = "b";
+            Assert.AreEqual("b", map["a"]);
+            map["a"] = "c";
+            Assert.AreEqual("c", map["a"]);
+            Assert.Throws<InvalidCastException>(() => dictionary[5] = "x");
+            Assert.Throws<InvalidCastException>(() => dictionary["x"] = 5);
+            Assert.Throws<ArgumentNullException>(() => dictionary[null] = "z");
+            Assert.Throws<ArgumentNullException>(() => dictionary["x"] = null);
+        }
+
+        [Test]
+        public void AllowNullValues_Property()
+        {
+            // Non-message reference type values are non-nullable by default, but can be overridden
+            Assert.IsFalse(new MapField<int, string>().AllowsNullValues);
+            Assert.IsFalse(new MapField<int, string>(false).AllowsNullValues);
+            Assert.IsTrue(new MapField<int, string>(true).AllowsNullValues);
+
+            // Non-nullable value type values are never nullable
+            Assert.IsFalse(new MapField<int, int>().AllowsNullValues);
+            Assert.IsFalse(new MapField<int, int>(false).AllowsNullValues);
+            Assert.Throws<ArgumentException>(() => new MapField<int, int>(true));
+
+            // Message type values are nullable by default, but can be overridden
+            Assert.IsTrue(new MapField<int, TestAllTypes>().AllowsNullValues);
+            Assert.IsFalse(new MapField<int, TestAllTypes>(false).AllowsNullValues);
+            Assert.IsTrue(new MapField<int, TestAllTypes>(true).AllowsNullValues);
+
+            // Nullable value type values are nullable by default, but can be overridden
+            Assert.IsTrue(new MapField<int, int?>().AllowsNullValues);
+            Assert.IsFalse(new MapField<int, int?>(false).AllowsNullValues);
+            Assert.IsTrue(new MapField<int, int?>(true).AllowsNullValues);
+        }
+
+        [Test]
+        public void KeysReturnsLiveView()
+        {
+            var map = new MapField<string, string>();
+            var keys = map.Keys;
+            CollectionAssert.AreEqual(new string[0], keys);
+            map["foo"] = "bar";
+            map["x"] = "y";
+            CollectionAssert.AreEqual(new[] { "foo", "x" }, keys);
+        }
+
+        [Test]
+        public void ValuesReturnsLiveView()
+        {
+            var map = new MapField<string, string>();
+            var values = map.Values;
+            CollectionAssert.AreEqual(new string[0], values);
+            map["foo"] = "bar";
+            map["x"] = "y";
+            CollectionAssert.AreEqual(new[] { "bar", "y" }, values);
+        }
+
+        // Just test keys - we know the implementation is the same for values
+        [Test]
+        public void ViewsAreReadOnly()
+        {
+            var map = new MapField<string, string>();
+            var keys = map.Keys;
+            Assert.IsTrue(keys.IsReadOnly);
+            Assert.Throws<NotSupportedException>(() => keys.Clear());
+            Assert.Throws<NotSupportedException>(() => keys.Remove("a"));
+            Assert.Throws<NotSupportedException>(() => keys.Add("a"));
+        }
+
+        // Just test keys - we know the implementation is the same for values
+        [Test]
+        public void ViewCopyTo()
+        {
+            var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
+            var keys = map.Keys;
+            var array = new string[4];
+            Assert.Throws<ArgumentException>(() => keys.CopyTo(array, 3));
+            Assert.Throws<ArgumentOutOfRangeException>(() => keys.CopyTo(array, -1));
+            keys.CopyTo(array, 1);
+            CollectionAssert.AreEqual(new[] { null, "foo", "x", null }, array);
+        }
+        
+        // Just test keys - we know the implementation is the same for values
+        [Test]
+        public void NonGenericViewCopyTo()
+        {
+            IDictionary map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
+            ICollection keys = map.Keys;
+            // Note the use of the Array type here rather than string[]
+            Array array = new string[4];
+            Assert.Throws<ArgumentException>(() => keys.CopyTo(array, 3));
+            Assert.Throws<ArgumentOutOfRangeException>(() => keys.CopyTo(array, -1));
+            keys.CopyTo(array, 1);
+            CollectionAssert.AreEqual(new[] { null, "foo", "x", null }, array);
+        }
+
+        [Test]
+        public void KeysContains()
+        {
+            var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
+            var keys = map.Keys;
+            Assert.IsTrue(keys.Contains("foo"));
+            Assert.IsFalse(keys.Contains("bar")); // It's a value!
+            Assert.IsFalse(keys.Contains("1"));
+            // Keys can't be null, so we should prevent contains check
+            Assert.Throws<ArgumentNullException>(() => keys.Contains(null));
+        }
+
+        [Test]
+        public void ValuesContains()
+        {
+            var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
+            var values = map.Values;
+            Assert.IsTrue(values.Contains("bar"));
+            Assert.IsFalse(values.Contains("foo")); // It's a key!
+            Assert.IsFalse(values.Contains("1"));
+            // Values can be null, so this makes sense
+            Assert.IsFalse(values.Contains(null));
+        }
+
+        private static KeyValuePair<TKey, TValue> NewKeyValuePair<TKey, TValue>(TKey key, TValue value)
+        {
+            return new KeyValuePair<TKey, TValue>(key, value);
+        }
+    }
+}

+ 603 - 0
csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs

@@ -0,0 +1,603 @@
+#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.IO;
+using System.Linq;
+using System.Text;
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+
+namespace Google.Protobuf.Collections
+{
+    public class RepeatedFieldTest
+    {
+        [Test]
+        public void NullValuesRejected()
+        {
+            var list = new RepeatedField<string>();
+            Assert.Throws<ArgumentNullException>(() => list.Add((string)null));
+            Assert.Throws<ArgumentNullException>(() => list.Add((IEnumerable<string>)null));
+            Assert.Throws<ArgumentNullException>(() => list.Add((RepeatedField<string>)null));
+            Assert.Throws<ArgumentNullException>(() => list.Contains(null));
+            Assert.Throws<ArgumentNullException>(() => list.IndexOf(null));
+        }
+
+        [Test]
+        public void Add_SingleItem()
+        {
+            var list = new RepeatedField<string>();
+            list.Add("foo");
+            Assert.AreEqual(1, list.Count);
+            Assert.AreEqual("foo", list[0]);
+        }
+
+        [Test]
+        public void Add_Sequence()
+        {
+            var list = new RepeatedField<string>();
+            list.Add(new[] { "foo", "bar" });
+            Assert.AreEqual(2, list.Count);
+            Assert.AreEqual("foo", list[0]);
+            Assert.AreEqual("bar", list[1]);
+        }
+
+        [Test]
+        public void Add_RepeatedField()
+        {
+            var list = new RepeatedField<string> { "original" };
+            list.Add(new RepeatedField<string> { "foo", "bar" });
+            Assert.AreEqual(3, list.Count);
+            Assert.AreEqual("original", list[0]);
+            Assert.AreEqual("foo", list[1]);
+            Assert.AreEqual("bar", list[2]);
+        }
+
+        [Test]
+        public void RemoveAt_Valid()
+        {
+            var list = new RepeatedField<string> { "first", "second", "third" };
+            list.RemoveAt(1);
+            CollectionAssert.AreEqual(new[] { "first", "third" }, list);
+            // Just check that these don't throw...
+            list.RemoveAt(list.Count - 1); // Now the count will be 1...
+            list.RemoveAt(0);
+            Assert.AreEqual(0, list.Count);
+        }
+
+        [Test]
+        public void RemoveAt_Invalid()
+        {
+            var list = new RepeatedField<string> { "first", "second", "third" };
+            Assert.Throws<ArgumentOutOfRangeException>(() => list.RemoveAt(-1));
+            Assert.Throws<ArgumentOutOfRangeException>(() => list.RemoveAt(3));
+        }
+
+        [Test]
+        public void Insert_Valid()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            list.Insert(1, "middle");
+            CollectionAssert.AreEqual(new[] { "first", "middle", "second" }, list);
+            list.Insert(3, "end");
+            CollectionAssert.AreEqual(new[] { "first", "middle", "second", "end" }, list);
+            list.Insert(0, "start");
+            CollectionAssert.AreEqual(new[] { "start", "first", "middle", "second", "end" }, list);
+        }
+
+        [Test]
+        public void Insert_Invalid()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            Assert.Throws<ArgumentOutOfRangeException>(() => list.Insert(-1, "foo"));
+            Assert.Throws<ArgumentOutOfRangeException>(() => list.Insert(3, "foo"));
+            Assert.Throws<ArgumentNullException>(() => list.Insert(0, null));
+        }
+
+        [Test]
+        public void Equals_RepeatedField()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            Assert.IsFalse(list.Equals((RepeatedField<string>) null));
+            Assert.IsTrue(list.Equals(list));
+            Assert.IsFalse(list.Equals(new RepeatedField<string> { "first", "third" }));
+            Assert.IsFalse(list.Equals(new RepeatedField<string> { "first" }));
+            Assert.IsTrue(list.Equals(new RepeatedField<string> { "first", "second" }));
+        }
+
+        [Test]
+        public void Equals_Object()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            Assert.IsFalse(list.Equals((object) null));
+            Assert.IsTrue(list.Equals((object) list));
+            Assert.IsFalse(list.Equals((object) new RepeatedField<string> { "first", "third" }));
+            Assert.IsFalse(list.Equals((object) new RepeatedField<string> { "first" }));
+            Assert.IsTrue(list.Equals((object) new RepeatedField<string> { "first", "second" }));
+            Assert.IsFalse(list.Equals(new object()));
+        }
+
+        [Test]
+        public void GetEnumerator_GenericInterface()
+        {
+            IEnumerable<string> list = new RepeatedField<string> { "first", "second" };
+            // Select gets rid of the optimizations in ToList...
+            CollectionAssert.AreEqual(new[] { "first", "second" }, list.Select(x => x).ToList());
+        }
+
+        [Test]
+        public void GetEnumerator_NonGenericInterface()
+        {
+            IEnumerable list = new RepeatedField<string> { "first", "second" };
+            CollectionAssert.AreEqual(new[] { "first", "second" }, list.Cast<object>().ToList());
+        }
+
+        [Test]
+        public void CopyTo()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            string[] stringArray = new string[4];
+            list.CopyTo(stringArray, 1);
+            CollectionAssert.AreEqual(new[] { null, "first", "second", null }, stringArray);
+        }
+
+        [Test]
+        public void Indexer_Get()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            Assert.AreEqual("first", list[0]);
+            Assert.AreEqual("second", list[1]);
+            Assert.Throws<ArgumentOutOfRangeException>(() => list[-1].GetHashCode());
+            Assert.Throws<ArgumentOutOfRangeException>(() => list[2].GetHashCode());
+        }
+
+        [Test]
+        public void Indexer_Set()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            list[0] = "changed";
+            Assert.AreEqual("changed", list[0]);
+            Assert.Throws<ArgumentNullException>(() => list[0] = null);
+            Assert.Throws<ArgumentOutOfRangeException>(() => list[-1] = "bad");
+            Assert.Throws<ArgumentOutOfRangeException>(() => list[2] = "bad");
+        }
+
+        [Test]
+        public void Clone_ReturnsMutable()
+        {
+            var list = new RepeatedField<int> { 0 };
+            var clone = list.Clone();
+            clone[0] = 1;
+        }
+
+        [Test]
+        public void Enumerator()
+        {
+            var list = new RepeatedField<string> { "first", "second" };
+            using (var enumerator = list.GetEnumerator())
+            {
+                Assert.IsTrue(enumerator.MoveNext());
+                Assert.AreEqual("first", enumerator.Current);
+                Assert.IsTrue(enumerator.MoveNext());
+                Assert.AreEqual("second", enumerator.Current);
+                Assert.IsFalse(enumerator.MoveNext());
+                Assert.IsFalse(enumerator.MoveNext());
+            }
+        }
+
+        [Test]
+        public void AddEntriesFrom_PackedInt32()
+        {
+            uint packedTag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            var length = CodedOutputStream.ComputeInt32Size(10)
+                + CodedOutputStream.ComputeInt32Size(999)
+                + CodedOutputStream.ComputeInt32Size(-1000);
+            output.WriteTag(packedTag);
+            output.WriteRawVarint32((uint) length);
+            output.WriteInt32(10);
+            output.WriteInt32(999);
+            output.WriteInt32(-1000);
+            output.Flush();
+            stream.Position = 0;
+
+            // Deliberately "expecting" a non-packed tag, but we detect that the data is
+            // actually packed.
+            uint nonPackedTag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
+            var field = new RepeatedField<int>();
+            var input = new CodedInputStream(stream);
+            input.AssertNextTag(packedTag);
+            field.AddEntriesFrom(input, FieldCodec.ForInt32(nonPackedTag));
+            CollectionAssert.AreEqual(new[] { 10, 999, -1000 }, field);
+            Assert.IsTrue(input.IsAtEnd);
+        }
+
+        [Test]
+        public void AddEntriesFrom_NonPackedInt32()
+        {
+            uint nonPackedTag = WireFormat.MakeTag(10, WireFormat.WireType.Varint);
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            output.WriteTag(nonPackedTag);
+            output.WriteInt32(10);
+            output.WriteTag(nonPackedTag);
+            output.WriteInt32(999);
+            output.WriteTag(nonPackedTag);
+            output.WriteInt32(-1000); // Just for variety...
+            output.Flush();
+            stream.Position = 0;
+
+            // Deliberately "expecting" a packed tag, but we detect that the data is
+            // actually not packed.
+            uint packedTag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
+            var field = new RepeatedField<int>();
+            var input = new CodedInputStream(stream);
+            input.AssertNextTag(nonPackedTag);
+            field.AddEntriesFrom(input, FieldCodec.ForInt32(packedTag));
+            CollectionAssert.AreEqual(new[] { 10, 999, -1000 }, field);
+            Assert.IsTrue(input.IsAtEnd);
+        }
+
+        [Test]
+        public void AddEntriesFrom_String()
+        {
+            uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            output.WriteTag(tag);
+            output.WriteString("Foo");
+            output.WriteTag(tag);
+            output.WriteString("");
+            output.WriteTag(tag);
+            output.WriteString("Bar");
+            output.Flush();
+            stream.Position = 0;
+
+            var field = new RepeatedField<string>();
+            var input = new CodedInputStream(stream);
+            input.AssertNextTag(tag);
+            field.AddEntriesFrom(input, FieldCodec.ForString(tag));
+            CollectionAssert.AreEqual(new[] { "Foo", "", "Bar" }, field);
+            Assert.IsTrue(input.IsAtEnd);
+        }
+
+        [Test]
+        public void AddEntriesFrom_Message()
+        {
+            var message1 = new ForeignMessage { C = 2000 };
+            var message2 = new ForeignMessage { C = -250 };
+
+            uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            output.WriteTag(tag);
+            output.WriteMessage(message1);
+            output.WriteTag(tag);
+            output.WriteMessage(message2);
+            output.Flush();
+            stream.Position = 0;
+
+            var field = new RepeatedField<ForeignMessage>();
+            var input = new CodedInputStream(stream);
+            input.AssertNextTag(tag);
+            field.AddEntriesFrom(input, FieldCodec.ForMessage(tag, ForeignMessage.Parser));
+            CollectionAssert.AreEqual(new[] { message1, message2}, field);
+            Assert.IsTrue(input.IsAtEnd);
+        }
+
+        [Test]
+        public void WriteTo_PackedInt32()
+        {
+            uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
+            var field = new RepeatedField<int> { 10, 1000, 1000000 };
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            field.WriteTo(output, FieldCodec.ForInt32(tag));
+            output.Flush();
+            stream.Position = 0;
+
+            var input = new CodedInputStream(stream);
+            input.AssertNextTag(tag);
+            var length = input.ReadLength();
+            Assert.AreEqual(10, input.ReadInt32());
+            Assert.AreEqual(1000, input.ReadInt32());
+            Assert.AreEqual(1000000, input.ReadInt32());
+            Assert.IsTrue(input.IsAtEnd);
+            Assert.AreEqual(1 + CodedOutputStream.ComputeLengthSize(length) + length, stream.Length);
+        }
+
+        [Test]
+        public void WriteTo_NonPackedInt32()
+        {
+            uint tag = WireFormat.MakeTag(10, WireFormat.WireType.Varint);
+            var field = new RepeatedField<int> { 10, 1000, 1000000};
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            field.WriteTo(output, FieldCodec.ForInt32(tag));
+            output.Flush();
+            stream.Position = 0;
+
+            var input = new CodedInputStream(stream);
+            input.AssertNextTag(tag);
+            Assert.AreEqual(10, input.ReadInt32());
+            input.AssertNextTag(tag);
+            Assert.AreEqual(1000, input.ReadInt32());
+            input.AssertNextTag(tag);
+            Assert.AreEqual(1000000, input.ReadInt32());
+            Assert.IsTrue(input.IsAtEnd);
+        }
+
+        [Test]
+        public void WriteTo_String()
+        {
+            uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
+            var field = new RepeatedField<string> { "Foo", "", "Bar" };
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            field.WriteTo(output, FieldCodec.ForString(tag));
+            output.Flush();
+            stream.Position = 0;
+
+            var input = new CodedInputStream(stream);
+            input.AssertNextTag(tag);
+            Assert.AreEqual("Foo", input.ReadString());
+            input.AssertNextTag(tag);
+            Assert.AreEqual("", input.ReadString());
+            input.AssertNextTag(tag);
+            Assert.AreEqual("Bar", input.ReadString());
+            Assert.IsTrue(input.IsAtEnd);
+        }
+
+        [Test]
+        public void WriteTo_Message()
+        {
+            var message1 = new ForeignMessage { C = 20 };
+            var message2 = new ForeignMessage { C = 25 };
+            uint tag = WireFormat.MakeTag(10, WireFormat.WireType.LengthDelimited);
+            var field = new RepeatedField<ForeignMessage> { message1, message2 };
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            field.WriteTo(output, FieldCodec.ForMessage(tag, ForeignMessage.Parser));
+            output.Flush();
+            stream.Position = 0;
+
+            var input = new CodedInputStream(stream);
+            input.AssertNextTag(tag);
+            Assert.AreEqual(message1, input.ReadMessage(ForeignMessage.Parser));
+            input.AssertNextTag(tag);
+            Assert.AreEqual(message2, input.ReadMessage(ForeignMessage.Parser));
+            Assert.IsTrue(input.IsAtEnd);
+        }
+
+        [Test]
+        public void CalculateSize_VariableSizeNonPacked()
+        {
+            var list = new RepeatedField<int> { 1, 500, 1 };
+            var tag = WireFormat.MakeTag(1, WireFormat.WireType.Varint);
+            // 2 bytes for the first entry, 3 bytes for the second, 2 bytes for the third
+            Assert.AreEqual(7, list.CalculateSize(FieldCodec.ForInt32(tag)));
+        }
+
+        [Test]
+        public void CalculateSize_FixedSizeNonPacked()
+        {
+            var list = new RepeatedField<int> { 1, 500, 1 };
+            var tag = WireFormat.MakeTag(1, WireFormat.WireType.Fixed32);
+            // 5 bytes for the each entry
+            Assert.AreEqual(15, list.CalculateSize(FieldCodec.ForSFixed32(tag)));
+        }
+
+        [Test]
+        public void CalculateSize_VariableSizePacked()
+        {
+            var list = new RepeatedField<int> { 1, 500, 1};
+            var tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
+            // 1 byte for the tag, 1 byte for the length,
+            // 1 byte for the first entry, 2 bytes for the second, 1 byte for the third
+            Assert.AreEqual(6, list.CalculateSize(FieldCodec.ForInt32(tag)));
+        }
+
+        [Test]
+        public void CalculateSize_FixedSizePacked()
+        {
+            var list = new RepeatedField<int> { 1, 500, 1 };
+            var tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);
+            // 1 byte for the tag, 1 byte for the length, 4 bytes per entry
+            Assert.AreEqual(14, list.CalculateSize(FieldCodec.ForSFixed32(tag)));
+        }
+
+        [Test]
+        public void TestNegativeEnumArray()
+        {
+            int arraySize = 1 + 1 + (11 * 5);
+            int msgSize = arraySize;
+            byte[] bytes = new byte[msgSize];
+            CodedOutputStream output = new CodedOutputStream(bytes);
+            uint tag = WireFormat.MakeTag(8, WireFormat.WireType.Varint);
+            for (int i = 0; i >= -5; i--)
+            {
+                output.WriteTag(tag);
+                output.WriteEnum(i);
+            }
+
+            Assert.AreEqual(0, output.SpaceLeft);
+
+            CodedInputStream input = new CodedInputStream(bytes);
+            tag = input.ReadTag();
+
+            RepeatedField<SampleEnum> values = new RepeatedField<SampleEnum>();
+            values.AddEntriesFrom(input, FieldCodec.ForEnum(tag, x => (int)x, x => (SampleEnum)x));
+
+            Assert.AreEqual(6, values.Count);
+            Assert.AreEqual(SampleEnum.None, values[0]);
+            Assert.AreEqual(((SampleEnum)(-1)), values[1]);
+            Assert.AreEqual(SampleEnum.NegativeValue, values[2]);
+            Assert.AreEqual(((SampleEnum)(-3)), values[3]);
+            Assert.AreEqual(((SampleEnum)(-4)), values[4]);
+            Assert.AreEqual(((SampleEnum)(-5)), values[5]);
+        }
+
+
+        [Test]
+        public void TestNegativeEnumPackedArray()
+        {
+            int arraySize = 1 + (10 * 5);
+            int msgSize = 1 + 1 + arraySize;
+            byte[] bytes = new byte[msgSize];
+            CodedOutputStream output = new CodedOutputStream(bytes);
+            // Length-delimited to show we want the packed representation
+            uint tag = WireFormat.MakeTag(8, WireFormat.WireType.LengthDelimited);
+            output.WriteTag(tag);
+            int size = 0;
+            for (int i = 0; i >= -5; i--)
+            {
+                size += CodedOutputStream.ComputeEnumSize(i);
+            }
+            output.WriteRawVarint32((uint)size);
+            for (int i = 0; i >= -5; i--)
+            {
+                output.WriteEnum(i);
+            }
+            Assert.AreEqual(0, output.SpaceLeft);
+
+            CodedInputStream input = new CodedInputStream(bytes);
+            tag = input.ReadTag();
+
+            RepeatedField<SampleEnum> values = new RepeatedField<SampleEnum>();
+            values.AddEntriesFrom(input, FieldCodec.ForEnum(tag, x => (int)x, x => (SampleEnum)x));
+
+            Assert.AreEqual(6, values.Count);
+            Assert.AreEqual(SampleEnum.None, values[0]);
+            Assert.AreEqual(((SampleEnum)(-1)), values[1]);
+            Assert.AreEqual(SampleEnum.NegativeValue, values[2]);
+            Assert.AreEqual(((SampleEnum)(-3)), values[3]);
+            Assert.AreEqual(((SampleEnum)(-4)), values[4]);
+            Assert.AreEqual(((SampleEnum)(-5)), values[5]);
+        }
+
+        // Fairly perfunctory tests for the non-generic IList implementation
+        [Test]
+        public void IList_Indexer()
+        {
+            var field = new RepeatedField<string> { "first", "second" };
+            IList list = field;
+            Assert.AreEqual("first", list[0]);
+            list[1] = "changed";
+            Assert.AreEqual("changed", field[1]);
+        }
+
+        [Test]
+        public void IList_Contains()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            Assert.IsTrue(list.Contains("second"));
+            Assert.IsFalse(list.Contains("third"));
+            Assert.IsFalse(list.Contains(new object()));
+        }
+
+        [Test]
+        public void IList_Add()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            list.Add("third");
+            CollectionAssert.AreEqual(new[] { "first", "second", "third" }, list);
+        }
+
+        [Test]
+        public void IList_Remove()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            list.Remove("third"); // No-op, no exception
+            list.Remove(new object()); // No-op, no exception
+            list.Remove("first");
+            CollectionAssert.AreEqual(new[] { "second" }, list);
+        }
+
+        [Test]
+        public void IList_IsFixedSize()
+        {
+            var field = new RepeatedField<string> { "first", "second" };
+            IList list = field;
+            Assert.IsFalse(list.IsFixedSize);
+        }
+
+        [Test]
+        public void IList_IndexOf()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            Assert.AreEqual(1, list.IndexOf("second"));
+            Assert.AreEqual(-1, list.IndexOf("third"));
+            Assert.AreEqual(-1, list.IndexOf(new object()));
+        }
+
+        [Test]
+        public void IList_SyncRoot()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            Assert.AreSame(list, list.SyncRoot);
+        }
+
+        [Test]
+        public void IList_CopyTo()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            string[] stringArray = new string[4];
+            list.CopyTo(stringArray, 1);
+            CollectionAssert.AreEqual(new[] { null, "first",  "second", null }, stringArray);
+
+            object[] objectArray = new object[4];
+            list.CopyTo(objectArray, 1);
+            CollectionAssert.AreEqual(new[] { null, "first", "second", null }, objectArray);
+
+            Assert.Throws<ArrayTypeMismatchException>(() => list.CopyTo(new StringBuilder[4], 1));
+            Assert.Throws<ArrayTypeMismatchException>(() => list.CopyTo(new int[4], 1));
+        }
+
+        [Test]
+        public void IList_IsSynchronized()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            Assert.IsFalse(list.IsSynchronized);
+        }
+
+        [Test]
+        public void IList_Insert()
+        {
+            IList list = new RepeatedField<string> { "first", "second" };
+            list.Insert(1, "middle");
+            CollectionAssert.AreEqual(new[] { "first", "middle", "second" }, list);
+        }
+    }
+}

+ 98 - 0
csharp/src/Google.Protobuf.Test/Compatibility/PropertyInfoExtensionsTest.cs

@@ -0,0 +1,98 @@
+#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 NUnit.Framework;
+using System.Reflection;
+
+namespace Google.Protobuf.Compatibility
+{
+    public class PropertyInfoExtensionsTest
+    {
+        public string PublicReadWrite { get; set; }
+        private string PrivateReadWrite { get; set; }
+        public string PublicReadPrivateWrite { get; private set; }
+        public string PrivateReadPublicWrite { private get; set; }
+        public string PublicReadOnly { get { return null; } }
+        private string PrivateReadOnly { get { return null; } }
+        public string PublicWriteOnly { set { } }
+        private string PrivateWriteOnly { set {  } }
+
+        [Test]
+        [TestCase("PublicReadWrite")]
+        [TestCase("PublicReadPrivateWrite")]
+        [TestCase("PublicReadOnly")]
+        public void GetGetMethod_Success(string name)
+        {
+            var propertyInfo = typeof(PropertyInfoExtensionsTest)
+                .GetProperty(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
+            Assert.IsNotNull(PropertyInfoExtensions.GetGetMethod(propertyInfo));
+        }
+
+        [Test]
+        [TestCase("PrivateReadWrite")]
+        [TestCase("PrivateReadPublicWrite")]
+        [TestCase("PrivateReadOnly")]
+        [TestCase("PublicWriteOnly")]
+        [TestCase("PrivateWriteOnly")]
+        public void GetGetMethod_NoAccessibleGetter(string name)
+        {
+            var propertyInfo = typeof(PropertyInfoExtensionsTest)
+                .GetProperty(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
+            Assert.IsNull(PropertyInfoExtensions.GetGetMethod(propertyInfo));
+        }
+
+        [Test]
+        [TestCase("PublicReadWrite")]
+        [TestCase("PrivateReadPublicWrite")]
+        [TestCase("PublicWriteOnly")]
+        public void GetSetMethod_Success(string name)
+        {
+            var propertyInfo = typeof(PropertyInfoExtensionsTest)
+                .GetProperty(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
+            Assert.IsNotNull(PropertyInfoExtensions.GetSetMethod(propertyInfo));
+        }
+
+        [Test]
+        [TestCase("PublicReadPrivateWrite")]
+        [TestCase("PrivateReadWrite")]
+        [TestCase("PrivateReadOnly")]
+        [TestCase("PublicReadOnly")]
+        [TestCase("PrivateWriteOnly")]
+        public void GetSetMethod_NoAccessibleGetter(string name)
+        {
+            var propertyInfo = typeof(PropertyInfoExtensionsTest)
+                .GetProperty(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
+            Assert.IsNull(PropertyInfoExtensions.GetSetMethod(propertyInfo));
+        }
+    }
+
+}

+ 133 - 0
csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs

@@ -0,0 +1,133 @@
+#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 NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace Google.Protobuf.Compatibility
+{
+    public class TypeExtensionsTest
+    {
+        public class DerivedList : List<string> { }
+        public string PublicProperty { get; set; }
+        private string PrivateProperty { get; set; }
+
+        public void PublicMethod()
+        {
+        }
+
+        private void PrivateMethod()
+        {
+        }
+
+        [Test]
+        [TestCase(typeof(int), true)]
+        [TestCase(typeof(int?), true)]
+        [TestCase(typeof(Nullable<>), true)]
+        [TestCase(typeof(WireFormat.WireType), true)]
+        [TestCase(typeof(string), false)]
+        [TestCase(typeof(object), false)]
+        [TestCase(typeof(Enum), false)]
+        [TestCase(typeof(ValueType), false)]
+        [TestCase(typeof(TypeExtensionsTest), false)]
+        [TestCase(typeof(Action), false)]
+        [TestCase(typeof(Action<>), false)]
+        [TestCase(typeof(IDisposable), false)]
+        public void IsValueType(Type type, bool expected)
+        {
+            Assert.AreEqual(expected, TypeExtensions.IsValueType(type));
+        }
+
+        [Test]
+        [TestCase(typeof(object), typeof(string), true)]
+        [TestCase(typeof(object), typeof(int), true)]
+        [TestCase(typeof(string), typeof(string), true)]
+        [TestCase(typeof(string), typeof(object), false)]
+        [TestCase(typeof(string), typeof(int), false)]
+        [TestCase(typeof(int), typeof(int), true)]
+        [TestCase(typeof(ValueType), typeof(int), true)]
+        [TestCase(typeof(long), typeof(int), false)] // 
+        public void IsAssignableFrom(Type target, Type argument, bool expected)
+        {
+            Assert.AreEqual(expected, TypeExtensions.IsAssignableFrom(target, argument));
+        }
+
+        [Test]
+        [TestCase(typeof(DerivedList), "Count")] // Go up the type hierarchy
+        [TestCase(typeof(List<string>), "Count")]
+        [TestCase(typeof(List<>), "Count")]
+        [TestCase(typeof(TypeExtensionsTest), "PublicProperty")]
+        public void GetProperty_Success(Type type, string name)
+        {
+            var property = TypeExtensions.GetProperty(type, name);
+            Assert.IsNotNull(property);
+            Assert.AreEqual(name, property.Name);
+        }
+
+        [Test]
+        [TestCase(typeof(TypeExtensionsTest), "PrivateProperty")]
+        [TestCase(typeof(TypeExtensionsTest), "Garbage")]
+        public void GetProperty_NoSuchProperty(Type type, string name)
+        {
+            var property = TypeExtensions.GetProperty(type, name);
+            Assert.IsNull(property);
+        }
+
+        [Test]
+        [TestCase(typeof(DerivedList), "RemoveAt")] // Go up the type hierarchy
+        [TestCase(typeof(List<>), "RemoveAt")]
+        [TestCase(typeof(TypeExtensionsTest), "PublicMethod")]
+        public void GetMethod_Success(Type type, string name)
+        {
+            var method = TypeExtensions.GetMethod(type, name);
+            Assert.IsNotNull(method);
+            Assert.AreEqual(name, method.Name);
+        }
+
+        [Test]
+        [TestCase(typeof(TypeExtensionsTest), "PrivateMethod")]
+        [TestCase(typeof(TypeExtensionsTest), "GarbageMethod")]
+        public void GetMethod_NoSuchMethod(Type type, string name)
+        {
+            var method = TypeExtensions.GetMethod(type, name);
+            Assert.IsNull(method);
+        }
+
+        [Test]
+        [TestCase(typeof(List<string>), "IndexOf")]
+        public void GetMethod_Ambiguous(Type type, string name)
+        {
+            Assert.Throws<AmbiguousMatchException>(() => TypeExtensions.GetMethod(type, name));
+        }
+    }
+}

+ 55 - 0
csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs

@@ -0,0 +1,55 @@
+#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.Reflection;
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+
+namespace Google.Protobuf
+{
+    public class DeprecatedMemberTest
+    {
+        private static void AssertIsDeprecated(MemberInfo member)
+        {
+            Assert.NotNull(member);
+            Assert.IsTrue(member.IsDefined(typeof(ObsoleteAttribute), false), "Member not obsolete: " + member);
+        }
+
+        [Test]
+        public void TestDepreatedPrimitiveValue()
+        {
+            AssertIsDeprecated(typeof(TestDeprecatedFields).GetProperty("DeprecatedInt32"));
+        }
+
+    }
+}

+ 64 - 0
csharp/src/Google.Protobuf.Test/EqualityTester.cs

@@ -0,0 +1,64 @@
+#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 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.IsTrue(first.Equals((object) 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));
+            Assert.IsFalse(first.Equals((object) second));
+            // While this isn't a requirement, the chances of this test failing due to
+            // coincidence rather than a bug are very small.
+            if (first != null && second != null)
+            {
+                Assert.AreNotEqual(first.GetHashCode(), second.GetHashCode());
+            }
+        }
+    }
+}

+ 195 - 0
csharp/src/Google.Protobuf.Test/FieldCodecTest.cs

@@ -0,0 +1,195 @@
+#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
+    {
+#pragma warning disable 0414 // Used by tests via reflection - do not remove!
+        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"),
+        };
+#pragma warning restore 0414
+
+        [Test, TestCaseSource("Codecs")]
+        public void RoundTripWithTag(ICodecTestData codec)
+        {
+            codec.TestRoundTripWithTag();
+        }
+
+        [Test, TestCaseSource("Codecs")]
+        public void RoundTripRaw(ICodecTestData codec)
+        {
+            codec.TestRoundTripRaw();
+        }
+
+        [Test, TestCaseSource("Codecs")]
+        public void CalculateSize(ICodecTestData codec)
+        {
+            codec.TestCalculateSizeWithTag();
+        }
+
+        [Test, TestCaseSource("Codecs")]
+        public void DefaultValue(ICodecTestData codec)
+        {
+            codec.TestDefaultValue();
+        }
+
+        [Test, TestCaseSource("Codecs")]
+        public void FixedSize(ICodecTestData codec)
+        {
+            codec.TestFixedSize();
+        }
+
+        // This is ugly, but it means we can have a non-generic interface.
+        // It feels like NUnit should support this better, but I don't know
+        // of any better ways right now.
+        public interface ICodecTestData
+        {
+            void TestRoundTripRaw();
+            void TestRoundTripWithTag();
+            void TestCalculateSizeWithTag();
+            void TestDefaultValue();
+            void TestFixedSize();
+        }
+
+        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 TestRoundTripRaw()
+            {
+                var stream = new MemoryStream();
+                var codedOutput = new CodedOutputStream(stream);
+                codec.ValueWriter(codedOutput, sampleValue);
+                codedOutput.Flush();
+                stream.Position = 0;
+                var codedInput = new CodedInputStream(stream);
+                Assert.AreEqual(sampleValue, codec.ValueReader(codedInput));
+                Assert.IsTrue(codedInput.IsAtEnd);
+            }
+
+            public void TestRoundTripWithTag()
+            {
+                var stream = new MemoryStream();
+                var codedOutput = new CodedOutputStream(stream);
+                codec.WriteTagAndValue(codedOutput, sampleValue);
+                codedOutput.Flush();
+                stream.Position = 0;
+                var codedInput = new CodedInputStream(stream);
+                codedInput.AssertNextTag(codec.Tag);
+                Assert.AreEqual(sampleValue, codec.Read(codedInput));
+                Assert.IsTrue(codedInput.IsAtEnd);
+            }
+
+            public void TestCalculateSizeWithTag()
+            {
+                var stream = new MemoryStream();
+                var codedOutput = new CodedOutputStream(stream);
+                codec.WriteTagAndValue(codedOutput, sampleValue);
+                codedOutput.Flush();
+                Assert.AreEqual(stream.Position, codec.CalculateSizeWithTag(sampleValue));
+            }
+
+            public void TestDefaultValue()
+            {
+                // WriteTagAndValue ignores default values
+                var stream = new MemoryStream();
+                var codedOutput = new CodedOutputStream(stream);
+                codec.WriteTagAndValue(codedOutput, codec.DefaultValue);
+                codedOutput.Flush();
+                Assert.AreEqual(0, stream.Position);
+                Assert.AreEqual(0, codec.CalculateSizeWithTag(codec.DefaultValue));
+                if (typeof(T).IsValueType)
+                {
+                    Assert.AreEqual(default(T), codec.DefaultValue);
+                }
+
+                // The plain ValueWriter/ValueReader delegates don't.
+                if (codec.DefaultValue != null) // This part isn't appropriate for message types.
+                {
+                    codedOutput = new CodedOutputStream(stream);
+                    codec.ValueWriter(codedOutput, codec.DefaultValue);
+                    codedOutput.Flush();
+                    Assert.AreNotEqual(0, stream.Position);
+                    Assert.AreEqual(stream.Position, codec.ValueSizeCalculator(codec.DefaultValue));
+                    stream.Position = 0;
+                    var codedInput = new CodedInputStream(stream);
+                    Assert.AreEqual(codec.DefaultValue, codec.ValueReader(codedInput));
+                }
+            }
+
+            public void TestFixedSize()
+            {
+                Assert.AreEqual(name.Contains("Fixed"), codec.FixedSize != 0);
+            }
+
+            public override string ToString()
+            {
+                return name;
+            }
+        }
+    }
+}

+ 655 - 0
csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs

@@ -0,0 +1,655 @@
+#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.IO;
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using Google.Protobuf.WellKnownTypes;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Tests around the generated TestAllTypes message.
+    /// </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()
+        {
+            // Single fields
+            var message = new TestAllTypes();
+            Assert.AreEqual(false, message.SingleBool);
+            Assert.AreEqual(ByteString.Empty, message.SingleBytes);
+            Assert.AreEqual(0.0, message.SingleDouble);
+            Assert.AreEqual(0, message.SingleFixed32);
+            Assert.AreEqual(0L, message.SingleFixed64);
+            Assert.AreEqual(0.0f, message.SingleFloat);
+            Assert.AreEqual(ForeignEnum.FOREIGN_UNSPECIFIED, message.SingleForeignEnum);
+            Assert.IsNull(message.SingleForeignMessage);
+            Assert.AreEqual(ImportEnum.IMPORT_ENUM_UNSPECIFIED, message.SingleImportEnum);
+            Assert.IsNull(message.SingleImportMessage);
+            Assert.AreEqual(0, message.SingleInt32);
+            Assert.AreEqual(0L, message.SingleInt64);
+            Assert.AreEqual(TestAllTypes.Types.NestedEnum.NESTED_ENUM_UNSPECIFIED, message.SingleNestedEnum);
+            Assert.IsNull(message.SingleNestedMessage);
+            Assert.IsNull(message.SinglePublicImportMessage);
+            Assert.AreEqual(0, message.SingleSfixed32);
+            Assert.AreEqual(0L, message.SingleSfixed64);
+            Assert.AreEqual(0, message.SingleSint32);
+            Assert.AreEqual(0L, message.SingleSint64);
+            Assert.AreEqual("", message.SingleString);
+            Assert.AreEqual(0U, message.SingleUint32);
+            Assert.AreEqual(0UL, message.SingleUint64);
+
+            // Repeated fields
+            Assert.AreEqual(0, message.RepeatedBool.Count);
+            Assert.AreEqual(0, message.RepeatedBytes.Count);
+            Assert.AreEqual(0, message.RepeatedDouble.Count);
+            Assert.AreEqual(0, message.RepeatedFixed32.Count);
+            Assert.AreEqual(0, message.RepeatedFixed64.Count);
+            Assert.AreEqual(0, message.RepeatedFloat.Count);
+            Assert.AreEqual(0, message.RepeatedForeignEnum.Count);
+            Assert.AreEqual(0, message.RepeatedForeignMessage.Count);
+            Assert.AreEqual(0, message.RepeatedImportEnum.Count);
+            Assert.AreEqual(0, message.RepeatedImportMessage.Count);
+            Assert.AreEqual(0, message.RepeatedNestedEnum.Count);
+            Assert.AreEqual(0, message.RepeatedNestedMessage.Count);
+            Assert.AreEqual(0, message.RepeatedPublicImportMessage.Count);
+            Assert.AreEqual(0, message.RepeatedSfixed32.Count);
+            Assert.AreEqual(0, message.RepeatedSfixed64.Count);
+            Assert.AreEqual(0, message.RepeatedSint32.Count);
+            Assert.AreEqual(0, message.RepeatedSint64.Count);
+            Assert.AreEqual(0, message.RepeatedString.Count);
+            Assert.AreEqual(0, message.RepeatedUint32.Count);
+            Assert.AreEqual(0, message.RepeatedUint64.Count);
+
+            // Oneof fields
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
+            Assert.AreEqual(0, message.OneofUint32);
+            Assert.AreEqual("", message.OneofString);
+            Assert.AreEqual(ByteString.Empty, message.OneofBytes);
+            Assert.IsNull(message.OneofNestedMessage);
+        }
+
+        [Test]
+        public void NullStringAndBytesRejected()
+        {
+            var message = new TestAllTypes();
+            Assert.Throws<ArgumentNullException>(() => message.SingleString = null);
+            Assert.Throws<ArgumentNullException>(() => message.OneofString = null);
+            Assert.Throws<ArgumentNullException>(() => message.SingleBytes = null);
+            Assert.Throws<ArgumentNullException>(() => message.OneofBytes = null);
+        }
+
+        [Test]
+        public void RoundTrip_Empty()
+        {
+            var message = new TestAllTypes();
+            // Without setting any values, there's nothing to write.
+            byte[] bytes = message.ToByteArray();
+            Assert.AreEqual(0, bytes.Length);
+            TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes);
+            Assert.AreEqual(message, parsed);
+        }
+
+        [Test]
+        public void RoundTrip_SingleValues()
+        {
+            var message = new TestAllTypes
+            {
+                SingleBool = true,
+                SingleBytes = ByteString.CopyFrom(1, 2, 3, 4),
+                SingleDouble = 23.5,
+                SingleFixed32 = 23,
+                SingleFixed64 = 1234567890123,
+                SingleFloat = 12.25f,
+                SingleForeignEnum = ForeignEnum.FOREIGN_BAR,
+                SingleForeignMessage = new ForeignMessage { C = 10 },
+                SingleImportEnum = ImportEnum.IMPORT_BAZ,
+                SingleImportMessage = new ImportMessage { D = 20 },
+                SingleInt32 = 100,
+                SingleInt64 = 3210987654321,
+                SingleNestedEnum = TestAllTypes.Types.NestedEnum.FOO,
+                SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 35 },
+                SinglePublicImportMessage = new PublicImportMessage { E = 54 },
+                SingleSfixed32 = -123,
+                SingleSfixed64 = -12345678901234,
+                SingleSint32 = -456,
+                SingleSint64 = -12345678901235,
+                SingleString = "test",
+                SingleUint32 = uint.MaxValue,
+                SingleUint64 = ulong.MaxValue
+            };
+
+            byte[] bytes = message.ToByteArray();
+            TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes);
+            Assert.AreEqual(message, parsed);
+        }
+
+        [Test]
+        public void RoundTrip_RepeatedValues()
+        {
+            var message = new TestAllTypes
+            {
+                RepeatedBool = { true, false },
+                RepeatedBytes = { ByteString.CopyFrom(1, 2, 3, 4), ByteString.CopyFrom(5, 6) },
+                RepeatedDouble = { -12.25, 23.5 },
+                RepeatedFixed32 = { uint.MaxValue, 23 },
+                RepeatedFixed64 = { ulong.MaxValue, 1234567890123 },
+                RepeatedFloat = { 100f, 12.25f },
+                RepeatedForeignEnum = { ForeignEnum.FOREIGN_FOO, ForeignEnum.FOREIGN_BAR },
+                RepeatedForeignMessage = { new ForeignMessage(), new ForeignMessage { C = 10 } },
+                RepeatedImportEnum = { ImportEnum.IMPORT_BAZ, ImportEnum.IMPORT_ENUM_UNSPECIFIED },
+                RepeatedImportMessage = { new ImportMessage { D = 20 }, new ImportMessage { D = 25 } },
+                RepeatedInt32 = { 100, 200 },
+                RepeatedInt64 = { 3210987654321, long.MaxValue },
+                RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.FOO, TestAllTypes.Types.NestedEnum.NEG },
+                RepeatedNestedMessage = { new TestAllTypes.Types.NestedMessage { Bb = 35 }, new TestAllTypes.Types.NestedMessage { Bb = 10 } },
+                RepeatedPublicImportMessage = { new PublicImportMessage { E = 54 }, new PublicImportMessage { E = -1 } },
+                RepeatedSfixed32 = { -123, 123 },
+                RepeatedSfixed64 = { -12345678901234, 12345678901234 },
+                RepeatedSint32 = { -456, 100 },
+                RepeatedSint64 = { -12345678901235, 123 },
+                RepeatedString = { "foo", "bar" },
+                RepeatedUint32 = { uint.MaxValue, uint.MinValue },
+                RepeatedUint64 = { ulong.MaxValue, uint.MinValue }
+            };
+
+            byte[] bytes = message.ToByteArray();
+            TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes);
+            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 = new CodedOutputStream(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.WriteLength(2 + nestedMessage.CalculateSize());
+            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 = new CodedOutputStream(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.WriteLength(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 = new CodedOutputStream(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.WriteLength(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 = new CodedOutputStream(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.WriteLength(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.WriteLength(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.WriteLength(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 = new CodedOutputStream(memoryStream);
+
+            var key = 10;
+            var value1 = 20;
+            var value2 = 30;
+
+            // First entry
+            output.WriteTag(TestMap.MapInt32Int32FieldNumber, WireFormat.WireType.LengthDelimited);
+            output.WriteLength(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.WriteLength(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()
+        {
+            var original = new TestAllTypes
+            {
+                SingleBool = true,
+                SingleBytes = ByteString.CopyFrom(1, 2, 3, 4),
+                SingleDouble = 23.5,
+                SingleFixed32 = 23,
+                SingleFixed64 = 1234567890123,
+                SingleFloat = 12.25f,
+                SingleInt32 = 100,
+                SingleInt64 = 3210987654321,
+                SingleNestedEnum = TestAllTypes.Types.NestedEnum.FOO,
+                SingleSfixed32 = -123,
+                SingleSfixed64 = -12345678901234,
+                SingleSint32 = -456,
+                SingleSint64 = -12345678901235,
+                SingleString = "test",
+                SingleUint32 = uint.MaxValue,
+                SingleUint64 = ulong.MaxValue
+            };
+            var clone = original.Clone();
+            Assert.AreNotSame(original, clone);
+            Assert.AreEqual(original, clone);
+            // Just as a single example
+            clone.SingleInt32 = 150;
+            Assert.AreNotEqual(original, clone);
+        }
+
+        [Test]
+        public void CloneRepeatedNonMessageValues()
+        {
+            var original = new TestAllTypes
+            {
+                RepeatedBool = { true, false },
+                RepeatedBytes = { ByteString.CopyFrom(1, 2, 3, 4), ByteString.CopyFrom(5, 6) },
+                RepeatedDouble = { -12.25, 23.5 },
+                RepeatedFixed32 = { uint.MaxValue, 23 },
+                RepeatedFixed64 = { ulong.MaxValue, 1234567890123 },
+                RepeatedFloat = { 100f, 12.25f },
+                RepeatedInt32 = { 100, 200 },
+                RepeatedInt64 = { 3210987654321, long.MaxValue },
+                RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.FOO, TestAllTypes.Types.NestedEnum.NEG },
+                RepeatedSfixed32 = { -123, 123 },
+                RepeatedSfixed64 = { -12345678901234, 12345678901234 },
+                RepeatedSint32 = { -456, 100 },
+                RepeatedSint64 = { -12345678901235, 123 },
+                RepeatedString = { "foo", "bar" },
+                RepeatedUint32 = { uint.MaxValue, uint.MinValue },
+                RepeatedUint64 = { ulong.MaxValue, uint.MinValue }
+            };
+
+            var clone = original.Clone();
+            Assert.AreNotSame(original, clone);
+            Assert.AreEqual(original, clone);
+            // Just as a single example
+            clone.RepeatedDouble.Add(25.5);
+            Assert.AreNotEqual(original, clone);
+        }
+
+        [Test]
+        public void CloneSingleMessageField()
+        {
+            var original = new TestAllTypes
+            {
+                SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 }
+            };
+
+            var clone = original.Clone();
+            Assert.AreNotSame(original, clone);
+            Assert.AreNotSame(original.SingleNestedMessage, clone.SingleNestedMessage);
+            Assert.AreEqual(original, clone);
+
+            clone.SingleNestedMessage.Bb = 30;
+            Assert.AreNotEqual(original, clone);
+        }
+
+        [Test]
+        public void CloneRepeatedMessageField()
+        {
+            var original = new TestAllTypes
+            {
+                RepeatedNestedMessage = { new TestAllTypes.Types.NestedMessage { Bb = 20 } }
+            };
+
+            var clone = original.Clone();
+            Assert.AreNotSame(original, clone);
+            Assert.AreNotSame(original.RepeatedNestedMessage, clone.RepeatedNestedMessage);
+            Assert.AreNotSame(original.RepeatedNestedMessage[0], clone.RepeatedNestedMessage[0]);
+            Assert.AreEqual(original, clone);
+
+            clone.RepeatedNestedMessage[0].Bb = 30;
+            Assert.AreNotEqual(original, clone);
+        }
+
+        [Test]
+        public void CloneOneofField()
+        {
+            var original = new TestAllTypes
+            {
+                OneofNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 }
+            };
+
+            var clone = original.Clone();
+            Assert.AreNotSame(original, clone);
+            Assert.AreEqual(original, clone);
+
+            // We should have cloned the message
+            original.OneofNestedMessage.Bb = 30;
+            Assert.AreNotEqual(original, clone);
+        }
+
+        [Test]
+        public void OneofProperties()
+        {
+            // Switch the oneof case between each of the different options, and check everything behaves
+            // as expected in each case.
+            var message = new TestAllTypes();
+            Assert.AreEqual("", message.OneofString);
+            Assert.AreEqual(0, message.OneofUint32);
+            Assert.AreEqual(ByteString.Empty, message.OneofBytes);
+            Assert.IsNull(message.OneofNestedMessage);
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
+
+            message.OneofString = "sample";
+            Assert.AreEqual("sample", message.OneofString);
+            Assert.AreEqual(0, message.OneofUint32);
+            Assert.AreEqual(ByteString.Empty, message.OneofBytes);
+            Assert.IsNull(message.OneofNestedMessage);
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase);
+
+            var bytes = ByteString.CopyFrom(1, 2, 3);
+            message.OneofBytes = bytes;
+            Assert.AreEqual("", message.OneofString);
+            Assert.AreEqual(0, message.OneofUint32);
+            Assert.AreEqual(bytes, message.OneofBytes);
+            Assert.IsNull(message.OneofNestedMessage);
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofBytes, message.OneofFieldCase);
+
+            message.OneofUint32 = 20;
+            Assert.AreEqual("", message.OneofString);
+            Assert.AreEqual(20, message.OneofUint32);
+            Assert.AreEqual(ByteString.Empty, message.OneofBytes);
+            Assert.IsNull(message.OneofNestedMessage);
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message.OneofFieldCase);
+
+            var nestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 25 };
+            message.OneofNestedMessage = nestedMessage;
+            Assert.AreEqual("", message.OneofString);
+            Assert.AreEqual(0, message.OneofUint32);
+            Assert.AreEqual(ByteString.Empty, message.OneofBytes);
+            Assert.AreEqual(nestedMessage, message.OneofNestedMessage);
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofNestedMessage, message.OneofFieldCase);
+
+            message.ClearOneofField();
+            Assert.AreEqual("", message.OneofString);
+            Assert.AreEqual(0, message.OneofUint32);
+            Assert.AreEqual(ByteString.Empty, message.OneofBytes);
+            Assert.IsNull(message.OneofNestedMessage);
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
+        }
+
+        [Test]
+        public void OneofSerialization_NonDefaultValue()
+        {
+            var message = new TestAllTypes();
+            message.OneofString = "this would take a bit of space";
+            message.OneofUint32 = 10;
+            var bytes = message.ToByteArray();
+            Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - no string!
+
+            var message2 = TestAllTypes.Parser.ParseFrom(bytes);
+            Assert.AreEqual(message, message2);
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase);
+        }
+
+        [Test]
+        public void OneofSerialization_DefaultValue()
+        {
+            var message = new TestAllTypes();
+            message.OneofString = "this would take a bit of space";
+            message.OneofUint32 = 0; // This is the default value for UInt32; normally wouldn't be serialized
+            var bytes = message.ToByteArray();
+            Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - it's still serialized
+
+            var message2 = TestAllTypes.Parser.ParseFrom(bytes);
+            Assert.AreEqual(message, message2);
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase);
+        }
+
+        [Test]
+        public void IgnoreUnknownFields_RealDataStillRead()
+        {
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            var unusedFieldNumber = 23456;
+            Assert.IsFalse(TestAllTypes.Descriptor.Fields.InDeclarationOrder().Select(x => x.FieldNumber).Contains(unusedFieldNumber));
+            output.WriteTag(unusedFieldNumber, WireFormat.WireType.LengthDelimited);
+            output.WriteString("ignore me");
+            message.WriteTo(output);
+            output.Flush();
+
+            stream.Position = 0;
+            var parsed = TestAllTypes.Parser.ParseFrom(stream);
+            Assert.AreEqual(message, parsed);
+        }
+
+        [Test]
+        public void IgnoreUnknownFields_AllTypes()
+        {
+            // Simple way of ensuring we can skip all kinds of fields.
+            var data = SampleMessages.CreateFullTestAllTypes().ToByteArray();
+            var empty = Empty.Parser.ParseFrom(data);
+            Assert.AreEqual(new Empty(), empty);
+        }
+
+        // This was originally seen as a conformance test failure.
+        [Test]
+        public void TruncatedMessageFieldThrows()
+        {
+            // 130, 3 is the message tag
+            // 1 is the data length - but there's no data.
+            var data = new byte[] { 130, 3, 1 };            
+            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseFrom(data));
+        }
+
+        /// <summary>
+        /// Demonstrates current behaviour with an extraneous end group tag - see issue 688
+        /// for details; we may want to change this.
+        /// </summary>
+        [Test]
+        public void ExtraEndGroupSkipped()
+        {
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+
+            output.WriteTag(100, WireFormat.WireType.EndGroup);
+            output.WriteTag(TestAllTypes.SingleFixed32FieldNumber, WireFormat.WireType.Fixed32);
+            output.WriteFixed32(123);
+
+            output.Flush();
+
+            stream.Position = 0;
+            var parsed = TestAllTypes.Parser.ParseFrom(stream);
+            Assert.AreEqual(new TestAllTypes { SingleFixed32 = 123 }, parsed);
+        }
+    }
+}

+ 137 - 0
csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj

@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{DD01ED24-3750-4567-9A23-1DB676A15610}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Google.Protobuf</RootNamespace>
+    <AssemblyName>Google.Protobuf.Test</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <OldToolsVersion>3.5</OldToolsVersion>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+    <NuGetPackageImportStamp>
+    </NuGetPackageImportStamp>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <IntermediateOutputPath>obj\Debug\</IntermediateOutputPath>
+    <DefineConstants>DEBUG;TRACE;$(EnvironmentFlavor);$(EnvironmentTemplate)</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <NoStdLib>true</NoStdLib>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <IntermediateOutputPath>obj\Release\</IntermediateOutputPath>
+    <DefineConstants>TRACE;$(EnvironmentFlavor);$(EnvironmentTemplate)</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <NoStdLib>true</NoStdLib>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\ReleaseSigned</OutputPath>
+    <IntermediateOutputPath>obj\ReleaseSigned\</IntermediateOutputPath>
+    <DefineConstants>TRACE;$(EnvironmentFlavor);$(EnvironmentTemplate)</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <NoStdLib>true</NoStdLib>
+    <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <Prefer32Bit>false</Prefer32Bit>
+    <SignAssembly>True</SignAssembly>
+    <AssemblyOriginatorKeyFile>C:\keys\Google.Protobuf.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="mscorlib" />
+    <Reference Include="nunit.core, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+      <HintPath>..\packages\NUnitTestAdapter.2.0.0\lib\nunit.core.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="nunit.core.interfaces, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+      <HintPath>..\packages\NUnitTestAdapter.2.0.0\lib\nunit.core.interfaces.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+      <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="nunit.util, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+      <HintPath>..\packages\NUnitTestAdapter.2.0.0\lib\nunit.util.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="NUnit.VisualStudio.TestAdapter, Version=2.0.0.0, Culture=neutral, PublicKeyToken=4cb40d35494691ac, processorArchitecture=MSIL">
+      <HintPath>..\packages\NUnitTestAdapter.2.0.0\lib\NUnit.VisualStudio.TestAdapter.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ByteStringTest.cs" />
+    <Compile Include="CodedInputStreamExtensions.cs" />
+    <Compile Include="CodedInputStreamTest.cs" />
+    <Compile Include="CodedOutputStreamTest.cs" />
+    <Compile Include="Compatibility\PropertyInfoExtensionsTest.cs" />
+    <Compile Include="Compatibility\TypeExtensionsTest.cs" />
+    <Compile Include="EqualityTester.cs" />
+    <Compile Include="FieldCodecTest.cs" />
+    <Compile Include="GeneratedMessageTest.cs" />
+    <Compile Include="Collections\MapFieldTest.cs" />
+    <Compile Include="Collections\RepeatedFieldTest.cs" />
+    <Compile Include="JsonFormatterTest.cs" />
+    <Compile Include="Reflection\DescriptorsTest.cs" />
+    <Compile Include="Reflection\FieldAccessTest.cs" />
+    <Compile Include="SampleEnum.cs" />
+    <Compile Include="SampleMessages.cs" />
+    <Compile Include="TestProtos\MapUnittestProto3.cs" />
+    <Compile Include="TestProtos\UnittestImportProto3.cs" />
+    <Compile Include="TestProtos\UnittestImportPublicProto3.cs" />
+    <Compile Include="TestProtos\UnittestIssues.cs" />
+    <Compile Include="TestProtos\UnittestProto3.cs" />
+    <Compile Include="DeprecatedMemberTest.cs" />
+    <Compile Include="IssuesTest.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="TestCornerCases.cs" />
+    <Compile Include="TestProtos\UnittestWellKnownTypes.cs" />
+    <Compile Include="WellKnownTypes\DurationTest.cs" />
+    <Compile Include="WellKnownTypes\TimestampTest.cs" />
+    <Compile Include="WellKnownTypes\WrappersTest.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Google.Protobuf\Google.Protobuf.csproj">
+      <Project>{6908BDCE-D925-43F3-94AC-A531E6DF2591}</Project>
+      <Name>Google.Protobuf</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </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.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

+ 63 - 0
csharp/src/Google.Protobuf.Test/IssuesTest.cs

@@ -0,0 +1,63 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using Google.Protobuf.Reflection;
+using UnitTest.Issues.TestProtos;
+using NUnit.Framework;
+
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Tests for issues which aren't easily compartmentalized into other unit tests.
+    /// </summary>
+    public class IssuesTest
+    {
+        // Issue 45
+        [Test]
+        public void FieldCalledItem()
+        {
+            ItemField message = new ItemField { Item = 3 };
+            FieldDescriptor field = ItemField.Descriptor.FindFieldByName("item");
+            Assert.NotNull(field);
+            Assert.AreEqual(3, (int)field.Accessor.GetValue(message));
+        }
+
+        [Test]
+        public void ReservedNames()
+        {
+            var message = new ReservedNames { Types_ = 10, Descriptor_ = 20 };
+            // Underscores aren't reflected in the JSON.
+            Assert.AreEqual("{ \"types\": 10, \"descriptor\": 20 }", message.ToString());
+        }
+    }
+}

+ 420 - 0
csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs

@@ -0,0 +1,420 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+using UnitTest.Issues.TestProtos;
+using Google.Protobuf.WellKnownTypes;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Tests for the JSON formatter. Note that in these tests, double quotes are replaced with apostrophes
+    /// for the sake of readability (embedding \" everywhere is painful). See the AssertJson method for details.
+    /// </summary>
+    public class JsonFormatterTest
+    {
+        [Test]
+        public void DefaultValues_WhenOmitted()
+        {
+            var formatter = new JsonFormatter(new JsonFormatter.Settings(formatDefaultValues: false));
+
+            AssertJson("{ }", formatter.Format(new ForeignMessage()));
+            AssertJson("{ }", formatter.Format(new TestAllTypes()));
+            AssertJson("{ }", formatter.Format(new TestMap()));
+        }
+
+        [Test]
+        public void DefaultValues_WhenIncluded()
+        {
+            var formatter = new JsonFormatter(new JsonFormatter.Settings(formatDefaultValues: true));
+            AssertJson("{ 'c': 0 }", formatter.Format(new ForeignMessage()));
+        }
+
+        [Test]
+        public void AllSingleFields()
+        {
+            var message = new TestAllTypes
+            {
+                SingleBool = true,
+                SingleBytes = ByteString.CopyFrom(1, 2, 3, 4),
+                SingleDouble = 23.5,
+                SingleFixed32 = 23,
+                SingleFixed64 = 1234567890123,
+                SingleFloat = 12.25f,
+                SingleForeignEnum = ForeignEnum.FOREIGN_BAR,
+                SingleForeignMessage = new ForeignMessage { C = 10 },
+                SingleImportEnum = ImportEnum.IMPORT_BAZ,
+                SingleImportMessage = new ImportMessage { D = 20 },
+                SingleInt32 = 100,
+                SingleInt64 = 3210987654321,
+                SingleNestedEnum = TestAllTypes.Types.NestedEnum.FOO,
+                SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 35 },
+                SinglePublicImportMessage = new PublicImportMessage { E = 54 },
+                SingleSfixed32 = -123,
+                SingleSfixed64 = -12345678901234,
+                SingleSint32 = -456,
+                SingleSint64 = -12345678901235,
+                SingleString = "test\twith\ttabs",
+                SingleUint32 = uint.MaxValue,
+                SingleUint64 = ulong.MaxValue,
+            };
+            var actualText = JsonFormatter.Default.Format(message);
+
+            // Fields in numeric order
+            var expectedText = "{ " +
+                "'singleInt32': 100, " +
+                "'singleInt64': '3210987654321', " +
+                "'singleUint32': 4294967295, " +
+                "'singleUint64': '18446744073709551615', " +
+                "'singleSint32': -456, " +
+                "'singleSint64': '-12345678901235', " +
+                "'singleFixed32': 23, " +
+                "'singleFixed64': '1234567890123', " +
+                "'singleSfixed32': -123, " +
+                "'singleSfixed64': '-12345678901234', " +
+                "'singleFloat': 12.25, " +
+                "'singleDouble': 23.5, " +
+                "'singleBool': true, " +
+                "'singleString': 'test\\twith\\ttabs', " +
+                "'singleBytes': 'AQIDBA==', " +
+                "'singleNestedMessage': { 'bb': 35 }, " +
+                "'singleForeignMessage': { 'c': 10 }, " +
+                "'singleImportMessage': { 'd': 20 }, " +
+                "'singleNestedEnum': 'FOO', " +
+                "'singleForeignEnum': 'FOREIGN_BAR', " +
+                "'singleImportEnum': 'IMPORT_BAZ', " +
+                "'singlePublicImportMessage': { 'e': 54 }" +
+                " }";
+            AssertJson(expectedText, actualText);
+        }
+
+        [Test]
+        public void RepeatedField()
+        {
+            AssertJson("{ 'repeatedInt32': [ 1, 2, 3, 4, 5 ] }",
+                JsonFormatter.Default.Format(new TestAllTypes { RepeatedInt32 = { 1, 2, 3, 4, 5 } }));
+        }
+
+        [Test]
+        public void MapField_StringString()
+        {
+            AssertJson("{ 'mapStringString': { 'with spaces': 'bar', 'a': 'b' } }",
+                JsonFormatter.Default.Format(new TestMap { MapStringString = { { "with spaces", "bar" }, { "a", "b" } } }));
+        }
+
+        [Test]
+        public void MapField_Int32Int32()
+        {
+            // The keys are quoted, but the values aren't.
+            AssertJson("{ 'mapInt32Int32': { '0': 1, '2': 3 } }",
+                JsonFormatter.Default.Format(new TestMap { MapInt32Int32 = { { 0, 1 }, { 2, 3 } } }));
+        }
+
+        [Test]
+        public void MapField_BoolBool()
+        {
+            // The keys are quoted, but the values aren't.
+            AssertJson("{ 'mapBoolBool': { 'false': true, 'true': false } }",
+                JsonFormatter.Default.Format(new TestMap { MapBoolBool = { { false, true }, { true, false } } }));
+        }
+
+        [TestCase(1.0, "1")]
+        [TestCase(double.NaN, "'NaN'")]
+        [TestCase(double.PositiveInfinity, "'Infinity'")]
+        [TestCase(double.NegativeInfinity, "'-Infinity'")]
+        public void DoubleRepresentations(double value, string expectedValueText)
+        {
+            var message = new TestAllTypes { SingleDouble = value };
+            string actualText = JsonFormatter.Default.Format(message);
+            string expectedText = "{ 'singleDouble': " + expectedValueText + " }";
+            AssertJson(expectedText, actualText);
+        }
+
+        [Test]
+        public void UnknownEnumValueOmitted_SingleField()
+        {
+            var message = new TestAllTypes { SingleForeignEnum = (ForeignEnum) 100 };
+            AssertJson("{ }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        public void UnknownEnumValueOmitted_RepeatedField()
+        {
+            var message = new TestAllTypes { RepeatedForeignEnum = { ForeignEnum.FOREIGN_BAZ, (ForeignEnum) 100, ForeignEnum.FOREIGN_FOO } };
+            AssertJson("{ 'repeatedForeignEnum': [ 'FOREIGN_BAZ', 'FOREIGN_FOO' ] }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        public void UnknownEnumValueOmitted_MapField()
+        {
+            // This matches the C++ behaviour.
+            var message = new TestMap { MapInt32Enum = { { 1, MapEnum.MAP_ENUM_FOO }, { 2, (MapEnum) 100 }, { 3, MapEnum.MAP_ENUM_BAR } } };
+            AssertJson("{ 'mapInt32Enum': { '1': 'MAP_ENUM_FOO', '3': 'MAP_ENUM_BAR' } }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        public void UnknownEnumValueOmitted_RepeatedField_AllEntriesUnknown()
+        {
+            // *Maybe* we should hold off on writing the "[" until we find that we've got at least one value to write...
+            // but this is what happens at the moment, and it doesn't seem too awful.
+            var message = new TestAllTypes { RepeatedForeignEnum = { (ForeignEnum) 200, (ForeignEnum) 100 } };
+            AssertJson("{ 'repeatedForeignEnum': [ ] }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        public void NullValueForMessage()
+        {
+            var message = new TestMap { MapInt32ForeignMessage = { { 10, null } } };
+            AssertJson("{ 'mapInt32ForeignMessage': { '10': null } }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        [TestCase("a\u17b4b", "a\\u17b4b")] // Explicit
+        [TestCase("a\u0601b", "a\\u0601b")] // Ranged
+        [TestCase("a\u0605b", "a\u0605b")] // Passthrough (note lack of double backslash...)
+        public void SimpleNonAscii(string text, string encoded)
+        {
+            var message = new TestAllTypes { SingleString = text };
+            AssertJson("{ 'singleString': '" + encoded + "' }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        public void SurrogatePairEscaping()
+        {
+            var message = new TestAllTypes { SingleString = "a\uD801\uDC01b" };
+            AssertJson("{ 'singleString': 'a\\ud801\\udc01b' }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        public void InvalidSurrogatePairsFail()
+        {
+            // Note: don't use TestCase for these, as the strings can't be reliably represented 
+            // See http://codeblog.jonskeet.uk/2014/11/07/when-is-a-string-not-a-string/
+
+            // Lone low surrogate
+            var message = new TestAllTypes { SingleString = "a\uDC01b" };
+            Assert.Throws<ArgumentException>(() => JsonFormatter.Default.Format(message));
+
+            // Lone high surrogate
+            message = new TestAllTypes { SingleString = "a\uD801b" };
+            Assert.Throws<ArgumentException>(() => JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        [TestCase("foo_bar", "fooBar")]
+        [TestCase("bananaBanana", "bananaBanana")]
+        [TestCase("BANANABanana", "bananaBanana")]
+        public void ToCamelCase(string original, string expected)
+        {
+            Assert.AreEqual(expected, JsonFormatter.ToCamelCase(original));
+        }
+
+        [Test]
+        [TestCase(null, "{ }")]
+        [TestCase("x", "{ 'fooString': 'x' }")]
+        [TestCase("", "{ 'fooString': '' }")]
+        [TestCase(null, "{ }")]
+        public void Oneof(string fooStringValue, string expectedJson)
+        {
+            var message = new TestOneof();
+            if (fooStringValue != null)
+            {
+                message.FooString = fooStringValue;
+            }
+
+            // We should get the same result both with and without "format default values".
+            var formatter = new JsonFormatter(new JsonFormatter.Settings(false));
+            AssertJson(expectedJson, formatter.Format(message));
+            formatter = new JsonFormatter(new JsonFormatter.Settings(true));
+            AssertJson(expectedJson, formatter.Format(message));
+        }
+
+        [Test]
+        public void WrapperFormatting_Single()
+        {
+            // Just a few examples, handling both classes and value types, and
+            // default vs non-default values
+            var message = new TestWellKnownTypes
+            {
+                Int64Field = 10,
+                Int32Field = 0,
+                BytesField = ByteString.FromBase64("ABCD"),
+                StringField = ""
+            };
+            var expectedJson = "{ 'int64Field': '10', 'int32Field': 0, 'stringField': '', 'bytesField': 'ABCD' }";
+            AssertJson(expectedJson, JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        public void WrapperFormatting_IncludeNull()
+        {
+            // The actual JSON here is very large because there are lots of fields. Just test a couple of them.
+            var message = new TestWellKnownTypes { Int32Field = 10 };
+            var formatter = new JsonFormatter(new JsonFormatter.Settings(true));
+            var actualJson = formatter.Format(message);
+            Assert.IsTrue(actualJson.Contains("\"int64Field\": null"));
+            Assert.IsFalse(actualJson.Contains("\"int32Field\": null"));
+        }
+
+        [Test]
+        public void OutputIsInNumericFieldOrder_NoDefaults()
+        {
+            var formatter = new JsonFormatter(new JsonFormatter.Settings(false));
+            var message = new TestJsonFieldOrdering { PlainString = "p1", PlainInt32 = 2 };
+            AssertJson("{ 'plainString': 'p1', 'plainInt32': 2 }", formatter.Format(message));
+            message = new TestJsonFieldOrdering { O1Int32 = 5, O2String = "o2", PlainInt32 = 10, PlainString = "plain" };
+            AssertJson("{ 'plainString': 'plain', 'o2String': 'o2', 'plainInt32': 10, 'o1Int32': 5 }", formatter.Format(message));
+            message = new TestJsonFieldOrdering { O1String = "", O2Int32 = 0, PlainInt32 = 10, PlainString = "plain" };
+            AssertJson("{ 'plainString': 'plain', 'o1String': '', 'plainInt32': 10, 'o2Int32': 0 }", formatter.Format(message));
+        }
+
+        [Test]
+        public void OutputIsInNumericFieldOrder_WithDefaults()
+        {
+            var formatter = new JsonFormatter(new JsonFormatter.Settings(true));
+            var message = new TestJsonFieldOrdering();
+            AssertJson("{ 'plainString': '', 'plainInt32': 0 }", formatter.Format(message));
+            message = new TestJsonFieldOrdering { O1Int32 = 5, O2String = "o2", PlainInt32 = 10, PlainString = "plain" };
+            AssertJson("{ 'plainString': 'plain', 'o2String': 'o2', 'plainInt32': 10, 'o1Int32': 5 }", formatter.Format(message));
+            message = new TestJsonFieldOrdering { O1String = "", O2Int32 = 0, PlainInt32 = 10, PlainString = "plain" };
+            AssertJson("{ 'plainString': 'plain', 'o1String': '', 'plainInt32': 10, 'o2Int32': 0 }", formatter.Format(message));
+        }
+
+        [Test]
+        public void TimestampStandalone()
+        {
+            Assert.AreEqual("1970-01-01T00:00:00Z", new Timestamp().ToString());
+            Assert.AreEqual("1970-01-01T00:00:00.100Z", new Timestamp { Nanos = 100000000 }.ToString());
+            Assert.AreEqual("1970-01-01T00:00:00.120Z", new Timestamp { Nanos = 120000000 }.ToString());
+            Assert.AreEqual("1970-01-01T00:00:00.123Z", new Timestamp { Nanos = 123000000 }.ToString());
+            Assert.AreEqual("1970-01-01T00:00:00.123400Z", new Timestamp { Nanos = 123400000 }.ToString());
+            Assert.AreEqual("1970-01-01T00:00:00.123450Z", new Timestamp { Nanos = 123450000 }.ToString());
+            Assert.AreEqual("1970-01-01T00:00:00.123456Z", new Timestamp { Nanos = 123456000 }.ToString());
+            Assert.AreEqual("1970-01-01T00:00:00.123456700Z", new Timestamp { Nanos = 123456700 }.ToString());
+            Assert.AreEqual("1970-01-01T00:00:00.123456780Z", new Timestamp { Nanos = 123456780 }.ToString());
+            Assert.AreEqual("1970-01-01T00:00:00.123456789Z", new Timestamp { Nanos = 123456789 }.ToString());
+
+            // One before and one after the Unix epoch
+            Assert.AreEqual("1673-06-19T12:34:56Z",
+                new DateTime(1673, 6, 19, 12, 34, 56, DateTimeKind.Utc).ToTimestamp().ToString());
+            Assert.AreEqual("2015-07-31T10:29:34Z",
+                new DateTime(2015, 7, 31, 10, 29, 34, DateTimeKind.Utc).ToTimestamp().ToString());
+        }
+
+        [Test]
+        public void TimestampField()
+        {
+            var message = new TestWellKnownTypes { TimestampField = new Timestamp() };
+            AssertJson("{ 'timestampField': '1970-01-01T00:00:00Z' }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        [TestCase(0, 0, "0s")]
+        [TestCase(1, 0, "1s")]
+        [TestCase(-1, 0, "-1s")]
+        [TestCase(0, 100000000, "0.100s")]
+        [TestCase(0, 120000000, "0.120s")]
+        [TestCase(0, 123000000, "0.123s")]
+        [TestCase(0, 123400000, "0.123400s")]
+        [TestCase(0, 123450000, "0.123450s")]
+        [TestCase(0, 123456000, "0.123456s")]
+        [TestCase(0, 123456700, "0.123456700s")]
+        [TestCase(0, 123456780, "0.123456780s")]
+        [TestCase(0, 123456789, "0.123456789s")]
+        [TestCase(0, -100000000, "-0.100s")]
+        [TestCase(1, 100000000, "1.100s")]
+        [TestCase(-1, -100000000, "-1.100s")]
+        // Non-normalized examples
+        [TestCase(1, 2123456789, "3.123456789s")]
+        [TestCase(1, -100000000, "0.900s")]
+        public void DurationStandalone(long seconds, int nanoseconds, string expected)
+        {
+            Assert.AreEqual(expected, new Duration { Seconds = seconds, Nanos = nanoseconds }.ToString());
+        }
+
+        [Test]
+        public void DurationField()
+        {
+            var message = new TestWellKnownTypes { DurationField = new Duration() };
+            AssertJson("{ 'durationField': '0s' }", JsonFormatter.Default.Format(message));
+        }
+
+        [Test]
+        public void StructSample()
+        {
+            var message = new Struct
+            {
+                Fields =
+                {
+                    { "a", new Value { NullValue = new NullValue() } },
+                    { "b", new Value { BoolValue = false } },
+                    { "c", new Value { NumberValue = 10.5 } },
+                    { "d", new Value { StringValue = "text" } },
+                    { "e", new Value { ListValue = new ListValue { Values = { new Value { StringValue = "t1" }, new Value { NumberValue = 5 } } } } },
+                    { "f", new Value { StructValue = new Struct { Fields = { { "nested", new Value { StringValue = "value" } } } } } }
+                }
+            };
+            AssertJson("{ 'a': null, 'b': false, 'c': 10.5, 'd': 'text', 'e': [ 't1', 5 ], 'f': { 'nested': 'value' } }", message.ToString());
+        }
+
+        [Test]
+        public void FieldMaskStandalone()
+        {
+            var fieldMask = new FieldMask { Paths = { "", "single", "with_underscore", "nested.field.name", "nested..double_dot" } };
+            Assert.AreEqual(",single,withUnderscore,nested.field.name,nested..doubleDot", fieldMask.ToString());
+
+            // Invalid, but we shouldn't create broken JSON...
+            fieldMask = new FieldMask { Paths = { "x\\y" } };
+            Assert.AreEqual(@"x\\y", fieldMask.ToString());
+        }
+
+        [Test]
+        public void FieldMaskField()
+        {
+            var message = new TestWellKnownTypes { FieldMaskField = new FieldMask { Paths = { "user.display_name", "photo" } } };
+            AssertJson("{ 'fieldMaskField': 'user.displayName,photo' }", JsonFormatter.Default.Format(message));
+        }
+
+        /// <summary>
+        /// Checks that the actual JSON is the same as the expected JSON - but after replacing
+        /// all apostrophes in the expected JSON with double quotes. This basically makes the tests easier
+        /// to read.
+        /// </summary>
+        private static void AssertJson(string expectedJsonWithApostrophes, string actualJson)
+        {
+            var expectedJson = expectedJsonWithApostrophes.Replace("'", "\"");
+            Assert.AreEqual(expectedJson, actualJson);
+        }
+    }
+}

+ 6 - 0
csharp/src/Google.Protobuf.Test/Properties/AppManifest.xml

@@ -0,0 +1,6 @@
+<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+>
+    <Deployment.Parts>
+    </Deployment.Parts>
+</Deployment>

+ 20 - 0
csharp/src/Google.Protobuf.Test/Properties/AssemblyInfo.cs

@@ -0,0 +1,20 @@
+using System;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("Google.Protobuf.Test")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Google.Protobuf.Test")]
+[assembly: AssemblyCopyright("Copyright ©  2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+[assembly: AssemblyVersion("3.0.0.0")]
+[assembly: AssemblyFileVersion("3.0.0.0")]

+ 255 - 0
csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs

@@ -0,0 +1,255 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System.Linq;
+using Google.Protobuf.TestProtos;
+using NUnit.Framework;
+using UnitTest.Issues.TestProtos;
+
+namespace Google.Protobuf.Reflection
+{
+    /// <summary>
+    /// Tests for descriptors. (Not in its own namespace or broken up into individual classes as the
+    /// size doesn't warrant it. On the other hand, this makes me feel a bit dirty...)
+    /// </summary>
+    public class DescriptorsTest
+    {
+        [Test]
+        public void FileDescriptor()
+        {
+            FileDescriptor file = UnittestProto3.Descriptor;
+
+            Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Name);
+            Assert.AreEqual("protobuf_unittest", file.Package);
+
+            Assert.AreEqual("UnittestProto", file.Proto.Options.JavaOuterClassname);
+            Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Proto.Name);
+
+            // unittest.proto doesn't have any public imports, but unittest_import.proto does.
+            Assert.AreEqual(0, file.PublicDependencies.Count);
+            Assert.AreEqual(1, UnittestImportProto3.Descriptor.PublicDependencies.Count);
+            Assert.AreEqual(UnittestImportPublicProto3.Descriptor, UnittestImportProto3.Descriptor.PublicDependencies[0]);
+
+            Assert.AreEqual(1, file.Dependencies.Count);
+            Assert.AreEqual(UnittestImportProto3.Descriptor, file.Dependencies[0]);
+
+            MessageDescriptor messageType = TestAllTypes.Descriptor;
+            Assert.AreSame(typeof(TestAllTypes), messageType.GeneratedType);
+            Assert.AreEqual(messageType, file.MessageTypes[0]);
+            Assert.AreEqual(messageType, file.FindTypeByName<MessageDescriptor>("TestAllTypes"));
+            Assert.Null(file.FindTypeByName<MessageDescriptor>("NoSuchType"));
+            Assert.Null(file.FindTypeByName<MessageDescriptor>("protobuf_unittest.TestAllTypes"));
+            for (int i = 0; i < file.MessageTypes.Count; i++)
+            {
+                Assert.AreEqual(i, file.MessageTypes[i].Index);
+            }
+
+            Assert.AreEqual(file.EnumTypes[0], file.FindTypeByName<EnumDescriptor>("ForeignEnum"));
+            Assert.Null(file.FindTypeByName<EnumDescriptor>("NoSuchType"));
+            Assert.Null(file.FindTypeByName<EnumDescriptor>("protobuf_unittest.ForeignEnum"));
+            Assert.AreEqual(1, UnittestImportProto3.Descriptor.EnumTypes.Count);
+            Assert.AreEqual("ImportEnum", UnittestImportProto3.Descriptor.EnumTypes[0].Name);
+            for (int i = 0; i < file.EnumTypes.Count; i++)
+            {
+                Assert.AreEqual(i, file.EnumTypes[i].Index);
+            }
+
+            Assert.AreEqual(10, file.SerializedData[0]);
+        }
+
+        [Test]
+        public void MessageDescriptor()
+        {
+            MessageDescriptor messageType = TestAllTypes.Descriptor;
+            MessageDescriptor nestedType = TestAllTypes.Types.NestedMessage.Descriptor;
+
+            Assert.AreEqual("TestAllTypes", messageType.Name);
+            Assert.AreEqual("protobuf_unittest.TestAllTypes", messageType.FullName);
+            Assert.AreEqual(UnittestProto3.Descriptor, messageType.File);
+            Assert.IsNull(messageType.ContainingType);
+            Assert.IsNull(messageType.Proto.Options);
+
+            Assert.AreEqual("TestAllTypes", messageType.Name);
+
+            Assert.AreEqual("NestedMessage", nestedType.Name);
+            Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedMessage", nestedType.FullName);
+            Assert.AreEqual(UnittestProto3.Descriptor, nestedType.File);
+            Assert.AreEqual(messageType, nestedType.ContainingType);
+
+            FieldDescriptor field = messageType.Fields.InDeclarationOrder()[0];
+            Assert.AreEqual("single_int32", field.Name);
+            Assert.AreEqual(field, messageType.FindDescriptor<FieldDescriptor>("single_int32"));
+            Assert.Null(messageType.FindDescriptor<FieldDescriptor>("no_such_field"));
+            Assert.AreEqual(field, messageType.FindFieldByNumber(1));
+            Assert.Null(messageType.FindFieldByNumber(571283));
+            var fieldsInDeclarationOrder = messageType.Fields.InDeclarationOrder();
+            for (int i = 0; i < fieldsInDeclarationOrder.Count; i++)
+            {
+                Assert.AreEqual(i, fieldsInDeclarationOrder[i].Index);
+            }
+
+            Assert.AreEqual(nestedType, messageType.NestedTypes[0]);
+            Assert.AreEqual(nestedType, messageType.FindDescriptor<MessageDescriptor>("NestedMessage"));
+            Assert.Null(messageType.FindDescriptor<MessageDescriptor>("NoSuchType"));
+            for (int i = 0; i < messageType.NestedTypes.Count; i++)
+            {
+                Assert.AreEqual(i, messageType.NestedTypes[i].Index);
+            }
+
+            Assert.AreEqual(messageType.EnumTypes[0], messageType.FindDescriptor<EnumDescriptor>("NestedEnum"));
+            Assert.Null(messageType.FindDescriptor<EnumDescriptor>("NoSuchType"));
+            for (int i = 0; i < messageType.EnumTypes.Count; i++)
+            {
+                Assert.AreEqual(i, messageType.EnumTypes[i].Index);
+            }
+        }
+
+        [Test]
+        public void FieldDescriptor()
+        {
+            MessageDescriptor messageType = TestAllTypes.Descriptor;
+            FieldDescriptor primitiveField = messageType.FindDescriptor<FieldDescriptor>("single_int32");
+            FieldDescriptor enumField = messageType.FindDescriptor<FieldDescriptor>("single_nested_enum");
+            FieldDescriptor messageField = messageType.FindDescriptor<FieldDescriptor>("single_foreign_message");
+
+            Assert.AreEqual("single_int32", primitiveField.Name);
+            Assert.AreEqual("protobuf_unittest.TestAllTypes.single_int32",
+                            primitiveField.FullName);
+            Assert.AreEqual(1, primitiveField.FieldNumber);
+            Assert.AreEqual(messageType, primitiveField.ContainingType);
+            Assert.AreEqual(UnittestProto3.Descriptor, primitiveField.File);
+            Assert.AreEqual(FieldType.Int32, primitiveField.FieldType);
+            Assert.IsNull(primitiveField.Proto.Options);
+            
+            Assert.AreEqual("single_nested_enum", enumField.Name);
+            Assert.AreEqual(FieldType.Enum, enumField.FieldType);
+            // Assert.AreEqual(TestAllTypes.Types.NestedEnum.DescriptorProtoFile, enumField.EnumType);
+
+            Assert.AreEqual("single_foreign_message", messageField.Name);
+            Assert.AreEqual(FieldType.Message, messageField.FieldType);
+            Assert.AreEqual(ForeignMessage.Descriptor, messageField.MessageType);
+        }
+
+        [Test]
+        public void FieldDescriptorLabel()
+        {
+            FieldDescriptor singleField =
+                TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("single_int32");
+            FieldDescriptor repeatedField =
+                TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("repeated_int32");
+
+            Assert.IsFalse(singleField.IsRepeated);
+            Assert.IsTrue(repeatedField.IsRepeated);
+        }
+
+        [Test]
+        public void EnumDescriptor()
+        {
+            // Note: this test is a bit different to the Java version because there's no static way of getting to the descriptor
+            EnumDescriptor enumType = UnittestProto3.Descriptor.FindTypeByName<EnumDescriptor>("ForeignEnum");
+            EnumDescriptor nestedType = TestAllTypes.Descriptor.FindDescriptor<EnumDescriptor>("NestedEnum");
+
+            Assert.AreEqual("ForeignEnum", enumType.Name);
+            Assert.AreEqual("protobuf_unittest.ForeignEnum", enumType.FullName);
+            Assert.AreEqual(UnittestProto3.Descriptor, enumType.File);
+            Assert.Null(enumType.ContainingType);
+            Assert.Null(enumType.Proto.Options);
+
+            Assert.AreEqual("NestedEnum", nestedType.Name);
+            Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedEnum",
+                            nestedType.FullName);
+            Assert.AreEqual(UnittestProto3.Descriptor, nestedType.File);
+            Assert.AreEqual(TestAllTypes.Descriptor, nestedType.ContainingType);
+
+            EnumValueDescriptor value = enumType.FindValueByName("FOREIGN_FOO");
+            Assert.AreEqual(value, enumType.Values[1]);
+            Assert.AreEqual("FOREIGN_FOO", value.Name);
+            Assert.AreEqual(4, value.Number);
+            Assert.AreEqual((int) ForeignEnum.FOREIGN_FOO, value.Number);
+            Assert.AreEqual(value, enumType.FindValueByNumber(4));
+            Assert.Null(enumType.FindValueByName("NO_SUCH_VALUE"));
+            for (int i = 0; i < enumType.Values.Count; i++)
+            {
+                Assert.AreEqual(i, enumType.Values[i].Index);
+            }
+        }
+
+        [Test]
+        public void OneofDescriptor()
+        {
+            OneofDescriptor descriptor = TestAllTypes.Descriptor.FindDescriptor<OneofDescriptor>("oneof_field");
+            Assert.AreEqual("oneof_field", descriptor.Name);
+            Assert.AreEqual("protobuf_unittest.TestAllTypes.oneof_field", descriptor.FullName);
+
+            var expectedFields = new[] {
+                TestAllTypes.OneofBytesFieldNumber,
+                TestAllTypes.OneofNestedMessageFieldNumber,
+                TestAllTypes.OneofStringFieldNumber,
+                TestAllTypes.OneofUint32FieldNumber }
+                .Select(fieldNumber => TestAllTypes.Descriptor.FindFieldByNumber(fieldNumber))
+                .ToList();
+            foreach (var field in expectedFields)
+            {
+                Assert.AreSame(descriptor, field.ContainingOneof);
+            }
+
+            CollectionAssert.AreEquivalent(expectedFields, descriptor.Fields);
+        }
+
+        [Test]
+        public void ConstructionWithoutGeneratedCodeInfo()
+        {
+            var data = UnittestIssues.Descriptor.Proto.ToByteArray();
+            var newDescriptor = Google.Protobuf.Reflection.FileDescriptor.InternalBuildGeneratedFileFrom(data, new Reflection.FileDescriptor[] { }, null);
+
+            // We should still be able to get at a field...
+            var messageDescriptor = newDescriptor.FindTypeByName<MessageDescriptor>("ItemField");
+            var fieldDescriptor = messageDescriptor.FindFieldByName("item");
+            // But there shouldn't be an accessor (or a generated type for the message)
+            Assert.IsNull(fieldDescriptor.Accessor);
+            Assert.IsNull(messageDescriptor.GeneratedType);
+        }
+
+        // From TestFieldOrdering:
+        // string my_string = 11;
+        // int64 my_int = 1;
+        // float my_float = 101;
+        // NestedMessage single_nested_message = 200;
+        [Test]
+        public void FieldListOrderings()
+        { 
+            var fields = TestFieldOrderings.Descriptor.Fields;
+            Assert.AreEqual(new[] { 11, 1, 101, 200 }, fields.InDeclarationOrder().Select(x => x.FieldNumber));
+            Assert.AreEqual(new[] { 1, 11, 101, 200 }, fields.InFieldNumberOrder().Select(x => x.FieldNumber));
+        }
+    }
+}

+ 218 - 0
csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs

@@ -0,0 +1,218 @@
+#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 Google.Protobuf.TestProtos;
+using NUnit.Framework;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Google.Protobuf.Reflection
+{
+    public class FieldAccessTest
+    {
+        [Test]
+        public void GetValue()
+        {
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var fields = TestAllTypes.Descriptor.Fields;
+            Assert.AreEqual(message.SingleBool, fields[TestAllTypes.SingleBoolFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleBytes, fields[TestAllTypes.SingleBytesFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleDouble, fields[TestAllTypes.SingleDoubleFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleFixed32, fields[TestAllTypes.SingleFixed32FieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleFixed64, fields[TestAllTypes.SingleFixed64FieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleFloat, fields[TestAllTypes.SingleFloatFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleForeignEnum, fields[TestAllTypes.SingleForeignEnumFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleForeignMessage, fields[TestAllTypes.SingleForeignMessageFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleImportEnum, fields[TestAllTypes.SingleImportEnumFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleImportMessage, fields[TestAllTypes.SingleImportMessageFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleInt32, fields[TestAllTypes.SingleInt32FieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleInt64, fields[TestAllTypes.SingleInt64FieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleNestedEnum, fields[TestAllTypes.SingleNestedEnumFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleNestedMessage, fields[TestAllTypes.SingleNestedMessageFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SinglePublicImportMessage, fields[TestAllTypes.SinglePublicImportMessageFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleSint32, fields[TestAllTypes.SingleSint32FieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleSint64, fields[TestAllTypes.SingleSint64FieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleString, fields[TestAllTypes.SingleStringFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleSfixed32, fields[TestAllTypes.SingleSfixed32FieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleSfixed64, fields[TestAllTypes.SingleSfixed64FieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleUint32, fields[TestAllTypes.SingleUint32FieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.SingleUint64, fields[TestAllTypes.SingleUint64FieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.OneofBytes, fields[TestAllTypes.OneofBytesFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.OneofString, fields[TestAllTypes.OneofStringFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.OneofNestedMessage, fields[TestAllTypes.OneofNestedMessageFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(message.OneofUint32, fields[TestAllTypes.OneofUint32FieldNumber].Accessor.GetValue(message));
+
+            // Just one example for repeated fields - they're all just returning the list
+            var list = (IList) fields[TestAllTypes.RepeatedInt32FieldNumber].Accessor.GetValue(message);
+            Assert.AreEqual(message.RepeatedInt32, list);
+            Assert.AreEqual(message.RepeatedInt32[0], list[0]); // Just in case there was any doubt...
+
+            // Just a single map field, for the same reason
+            var mapMessage = new TestMap { MapStringString = { { "key1", "value1" }, { "key2", "value2" } } };
+            fields = TestMap.Descriptor.Fields;
+            var dictionary = (IDictionary) fields[TestMap.MapStringStringFieldNumber].Accessor.GetValue(mapMessage);
+            Assert.AreEqual(mapMessage.MapStringString, dictionary);
+            Assert.AreEqual("value1", dictionary["key1"]);
+        }
+
+        [Test]
+        public void Clear()
+        {
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var fields = TestAllTypes.Descriptor.Fields;
+            fields[TestAllTypes.SingleBoolFieldNumber].Accessor.Clear(message);
+            fields[TestAllTypes.SingleInt32FieldNumber].Accessor.Clear(message);
+            fields[TestAllTypes.SingleStringFieldNumber].Accessor.Clear(message);
+            fields[TestAllTypes.SingleBytesFieldNumber].Accessor.Clear(message);
+            fields[TestAllTypes.SingleForeignEnumFieldNumber].Accessor.Clear(message);
+            fields[TestAllTypes.SingleForeignMessageFieldNumber].Accessor.Clear(message);
+            fields[TestAllTypes.RepeatedDoubleFieldNumber].Accessor.Clear(message);
+
+            var expected = new TestAllTypes(SampleMessages.CreateFullTestAllTypes())
+            {
+                SingleBool = false,
+                SingleInt32 = 0,
+                SingleString = "",
+                SingleBytes = ByteString.Empty,
+                SingleForeignEnum = 0,
+                SingleForeignMessage = null,
+            };
+            expected.RepeatedDouble.Clear();
+
+            Assert.AreEqual(expected, message);
+
+            // Separately, maps.
+            var mapMessage = new TestMap { MapStringString = { { "key1", "value1" }, { "key2", "value2" } } };
+            fields = TestMap.Descriptor.Fields;
+            fields[TestMap.MapStringStringFieldNumber].Accessor.Clear(mapMessage);
+            Assert.AreEqual(0, mapMessage.MapStringString.Count);
+        }
+
+        [Test]
+        public void SetValue_SingleFields()
+        {
+            // Just a sample (primitives, messages, enums, strings, byte strings)
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var fields = TestAllTypes.Descriptor.Fields;
+            fields[TestAllTypes.SingleBoolFieldNumber].Accessor.SetValue(message, false);
+            fields[TestAllTypes.SingleInt32FieldNumber].Accessor.SetValue(message, 500);
+            fields[TestAllTypes.SingleStringFieldNumber].Accessor.SetValue(message, "It's a string");
+            fields[TestAllTypes.SingleBytesFieldNumber].Accessor.SetValue(message, ByteString.CopyFrom(99, 98, 97));
+            fields[TestAllTypes.SingleForeignEnumFieldNumber].Accessor.SetValue(message, ForeignEnum.FOREIGN_FOO);
+            fields[TestAllTypes.SingleForeignMessageFieldNumber].Accessor.SetValue(message, new ForeignMessage { C = 12345 });
+            fields[TestAllTypes.SingleDoubleFieldNumber].Accessor.SetValue(message, 20150701.5);
+
+            var expected = new TestAllTypes(SampleMessages.CreateFullTestAllTypes())
+            {
+                SingleBool = false,
+                SingleInt32 = 500,
+                SingleString = "It's a string",
+                SingleBytes = ByteString.CopyFrom(99, 98, 97),
+                SingleForeignEnum = ForeignEnum.FOREIGN_FOO,
+                SingleForeignMessage = new ForeignMessage { C = 12345 },
+                SingleDouble = 20150701.5
+            };
+
+            Assert.AreEqual(expected, message);
+        }
+
+        [Test]
+        public void SetValue_SingleFields_WrongType()
+        {
+            IMessage message = SampleMessages.CreateFullTestAllTypes();
+            var fields = message.Descriptor.Fields;
+            Assert.Throws<InvalidCastException>(() => fields[TestAllTypes.SingleBoolFieldNumber].Accessor.SetValue(message, "This isn't a bool"));
+        }
+
+        [Test]
+        public void SetValue_MapFields()
+        {
+            IMessage message = new TestMap();
+            var fields = message.Descriptor.Fields;
+            Assert.Throws<InvalidOperationException>(() => fields[TestMap.MapStringStringFieldNumber].Accessor.SetValue(message, new Dictionary<string, string>()));
+        }
+
+        [Test]
+        public void SetValue_RepeatedFields()
+        {
+            IMessage message = SampleMessages.CreateFullTestAllTypes();
+            var fields = message.Descriptor.Fields;
+            Assert.Throws<InvalidOperationException>(() => fields[TestAllTypes.RepeatedDoubleFieldNumber].Accessor.SetValue(message, new double[10]));
+        }
+
+        [Test]
+        public void GetValue_IncorrectType()
+        {
+            IMessage message = SampleMessages.CreateFullTestAllTypes();
+            var fields = message.Descriptor.Fields;
+            Assert.Throws<InvalidCastException>(() => fields[TestAllTypes.SingleBoolFieldNumber].Accessor.GetValue(new TestMap()));
+        }
+
+        [Test]
+        public void Oneof()
+        {
+            var message = new TestAllTypes();
+            var descriptor = TestAllTypes.Descriptor;
+            Assert.AreEqual(1, descriptor.Oneofs.Count);
+            var oneof = descriptor.Oneofs[0];
+            Assert.AreEqual("oneof_field", oneof.Name);
+            Assert.IsNull(oneof.Accessor.GetCaseFieldDescriptor(message));
+
+            message.OneofString = "foo";
+            Assert.AreSame(descriptor.Fields[TestAllTypes.OneofStringFieldNumber], oneof.Accessor.GetCaseFieldDescriptor(message));
+
+            message.OneofUint32 = 10;
+            Assert.AreSame(descriptor.Fields[TestAllTypes.OneofUint32FieldNumber], oneof.Accessor.GetCaseFieldDescriptor(message));
+
+            oneof.Accessor.Clear(message);
+            Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
+        }
+
+        [Test]
+        public void FieldDescriptor_ByName()
+        {
+            var descriptor = TestAllTypes.Descriptor;
+            Assert.AreSame(
+                descriptor.Fields[TestAllTypes.SingleBoolFieldNumber],
+                descriptor.Fields["single_bool"]);
+        }
+
+        [Test]
+        public void FieldDescriptor_NotFound()
+        {
+            var descriptor = TestAllTypes.Descriptor;
+            Assert.Throws<KeyNotFoundException>(() => descriptor.Fields[999999].ToString());
+            Assert.Throws<KeyNotFoundException>(() => descriptor.Fields["not found"].ToString());
+        }        
+    }
+}

+ 42 - 0
csharp/src/Google.Protobuf.Test/SampleEnum.cs

@@ -0,0 +1,42 @@
+#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
+    
+namespace Google.Protobuf
+{
+    // Just a sample enum with positive and negative values to be used in tests.
+    internal enum SampleEnum
+    {
+        NegativeValue = -2,
+        None = 0,
+        PositiveValue = 3
+    }
+}

+ 99 - 0
csharp/src/Google.Protobuf.Test/SampleMessages.cs

@@ -0,0 +1,99 @@
+#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 Google.Protobuf.TestProtos;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Helper methods to create sample instances of types generated from unit test messages.
+    /// </summary>
+    public class SampleMessages
+    {
+        /// <summary>
+        /// Creates a new sample TestAllTypes message with all fields populated.
+        /// The "oneof" field is populated with the string property (OneofString).
+        /// </summary>
+        public static TestAllTypes CreateFullTestAllTypes()
+        {
+            return new TestAllTypes
+            {
+                SingleBool = true,
+                SingleBytes = ByteString.CopyFrom(1, 2, 3, 4),
+                SingleDouble = 23.5,
+                SingleFixed32 = 23,
+                SingleFixed64 = 1234567890123,
+                SingleFloat = 12.25f,
+                SingleForeignEnum = ForeignEnum.FOREIGN_BAR,
+                SingleForeignMessage = new ForeignMessage { C = 10 },
+                SingleImportEnum = ImportEnum.IMPORT_BAZ,
+                SingleImportMessage = new ImportMessage { D = 20 },
+                SingleInt32 = 100,
+                SingleInt64 = 3210987654321,
+                SingleNestedEnum = TestAllTypes.Types.NestedEnum.FOO,
+                SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 35 },
+                SinglePublicImportMessage = new PublicImportMessage { E = 54 },
+                SingleSfixed32 = -123,
+                SingleSfixed64 = -12345678901234,
+                SingleSint32 = -456,
+                SingleSint64 = -12345678901235,
+                SingleString = "test",
+                SingleUint32 = UInt32.MaxValue,
+                SingleUint64 = UInt64.MaxValue,
+                RepeatedBool = { true, false },
+                RepeatedBytes = { ByteString.CopyFrom(1, 2, 3, 4), ByteString.CopyFrom(5, 6), ByteString.CopyFrom(new byte[1000]) },
+                RepeatedDouble = { -12.25, 23.5 },
+                RepeatedFixed32 = { UInt32.MaxValue, 23 },
+                RepeatedFixed64 = { UInt64.MaxValue, 1234567890123 },
+                RepeatedFloat = { 100f, 12.25f },
+                RepeatedForeignEnum = { ForeignEnum.FOREIGN_FOO, ForeignEnum.FOREIGN_BAR },
+                RepeatedForeignMessage = { new ForeignMessage(), new ForeignMessage { C = 10 } },
+                RepeatedImportEnum = { ImportEnum.IMPORT_BAZ, ImportEnum.IMPORT_ENUM_UNSPECIFIED },
+                RepeatedImportMessage = { new ImportMessage { D = 20 }, new ImportMessage { D = 25 } },
+                RepeatedInt32 = { 100, 200 },
+                RepeatedInt64 = { 3210987654321, Int64.MaxValue },
+                RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.FOO, TestAllTypes.Types.NestedEnum.NEG },
+                RepeatedNestedMessage = { new TestAllTypes.Types.NestedMessage { Bb = 35 }, new TestAllTypes.Types.NestedMessage { Bb = 10 } },
+                RepeatedPublicImportMessage = { new PublicImportMessage { E = 54 }, new PublicImportMessage { E = -1 } },
+                RepeatedSfixed32 = { -123, 123 },
+                RepeatedSfixed64 = { -12345678901234, 12345678901234 },
+                RepeatedSint32 = { -456, 100 },
+                RepeatedSint64 = { -12345678901235, 123 },
+                RepeatedString = { "foo", "bar" },
+                RepeatedUint32 = { UInt32.MaxValue, UInt32.MinValue },
+                RepeatedUint64 = { UInt64.MaxValue, UInt32.MinValue },
+                OneofString = "Oneof string"                
+            };
+        }
+    }
+}

+ 62 - 0
csharp/src/Google.Protobuf.Test/TestCornerCases.cs

@@ -0,0 +1,62 @@
+#region Copyright notice and license
+// 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.
+#endregion
+    
+using UnitTest.Issues.TestProtos;
+using NUnit.Framework;
+
+namespace Google.Protobuf
+{
+    public class TestCornerCases
+    {
+        [Test]
+        public void TestRoundTripNegativeEnums()
+        {
+            NegativeEnumMessage msg = new NegativeEnumMessage
+            {
+                Value = NegativeEnum.MinusOne,
+                Values = { NegativeEnum.NEGATIVE_ENUM_ZERO, NegativeEnum.MinusOne, NegativeEnum.FiveBelow },
+                PackedValues = { NegativeEnum.NEGATIVE_ENUM_ZERO, NegativeEnum.MinusOne, NegativeEnum.FiveBelow }
+            };
+
+            Assert.AreEqual(58, msg.CalculateSize());
+
+            byte[] bytes = new byte[58];
+            CodedOutputStream output = new CodedOutputStream(bytes);
+
+            msg.WriteTo(output);
+            Assert.AreEqual(0, output.SpaceLeft);
+
+            NegativeEnumMessage copy = NegativeEnumMessage.Parser.ParseFrom(bytes);
+            Assert.AreEqual(msg, copy);
+        }
+    }
+}

+ 1417 - 0
csharp/src/Google.Protobuf.Test/TestProtos/MapUnittestProto3.cs

@@ -0,0 +1,1417 @@
+// 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 pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.TestProtos {
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class MapUnittestProto3 {
+
+    #region Descriptor
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::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="));
+      descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+          new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor, },
+          new pbr::GeneratedCodeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.MapEnum), }, new pbr::GeneratedCodeInfo[] {
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestMap), new[]{ "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapInt32Bytes", "MapInt32Enum", "MapInt32ForeignMessage" }, null, null, new pbr::GeneratedCodeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestMapSubmessage), new[]{ "TestMap" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestMessageMap), new[]{ "MapInt32Message" }, null, null, new pbr::GeneratedCodeInfo[] { null, }),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestSameTypeMap), new[]{ "Map1", "Map2" }, null, null, new pbr::GeneratedCodeInfo[] { null, null, }),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestArenaMap), new[]{ "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapInt32Enum", "MapInt32ForeignMessage" }, null, null, new pbr::GeneratedCodeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType), new[]{ "Type" }, null, new[]{ typeof(global::Google.Protobuf.TestProtos.MessageContainingEnumCalledType.Types.Type) }, new pbr::GeneratedCodeInfo[] { null, }),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.MessageContainingMapCalledEntry), new[]{ "Entry" }, null, null, new pbr::GeneratedCodeInfo[] { null, })
+          }));
+    }
+    #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; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestMap() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestMap(TestMap other) : this() {
+      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 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 override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    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 ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            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;
+          }
+        }
+      }
+    }
+
+  }
+
+  [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; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.Descriptor.MessageTypes[1]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestMapSubmessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestMapSubmessage(TestMapSubmessage other) : this() {
+      TestMap = other.testMap_ != null ? other.TestMap.Clone() : null;
+    }
+
+    public TestMapSubmessage Clone() {
+      return new TestMapSubmessage(this);
+    }
+
+    public const int TestMapFieldNumber = 1;
+    private global::Google.Protobuf.TestProtos.TestMap testMap_;
+    public global::Google.Protobuf.TestProtos.TestMap TestMap {
+      get { return testMap_; }
+      set {
+        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 override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    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 ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            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; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.Descriptor.MessageTypes[2]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestMessageMap() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestMessageMap(TestMessageMap other) : this() {
+      mapInt32Message_ = other.mapInt32Message_.Clone();
+    }
+
+    public TestMessageMap Clone() {
+      return new TestMessageMap(this);
+    }
+
+    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 override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    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 ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            mapInt32Message_.AddEntriesFrom(input, _map_mapInt32Message_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [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; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.Descriptor.MessageTypes[3]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestSameTypeMap() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestSameTypeMap(TestSameTypeMap other) : this() {
+      map1_ = other.map1_.Clone();
+      map2_ = other.map2_.Clone();
+    }
+
+    public TestSameTypeMap Clone() {
+      return new TestSameTypeMap(this);
+    }
+
+    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 override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    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 ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            map1_.AddEntriesFrom(input, _map_map1_codec);
+            break;
+          }
+          case 18: {
+            map2_.AddEntriesFrom(input, _map_map2_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [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; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.Descriptor.MessageTypes[4]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestArenaMap() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestArenaMap(TestArenaMap other) : this() {
+      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 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 override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    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 ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            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;
+          }
+        }
+      }
+    }
+
+  }
+
+  [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; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.Descriptor.MessageTypes[5]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public MessageContainingEnumCalledType() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public MessageContainingEnumCalledType(MessageContainingEnumCalledType other) : this() {
+      type_ = other.type_.Clone();
+    }
+
+    public MessageContainingEnumCalledType Clone() {
+      return new MessageContainingEnumCalledType(this);
+    }
+
+    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 override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    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 ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            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,
+      }
+
+    }
+    #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; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.MapUnittestProto3.Descriptor.MessageTypes[6]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public MessageContainingMapCalledEntry() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public MessageContainingMapCalledEntry(MessageContainingMapCalledEntry other) : this() {
+      entry_ = other.entry_.Clone();
+    }
+
+    public MessageContainingMapCalledEntry Clone() {
+      return new MessageContainingMapCalledEntry(this);
+    }
+
+    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 override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    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 ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            entry_.AddEntriesFrom(input, _map_entry_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code

+ 158 - 0
csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportProto3.cs

@@ -0,0 +1,158 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/unittest_import_proto3.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.TestProtos {
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class UnittestImportProto3 {
+
+    #region Descriptor
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static UnittestImportProto3() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "Cixnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfaW1wb3J0X3Byb3RvMy5wcm90", 
+            "bxIYcHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0GjNnb29nbGUvcHJvdG9idWYv", 
+            "dW5pdHRlc3RfaW1wb3J0X3B1YmxpY19wcm90bzMucHJvdG8iGgoNSW1wb3J0", 
+            "TWVzc2FnZRIJCgFkGAEgASgFKlkKCkltcG9ydEVudW0SGwoXSU1QT1JUX0VO", 
+            "VU1fVU5TUEVDSUZJRUQQABIOCgpJTVBPUlRfRk9PEAcSDgoKSU1QT1JUX0JB", 
+            "UhAIEg4KCklNUE9SVF9CQVoQCUI8Chhjb20uZ29vZ2xlLnByb3RvYnVmLnRl", 
+            "c3RIAfgBAaoCGkdvb2dsZS5Qcm90b2J1Zi5UZXN0UHJvdG9zUABiBnByb3Rv", 
+            "Mw=="));
+      descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+          new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestImportPublicProto3.Descriptor, },
+          new pbr::GeneratedCodeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.ImportEnum), }, new pbr::GeneratedCodeInfo[] {
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.ImportMessage), new[]{ "D" }, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Enums
+  public enum ImportEnum {
+    IMPORT_ENUM_UNSPECIFIED = 0,
+    IMPORT_FOO = 7,
+    IMPORT_BAR = 8,
+    IMPORT_BAZ = 9,
+  }
+
+  #endregion
+
+  #region Messages
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ImportMessage : pb::IMessage<ImportMessage> {
+    private static readonly pb::MessageParser<ImportMessage> _parser = new pb::MessageParser<ImportMessage>(() => new ImportMessage());
+    public static pb::MessageParser<ImportMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestImportProto3.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ImportMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ImportMessage(ImportMessage other) : this() {
+      d_ = other.d_;
+    }
+
+    public ImportMessage Clone() {
+      return new ImportMessage(this);
+    }
+
+    public const int DFieldNumber = 1;
+    private int d_;
+    public int D {
+      get { return d_; }
+      set {
+        d_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ImportMessage);
+    }
+
+    public bool Equals(ImportMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (D != other.D) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (D != 0) hash ^= D.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (D != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(D);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (D != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(D);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ImportMessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.D != 0) {
+        D = other.D;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            D = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code

+ 144 - 0
csharp/src/Google.Protobuf.Test/TestProtos/UnittestImportPublicProto3.cs

@@ -0,0 +1,144 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/unittest_import_public_proto3.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.TestProtos {
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class UnittestImportPublicProto3 {
+
+    #region Descriptor
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static UnittestImportPublicProto3() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "CjNnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfaW1wb3J0X3B1YmxpY19wcm90", 
+            "bzMucHJvdG8SGHByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydCIgChNQdWJsaWNJ", 
+            "bXBvcnRNZXNzYWdlEgkKAWUYASABKAVCNwoYY29tLmdvb2dsZS5wcm90b2J1", 
+            "Zi50ZXN0qgIaR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3NiBnByb3RvMw=="));
+      descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.PublicImportMessage), new[]{ "E" }, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Messages
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class PublicImportMessage : pb::IMessage<PublicImportMessage> {
+    private static readonly pb::MessageParser<PublicImportMessage> _parser = new pb::MessageParser<PublicImportMessage>(() => new PublicImportMessage());
+    public static pb::MessageParser<PublicImportMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestImportPublicProto3.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public PublicImportMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public PublicImportMessage(PublicImportMessage other) : this() {
+      e_ = other.e_;
+    }
+
+    public PublicImportMessage Clone() {
+      return new PublicImportMessage(this);
+    }
+
+    public const int EFieldNumber = 1;
+    private int e_;
+    public int E {
+      get { return e_; }
+      set {
+        e_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as PublicImportMessage);
+    }
+
+    public bool Equals(PublicImportMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (E != other.E) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (E != 0) hash ^= E.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (E != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(E);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (E != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(E);
+      }
+      return size;
+    }
+
+    public void MergeFrom(PublicImportMessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.E != 0) {
+        E = other.E;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            E = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code

+ 1355 - 0
csharp/src/Google.Protobuf.Test/TestProtos/UnittestIssues.cs

@@ -0,0 +1,1355 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: unittest_issues.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace UnitTest.Issues.TestProtos {
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class UnittestIssues {
+
+    #region Descriptor
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static UnittestIssues() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "ChV1bml0dGVzdF9pc3N1ZXMucHJvdG8SD3VuaXR0ZXN0X2lzc3VlcyInCghJ", 
+            "c3N1ZTMwNxobCgpOZXN0ZWRPbmNlGg0KC05lc3RlZFR3aWNlIrABChNOZWdh", 
+            "dGl2ZUVudW1NZXNzYWdlEiwKBXZhbHVlGAEgASgOMh0udW5pdHRlc3RfaXNz", 
+            "dWVzLk5lZ2F0aXZlRW51bRIxCgZ2YWx1ZXMYAiADKA4yHS51bml0dGVzdF9p", 
+            "c3N1ZXMuTmVnYXRpdmVFbnVtQgIQABI4Cg1wYWNrZWRfdmFsdWVzGAMgAygO", 
+            "Mh0udW5pdHRlc3RfaXNzdWVzLk5lZ2F0aXZlRW51bUICEAEiEQoPRGVwcmVj", 
+            "YXRlZENoaWxkIrkCChdEZXByZWNhdGVkRmllbGRzTWVzc2FnZRIaCg5Qcmlt", 
+            "aXRpdmVWYWx1ZRgBIAEoBUICGAESGgoOUHJpbWl0aXZlQXJyYXkYAiADKAVC", 
+            "AhgBEjoKDE1lc3NhZ2VWYWx1ZRgDIAEoCzIgLnVuaXR0ZXN0X2lzc3Vlcy5E", 
+            "ZXByZWNhdGVkQ2hpbGRCAhgBEjoKDE1lc3NhZ2VBcnJheRgEIAMoCzIgLnVu", 
+            "aXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkQ2hpbGRCAhgBEjYKCUVudW1WYWx1", 
+            "ZRgFIAEoDjIfLnVuaXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkRW51bUICGAES", 
+            "NgoJRW51bUFycmF5GAYgAygOMh8udW5pdHRlc3RfaXNzdWVzLkRlcHJlY2F0", 
+            "ZWRFbnVtQgIYASIZCglJdGVtRmllbGQSDAoEaXRlbRgBIAEoBSJECg1SZXNl", 
+            "cnZlZE5hbWVzEg0KBXR5cGVzGAEgASgFEhIKCmRlc2NyaXB0b3IYAiABKAUa", 
+            "EAoOU29tZU5lc3RlZFR5cGUioAEKFVRlc3RKc29uRmllbGRPcmRlcmluZxIT", 
+            "CgtwbGFpbl9pbnQzMhgEIAEoBRITCglvMV9zdHJpbmcYAiABKAlIABISCghv", 
+            "MV9pbnQzMhgFIAEoBUgAEhQKDHBsYWluX3N0cmluZxgBIAEoCRISCghvMl9p", 
+            "bnQzMhgGIAEoBUgBEhMKCW8yX3N0cmluZxgDIAEoCUgBQgQKAm8xQgQKAm8y", 
+            "KlUKDE5lZ2F0aXZlRW51bRIWChJORUdBVElWRV9FTlVNX1pFUk8QABIWCglG", 
+            "aXZlQmVsb3cQ+///////////ARIVCghNaW51c09uZRD///////////8BKi4K", 
+            "DkRlcHJlY2F0ZWRFbnVtEhMKD0RFUFJFQ0FURURfWkVSTxAAEgcKA29uZRAB", 
+            "Qh9IAaoCGlVuaXRUZXN0Lklzc3Vlcy5UZXN0UHJvdG9zYgZwcm90bzM="));
+      descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+          new pbr::FileDescriptor[] { },
+          new pbr::GeneratedCodeInfo(new[] {typeof(global::UnitTest.Issues.TestProtos.NegativeEnum), typeof(global::UnitTest.Issues.TestProtos.DeprecatedEnum), }, new pbr::GeneratedCodeInfo[] {
+            new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307), null, null, null, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce), null, null, null, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Types.NestedTwice), null, null, null, null)})}),
+            new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.NegativeEnumMessage), new[]{ "Value", "Values", "PackedValues" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.DeprecatedChild), null, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage), new[]{ "PrimitiveValue", "PrimitiveArray", "MessageValue", "MessageArray", "EnumValue", "EnumArray" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.ItemField), new[]{ "Item" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames), new[]{ "Types_", "Descriptor_" }, null, null, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.ReservedNames.Types.SomeNestedType), null, null, null, null)}),
+            new pbr::GeneratedCodeInfo(typeof(global::UnitTest.Issues.TestProtos.TestJsonFieldOrdering), new[]{ "PlainInt32", "O1String", "O1Int32", "PlainString", "O2Int32", "O2String" }, new[]{ "O1", "O2" }, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Enums
+  public enum NegativeEnum {
+    NEGATIVE_ENUM_ZERO = 0,
+    FiveBelow = -5,
+    MinusOne = -1,
+  }
+
+  public enum DeprecatedEnum {
+    DEPRECATED_ZERO = 0,
+    one = 1,
+  }
+
+  #endregion
+
+  #region Messages
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Issue307 : pb::IMessage<Issue307> {
+    private static readonly pb::MessageParser<Issue307> _parser = new pb::MessageParser<Issue307>(() => new Issue307());
+    public static pb::MessageParser<Issue307> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Issue307() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Issue307(Issue307 other) : this() {
+    }
+
+    public Issue307 Clone() {
+      return new Issue307(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Issue307);
+    }
+
+    public bool Equals(Issue307 other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(Issue307 other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+    #region Nested types
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class NestedOnce : pb::IMessage<NestedOnce> {
+        private static readonly pb::MessageParser<NestedOnce> _parser = new pb::MessageParser<NestedOnce>(() => new NestedOnce());
+        public static pb::MessageParser<NestedOnce> Parser { get { return _parser; } }
+
+        public static pbr::MessageDescriptor Descriptor {
+          get { return global::UnitTest.Issues.TestProtos.Issue307.Descriptor.NestedTypes[0]; }
+        }
+
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
+        }
+
+        public NestedOnce() {
+          OnConstruction();
+        }
+
+        partial void OnConstruction();
+
+        public NestedOnce(NestedOnce other) : this() {
+        }
+
+        public NestedOnce Clone() {
+          return new NestedOnce(this);
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as NestedOnce);
+        }
+
+        public bool Equals(NestedOnce other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          return hash;
+        }
+
+        public override string ToString() {
+          return pb::JsonFormatter.Default.Format(this);
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          return size;
+        }
+
+        public void MergeFrom(NestedOnce other) {
+          if (other == null) {
+            return;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                input.SkipLastField();
+                break;
+            }
+          }
+        }
+
+        #region Nested types
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        public static partial class Types {
+          [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+          public sealed partial class NestedTwice : pb::IMessage<NestedTwice> {
+            private static readonly pb::MessageParser<NestedTwice> _parser = new pb::MessageParser<NestedTwice>(() => new NestedTwice());
+            public static pb::MessageParser<NestedTwice> Parser { get { return _parser; } }
+
+            public static pbr::MessageDescriptor Descriptor {
+              get { return global::UnitTest.Issues.TestProtos.Issue307.Types.NestedOnce.Descriptor.NestedTypes[0]; }
+            }
+
+            pbr::MessageDescriptor pb::IMessage.Descriptor {
+              get { return Descriptor; }
+            }
+
+            public NestedTwice() {
+              OnConstruction();
+            }
+
+            partial void OnConstruction();
+
+            public NestedTwice(NestedTwice other) : this() {
+            }
+
+            public NestedTwice Clone() {
+              return new NestedTwice(this);
+            }
+
+            public override bool Equals(object other) {
+              return Equals(other as NestedTwice);
+            }
+
+            public bool Equals(NestedTwice other) {
+              if (ReferenceEquals(other, null)) {
+                return false;
+              }
+              if (ReferenceEquals(other, this)) {
+                return true;
+              }
+              return true;
+            }
+
+            public override int GetHashCode() {
+              int hash = 1;
+              return hash;
+            }
+
+            public override string ToString() {
+              return pb::JsonFormatter.Default.Format(this);
+            }
+
+            public void WriteTo(pb::CodedOutputStream output) {
+            }
+
+            public int CalculateSize() {
+              int size = 0;
+              return size;
+            }
+
+            public void MergeFrom(NestedTwice other) {
+              if (other == null) {
+                return;
+              }
+            }
+
+            public void MergeFrom(pb::CodedInputStream input) {
+              uint tag;
+              while ((tag = input.ReadTag()) != 0) {
+                switch(tag) {
+                  default:
+                    input.SkipLastField();
+                    break;
+                }
+              }
+            }
+
+          }
+
+        }
+        #endregion
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class NegativeEnumMessage : pb::IMessage<NegativeEnumMessage> {
+    private static readonly pb::MessageParser<NegativeEnumMessage> _parser = new pb::MessageParser<NegativeEnumMessage>(() => new NegativeEnumMessage());
+    public static pb::MessageParser<NegativeEnumMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[1]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public NegativeEnumMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public NegativeEnumMessage(NegativeEnumMessage other) : this() {
+      value_ = other.value_;
+      values_ = other.values_.Clone();
+      packedValues_ = other.packedValues_.Clone();
+    }
+
+    public NegativeEnumMessage Clone() {
+      return new NegativeEnumMessage(this);
+    }
+
+    public const int ValueFieldNumber = 1;
+    private global::UnitTest.Issues.TestProtos.NegativeEnum value_ = global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO;
+    public global::UnitTest.Issues.TestProtos.NegativeEnum Value {
+      get { return value_; }
+      set {
+        value_ = value;
+      }
+    }
+
+    public const int ValuesFieldNumber = 2;
+    private static readonly pb::FieldCodec<global::UnitTest.Issues.TestProtos.NegativeEnum> _repeated_values_codec
+        = pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::UnitTest.Issues.TestProtos.NegativeEnum) x);
+    private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> values_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum>();
+    public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> Values {
+      get { return values_; }
+    }
+
+    public const int PackedValuesFieldNumber = 3;
+    private static readonly pb::FieldCodec<global::UnitTest.Issues.TestProtos.NegativeEnum> _repeated_packedValues_codec
+        = pb::FieldCodec.ForEnum(26, x => (int) x, x => (global::UnitTest.Issues.TestProtos.NegativeEnum) x);
+    private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> packedValues_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum>();
+    public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.NegativeEnum> PackedValues {
+      get { return packedValues_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as NegativeEnumMessage);
+    }
+
+    public bool Equals(NegativeEnumMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Value != other.Value) return false;
+      if(!values_.Equals(other.values_)) return false;
+      if(!packedValues_.Equals(other.packedValues_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) hash ^= Value.GetHashCode();
+      hash ^= values_.GetHashCode();
+      hash ^= packedValues_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) {
+        output.WriteRawTag(8);
+        output.WriteEnum((int) Value);
+      }
+      values_.WriteTo(output, _repeated_values_codec);
+      packedValues_.WriteTo(output, _repeated_packedValues_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Value);
+      }
+      size += values_.CalculateSize(_repeated_values_codec);
+      size += packedValues_.CalculateSize(_repeated_packedValues_codec);
+      return size;
+    }
+
+    public void MergeFrom(NegativeEnumMessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) {
+        Value = other.Value;
+      }
+      values_.Add(other.values_);
+      packedValues_.Add(other.packedValues_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            value_ = (global::UnitTest.Issues.TestProtos.NegativeEnum) input.ReadEnum();
+            break;
+          }
+          case 18:
+          case 16: {
+            values_.AddEntriesFrom(input, _repeated_values_codec);
+            break;
+          }
+          case 26:
+          case 24: {
+            packedValues_.AddEntriesFrom(input, _repeated_packedValues_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class DeprecatedChild : pb::IMessage<DeprecatedChild> {
+    private static readonly pb::MessageParser<DeprecatedChild> _parser = new pb::MessageParser<DeprecatedChild>(() => new DeprecatedChild());
+    public static pb::MessageParser<DeprecatedChild> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[2]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public DeprecatedChild() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public DeprecatedChild(DeprecatedChild other) : this() {
+    }
+
+    public DeprecatedChild Clone() {
+      return new DeprecatedChild(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as DeprecatedChild);
+    }
+
+    public bool Equals(DeprecatedChild other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(DeprecatedChild other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class DeprecatedFieldsMessage : pb::IMessage<DeprecatedFieldsMessage> {
+    private static readonly pb::MessageParser<DeprecatedFieldsMessage> _parser = new pb::MessageParser<DeprecatedFieldsMessage>(() => new DeprecatedFieldsMessage());
+    public static pb::MessageParser<DeprecatedFieldsMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[3]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public DeprecatedFieldsMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public DeprecatedFieldsMessage(DeprecatedFieldsMessage other) : this() {
+      primitiveValue_ = other.primitiveValue_;
+      primitiveArray_ = other.primitiveArray_.Clone();
+      MessageValue = other.messageValue_ != null ? other.MessageValue.Clone() : null;
+      messageArray_ = other.messageArray_.Clone();
+      enumValue_ = other.enumValue_;
+      enumArray_ = other.enumArray_.Clone();
+    }
+
+    public DeprecatedFieldsMessage Clone() {
+      return new DeprecatedFieldsMessage(this);
+    }
+
+    public const int PrimitiveValueFieldNumber = 1;
+    private int primitiveValue_;
+    [global::System.ObsoleteAttribute()]
+    public int PrimitiveValue {
+      get { return primitiveValue_; }
+      set {
+        primitiveValue_ = value;
+      }
+    }
+
+    public const int PrimitiveArrayFieldNumber = 2;
+    private static readonly pb::FieldCodec<int> _repeated_primitiveArray_codec
+        = pb::FieldCodec.ForInt32(18);
+    private readonly pbc::RepeatedField<int> primitiveArray_ = new pbc::RepeatedField<int>();
+    [global::System.ObsoleteAttribute()]
+    public pbc::RepeatedField<int> PrimitiveArray {
+      get { return primitiveArray_; }
+    }
+
+    public const int MessageValueFieldNumber = 3;
+    private global::UnitTest.Issues.TestProtos.DeprecatedChild messageValue_;
+    [global::System.ObsoleteAttribute()]
+    public global::UnitTest.Issues.TestProtos.DeprecatedChild MessageValue {
+      get { return messageValue_; }
+      set {
+        messageValue_ = value;
+      }
+    }
+
+    public const int MessageArrayFieldNumber = 4;
+    private static readonly pb::FieldCodec<global::UnitTest.Issues.TestProtos.DeprecatedChild> _repeated_messageArray_codec
+        = pb::FieldCodec.ForMessage(34, global::UnitTest.Issues.TestProtos.DeprecatedChild.Parser);
+    private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedChild> messageArray_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedChild>();
+    [global::System.ObsoleteAttribute()]
+    public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedChild> MessageArray {
+      get { return messageArray_; }
+    }
+
+    public const int EnumValueFieldNumber = 5;
+    private global::UnitTest.Issues.TestProtos.DeprecatedEnum enumValue_ = global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO;
+    [global::System.ObsoleteAttribute()]
+    public global::UnitTest.Issues.TestProtos.DeprecatedEnum EnumValue {
+      get { return enumValue_; }
+      set {
+        enumValue_ = value;
+      }
+    }
+
+    public const int EnumArrayFieldNumber = 6;
+    private static readonly pb::FieldCodec<global::UnitTest.Issues.TestProtos.DeprecatedEnum> _repeated_enumArray_codec
+        = pb::FieldCodec.ForEnum(50, x => (int) x, x => (global::UnitTest.Issues.TestProtos.DeprecatedEnum) x);
+    private readonly pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum> enumArray_ = new pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum>();
+    [global::System.ObsoleteAttribute()]
+    public pbc::RepeatedField<global::UnitTest.Issues.TestProtos.DeprecatedEnum> EnumArray {
+      get { return enumArray_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as DeprecatedFieldsMessage);
+    }
+
+    public bool Equals(DeprecatedFieldsMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (PrimitiveValue != other.PrimitiveValue) return false;
+      if(!primitiveArray_.Equals(other.primitiveArray_)) return false;
+      if (!object.Equals(MessageValue, other.MessageValue)) return false;
+      if(!messageArray_.Equals(other.messageArray_)) return false;
+      if (EnumValue != other.EnumValue) return false;
+      if(!enumArray_.Equals(other.enumArray_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (PrimitiveValue != 0) hash ^= PrimitiveValue.GetHashCode();
+      hash ^= primitiveArray_.GetHashCode();
+      if (messageValue_ != null) hash ^= MessageValue.GetHashCode();
+      hash ^= messageArray_.GetHashCode();
+      if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) hash ^= EnumValue.GetHashCode();
+      hash ^= enumArray_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (PrimitiveValue != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(PrimitiveValue);
+      }
+      primitiveArray_.WriteTo(output, _repeated_primitiveArray_codec);
+      if (messageValue_ != null) {
+        output.WriteRawTag(26);
+        output.WriteMessage(MessageValue);
+      }
+      messageArray_.WriteTo(output, _repeated_messageArray_codec);
+      if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) {
+        output.WriteRawTag(40);
+        output.WriteEnum((int) EnumValue);
+      }
+      enumArray_.WriteTo(output, _repeated_enumArray_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (PrimitiveValue != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(PrimitiveValue);
+      }
+      size += primitiveArray_.CalculateSize(_repeated_primitiveArray_codec);
+      if (messageValue_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(MessageValue);
+      }
+      size += messageArray_.CalculateSize(_repeated_messageArray_codec);
+      if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) EnumValue);
+      }
+      size += enumArray_.CalculateSize(_repeated_enumArray_codec);
+      return size;
+    }
+
+    public void MergeFrom(DeprecatedFieldsMessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.PrimitiveValue != 0) {
+        PrimitiveValue = other.PrimitiveValue;
+      }
+      primitiveArray_.Add(other.primitiveArray_);
+      if (other.messageValue_ != null) {
+        if (messageValue_ == null) {
+          messageValue_ = new global::UnitTest.Issues.TestProtos.DeprecatedChild();
+        }
+        MessageValue.MergeFrom(other.MessageValue);
+      }
+      messageArray_.Add(other.messageArray_);
+      if (other.EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) {
+        EnumValue = other.EnumValue;
+      }
+      enumArray_.Add(other.enumArray_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            PrimitiveValue = input.ReadInt32();
+            break;
+          }
+          case 18:
+          case 16: {
+            primitiveArray_.AddEntriesFrom(input, _repeated_primitiveArray_codec);
+            break;
+          }
+          case 26: {
+            if (messageValue_ == null) {
+              messageValue_ = new global::UnitTest.Issues.TestProtos.DeprecatedChild();
+            }
+            input.ReadMessage(messageValue_);
+            break;
+          }
+          case 34: {
+            messageArray_.AddEntriesFrom(input, _repeated_messageArray_codec);
+            break;
+          }
+          case 40: {
+            enumValue_ = (global::UnitTest.Issues.TestProtos.DeprecatedEnum) input.ReadEnum();
+            break;
+          }
+          case 50:
+          case 48: {
+            enumArray_.AddEntriesFrom(input, _repeated_enumArray_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ItemField : pb::IMessage<ItemField> {
+    private static readonly pb::MessageParser<ItemField> _parser = new pb::MessageParser<ItemField>(() => new ItemField());
+    public static pb::MessageParser<ItemField> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[4]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ItemField() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ItemField(ItemField other) : this() {
+      item_ = other.item_;
+    }
+
+    public ItemField Clone() {
+      return new ItemField(this);
+    }
+
+    public const int ItemFieldNumber = 1;
+    private int item_;
+    public int Item {
+      get { return item_; }
+      set {
+        item_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ItemField);
+    }
+
+    public bool Equals(ItemField other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Item != other.Item) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Item != 0) hash ^= Item.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Item != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Item);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Item != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Item);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ItemField other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Item != 0) {
+        Item = other.Item;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Item = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ReservedNames : pb::IMessage<ReservedNames> {
+    private static readonly pb::MessageParser<ReservedNames> _parser = new pb::MessageParser<ReservedNames>(() => new ReservedNames());
+    public static pb::MessageParser<ReservedNames> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[5]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ReservedNames() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ReservedNames(ReservedNames other) : this() {
+      types_ = other.types_;
+      descriptor_ = other.descriptor_;
+    }
+
+    public ReservedNames Clone() {
+      return new ReservedNames(this);
+    }
+
+    public const int Types_FieldNumber = 1;
+    private int types_;
+    public int Types_ {
+      get { return types_; }
+      set {
+        types_ = value;
+      }
+    }
+
+    public const int Descriptor_FieldNumber = 2;
+    private int descriptor_;
+    public int Descriptor_ {
+      get { return descriptor_; }
+      set {
+        descriptor_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ReservedNames);
+    }
+
+    public bool Equals(ReservedNames other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Types_ != other.Types_) return false;
+      if (Descriptor_ != other.Descriptor_) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Types_ != 0) hash ^= Types_.GetHashCode();
+      if (Descriptor_ != 0) hash ^= Descriptor_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Types_ != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Types_);
+      }
+      if (Descriptor_ != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Descriptor_);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Types_ != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Types_);
+      }
+      if (Descriptor_ != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Descriptor_);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ReservedNames other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Types_ != 0) {
+        Types_ = other.Types_;
+      }
+      if (other.Descriptor_ != 0) {
+        Descriptor_ = other.Descriptor_;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Types_ = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            Descriptor_ = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class SomeNestedType : pb::IMessage<SomeNestedType> {
+        private static readonly pb::MessageParser<SomeNestedType> _parser = new pb::MessageParser<SomeNestedType>(() => new SomeNestedType());
+        public static pb::MessageParser<SomeNestedType> Parser { get { return _parser; } }
+
+        public static pbr::MessageDescriptor Descriptor {
+          get { return global::UnitTest.Issues.TestProtos.ReservedNames.Descriptor.NestedTypes[0]; }
+        }
+
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
+        }
+
+        public SomeNestedType() {
+          OnConstruction();
+        }
+
+        partial void OnConstruction();
+
+        public SomeNestedType(SomeNestedType other) : this() {
+        }
+
+        public SomeNestedType Clone() {
+          return new SomeNestedType(this);
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as SomeNestedType);
+        }
+
+        public bool Equals(SomeNestedType other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          return hash;
+        }
+
+        public override string ToString() {
+          return pb::JsonFormatter.Default.Format(this);
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          return size;
+        }
+
+        public void MergeFrom(SomeNestedType other) {
+          if (other == null) {
+            return;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                input.SkipLastField();
+                break;
+            }
+          }
+        }
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestJsonFieldOrdering : pb::IMessage<TestJsonFieldOrdering> {
+    private static readonly pb::MessageParser<TestJsonFieldOrdering> _parser = new pb::MessageParser<TestJsonFieldOrdering>(() => new TestJsonFieldOrdering());
+    public static pb::MessageParser<TestJsonFieldOrdering> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::UnitTest.Issues.TestProtos.UnittestIssues.Descriptor.MessageTypes[6]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestJsonFieldOrdering() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestJsonFieldOrdering(TestJsonFieldOrdering other) : this() {
+      plainInt32_ = other.plainInt32_;
+      plainString_ = other.plainString_;
+      switch (other.O1Case) {
+        case O1OneofCase.O1String:
+          O1String = other.O1String;
+          break;
+        case O1OneofCase.O1Int32:
+          O1Int32 = other.O1Int32;
+          break;
+      }
+
+      switch (other.O2Case) {
+        case O2OneofCase.O2Int32:
+          O2Int32 = other.O2Int32;
+          break;
+        case O2OneofCase.O2String:
+          O2String = other.O2String;
+          break;
+      }
+
+    }
+
+    public TestJsonFieldOrdering Clone() {
+      return new TestJsonFieldOrdering(this);
+    }
+
+    public const int PlainInt32FieldNumber = 4;
+    private int plainInt32_;
+    public int PlainInt32 {
+      get { return plainInt32_; }
+      set {
+        plainInt32_ = value;
+      }
+    }
+
+    public const int O1StringFieldNumber = 2;
+    public string O1String {
+      get { return o1Case_ == O1OneofCase.O1String ? (string) o1_ : ""; }
+      set {
+        o1_ = pb::Preconditions.CheckNotNull(value, "value");
+        o1Case_ = O1OneofCase.O1String;
+      }
+    }
+
+    public const int O1Int32FieldNumber = 5;
+    public int O1Int32 {
+      get { return o1Case_ == O1OneofCase.O1Int32 ? (int) o1_ : 0; }
+      set {
+        o1_ = value;
+        o1Case_ = O1OneofCase.O1Int32;
+      }
+    }
+
+    public const int PlainStringFieldNumber = 1;
+    private string plainString_ = "";
+    public string PlainString {
+      get { return plainString_; }
+      set {
+        plainString_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public const int O2Int32FieldNumber = 6;
+    public int O2Int32 {
+      get { return o2Case_ == O2OneofCase.O2Int32 ? (int) o2_ : 0; }
+      set {
+        o2_ = value;
+        o2Case_ = O2OneofCase.O2Int32;
+      }
+    }
+
+    public const int O2StringFieldNumber = 3;
+    public string O2String {
+      get { return o2Case_ == O2OneofCase.O2String ? (string) o2_ : ""; }
+      set {
+        o2_ = pb::Preconditions.CheckNotNull(value, "value");
+        o2Case_ = O2OneofCase.O2String;
+      }
+    }
+
+    private object o1_;
+    public enum O1OneofCase {
+      None = 0,
+      O1String = 2,
+      O1Int32 = 5,
+    }
+    private O1OneofCase o1Case_ = O1OneofCase.None;
+    public O1OneofCase O1Case {
+      get { return o1Case_; }
+    }
+
+    public void ClearO1() {
+      o1Case_ = O1OneofCase.None;
+      o1_ = null;
+    }
+
+    private object o2_;
+    public enum O2OneofCase {
+      None = 0,
+      O2Int32 = 6,
+      O2String = 3,
+    }
+    private O2OneofCase o2Case_ = O2OneofCase.None;
+    public O2OneofCase O2Case {
+      get { return o2Case_; }
+    }
+
+    public void ClearO2() {
+      o2Case_ = O2OneofCase.None;
+      o2_ = null;
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestJsonFieldOrdering);
+    }
+
+    public bool Equals(TestJsonFieldOrdering other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (PlainInt32 != other.PlainInt32) return false;
+      if (O1String != other.O1String) return false;
+      if (O1Int32 != other.O1Int32) return false;
+      if (PlainString != other.PlainString) return false;
+      if (O2Int32 != other.O2Int32) return false;
+      if (O2String != other.O2String) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (PlainInt32 != 0) hash ^= PlainInt32.GetHashCode();
+      if (o1Case_ == O1OneofCase.O1String) hash ^= O1String.GetHashCode();
+      if (o1Case_ == O1OneofCase.O1Int32) hash ^= O1Int32.GetHashCode();
+      if (PlainString.Length != 0) hash ^= PlainString.GetHashCode();
+      if (o2Case_ == O2OneofCase.O2Int32) hash ^= O2Int32.GetHashCode();
+      if (o2Case_ == O2OneofCase.O2String) hash ^= O2String.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (PlainString.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(PlainString);
+      }
+      if (o1Case_ == O1OneofCase.O1String) {
+        output.WriteRawTag(18);
+        output.WriteString(O1String);
+      }
+      if (o2Case_ == O2OneofCase.O2String) {
+        output.WriteRawTag(26);
+        output.WriteString(O2String);
+      }
+      if (PlainInt32 != 0) {
+        output.WriteRawTag(32);
+        output.WriteInt32(PlainInt32);
+      }
+      if (o1Case_ == O1OneofCase.O1Int32) {
+        output.WriteRawTag(40);
+        output.WriteInt32(O1Int32);
+      }
+      if (o2Case_ == O2OneofCase.O2Int32) {
+        output.WriteRawTag(48);
+        output.WriteInt32(O2Int32);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (PlainInt32 != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(PlainInt32);
+      }
+      if (o1Case_ == O1OneofCase.O1String) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(O1String);
+      }
+      if (o1Case_ == O1OneofCase.O1Int32) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(O1Int32);
+      }
+      if (PlainString.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(PlainString);
+      }
+      if (o2Case_ == O2OneofCase.O2Int32) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(O2Int32);
+      }
+      if (o2Case_ == O2OneofCase.O2String) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(O2String);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestJsonFieldOrdering other) {
+      if (other == null) {
+        return;
+      }
+      if (other.PlainInt32 != 0) {
+        PlainInt32 = other.PlainInt32;
+      }
+      if (other.PlainString.Length != 0) {
+        PlainString = other.PlainString;
+      }
+      switch (other.O1Case) {
+        case O1OneofCase.O1String:
+          O1String = other.O1String;
+          break;
+        case O1OneofCase.O1Int32:
+          O1Int32 = other.O1Int32;
+          break;
+      }
+
+      switch (other.O2Case) {
+        case O2OneofCase.O2Int32:
+          O2Int32 = other.O2Int32;
+          break;
+        case O2OneofCase.O2String:
+          O2String = other.O2String;
+          break;
+      }
+
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            PlainString = input.ReadString();
+            break;
+          }
+          case 18: {
+            O1String = input.ReadString();
+            break;
+          }
+          case 26: {
+            O2String = input.ReadString();
+            break;
+          }
+          case 32: {
+            PlainInt32 = input.ReadInt32();
+            break;
+          }
+          case 40: {
+            O1Int32 = input.ReadInt32();
+            break;
+          }
+          case 48: {
+            O2Int32 = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code

+ 5830 - 0
csharp/src/Google.Protobuf.Test/TestProtos/UnittestProto3.cs

@@ -0,0 +1,5830 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/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 pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.TestProtos {
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class UnittestProto3 {
+
+    #region Descriptor
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static UnittestProto3() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "CiVnb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfcHJvdG8zLnByb3RvEhFwcm90", 
+            "b2J1Zl91bml0dGVzdBosZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0X2ltcG9y", 
+            "dF9wcm90bzMucHJvdG8i8A8KDFRlc3RBbGxUeXBlcxIUCgxzaW5nbGVfaW50", 
+            "MzIYASABKAUSFAoMc2luZ2xlX2ludDY0GAIgASgDEhUKDXNpbmdsZV91aW50", 
+            "MzIYAyABKA0SFQoNc2luZ2xlX3VpbnQ2NBgEIAEoBBIVCg1zaW5nbGVfc2lu", 
+            "dDMyGAUgASgREhUKDXNpbmdsZV9zaW50NjQYBiABKBISFgoOc2luZ2xlX2Zp", 
+            "eGVkMzIYByABKAcSFgoOc2luZ2xlX2ZpeGVkNjQYCCABKAYSFwoPc2luZ2xl", 
+            "X3NmaXhlZDMyGAkgASgPEhcKD3NpbmdsZV9zZml4ZWQ2NBgKIAEoEBIUCgxz", 
+            "aW5nbGVfZmxvYXQYCyABKAISFQoNc2luZ2xlX2RvdWJsZRgMIAEoARITCgtz", 
+            "aW5nbGVfYm9vbBgNIAEoCBIVCg1zaW5nbGVfc3RyaW5nGA4gASgJEhQKDHNp", 
+            "bmdsZV9ieXRlcxgPIAEoDBJMChVzaW5nbGVfbmVzdGVkX21lc3NhZ2UYEiAB", 
+            "KAsyLS5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXMuTmVzdGVkTWVz", 
+            "c2FnZRJBChZzaW5nbGVfZm9yZWlnbl9tZXNzYWdlGBMgASgLMiEucHJvdG9i", 
+            "dWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2USRgoVc2luZ2xlX2ltcG9ydF9t", 
+            "ZXNzYWdlGBQgASgLMicucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9y", 
+            "dE1lc3NhZ2USRgoSc2luZ2xlX25lc3RlZF9lbnVtGBUgASgOMioucHJvdG9i", 
+            "dWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzLk5lc3RlZEVudW0SOwoTc2luZ2xl", 
+            "X2ZvcmVpZ25fZW51bRgWIAEoDjIeLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVp", 
+            "Z25FbnVtEkAKEnNpbmdsZV9pbXBvcnRfZW51bRgXIAEoDjIkLnByb3RvYnVm", 
+            "X3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtElMKHHNpbmdsZV9wdWJsaWNf", 
+            "aW1wb3J0X21lc3NhZ2UYGiABKAsyLS5wcm90b2J1Zl91bml0dGVzdF9pbXBv", 
+            "cnQuUHVibGljSW1wb3J0TWVzc2FnZRIWCg5yZXBlYXRlZF9pbnQzMhgfIAMo", 
+            "BRIWCg5yZXBlYXRlZF9pbnQ2NBggIAMoAxIXCg9yZXBlYXRlZF91aW50MzIY", 
+            "ISADKA0SFwoPcmVwZWF0ZWRfdWludDY0GCIgAygEEhcKD3JlcGVhdGVkX3Np", 
+            "bnQzMhgjIAMoERIXCg9yZXBlYXRlZF9zaW50NjQYJCADKBISGAoQcmVwZWF0", 
+            "ZWRfZml4ZWQzMhglIAMoBxIYChByZXBlYXRlZF9maXhlZDY0GCYgAygGEhkK", 
+            "EXJlcGVhdGVkX3NmaXhlZDMyGCcgAygPEhkKEXJlcGVhdGVkX3NmaXhlZDY0", 
+            "GCggAygQEhYKDnJlcGVhdGVkX2Zsb2F0GCkgAygCEhcKD3JlcGVhdGVkX2Rv", 
+            "dWJsZRgqIAMoARIVCg1yZXBlYXRlZF9ib29sGCsgAygIEhcKD3JlcGVhdGVk", 
+            "X3N0cmluZxgsIAMoCRIWCg5yZXBlYXRlZF9ieXRlcxgtIAMoDBJOChdyZXBl", 
+            "YXRlZF9uZXN0ZWRfbWVzc2FnZRgwIAMoCzItLnByb3RvYnVmX3VuaXR0ZXN0", 
+            "LlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlEkMKGHJlcGVhdGVkX2ZvcmVp", 
+            "Z25fbWVzc2FnZRgxIAMoCzIhLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25N", 
+            "ZXNzYWdlEkgKF3JlcGVhdGVkX2ltcG9ydF9tZXNzYWdlGDIgAygLMicucHJv", 
+            "dG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2USSAoUcmVwZWF0", 
+            "ZWRfbmVzdGVkX2VudW0YMyADKA4yKi5wcm90b2J1Zl91bml0dGVzdC5UZXN0", 
+            "QWxsVHlwZXMuTmVzdGVkRW51bRI9ChVyZXBlYXRlZF9mb3JlaWduX2VudW0Y", 
+            "NCADKA4yHi5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bRJCChRyZXBl", 
+            "YXRlZF9pbXBvcnRfZW51bRg1IAMoDjIkLnByb3RvYnVmX3VuaXR0ZXN0X2lt", 
+            "cG9ydC5JbXBvcnRFbnVtElUKHnJlcGVhdGVkX3B1YmxpY19pbXBvcnRfbWVz", 
+            "c2FnZRg2IAMoCzItLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5QdWJsaWNJ", 
+            "bXBvcnRNZXNzYWdlEhYKDG9uZW9mX3VpbnQzMhhvIAEoDUgAEk0KFG9uZW9m", 
+            "X25lc3RlZF9tZXNzYWdlGHAgASgLMi0ucHJvdG9idWZfdW5pdHRlc3QuVGVz", 
+            "dEFsbFR5cGVzLk5lc3RlZE1lc3NhZ2VIABIWCgxvbmVvZl9zdHJpbmcYcSAB", 
+            "KAlIABIVCgtvbmVvZl9ieXRlcxhyIAEoDEgAGhsKDU5lc3RlZE1lc3NhZ2US", 
+            "CgoCYmIYASABKAUiVgoKTmVzdGVkRW51bRIbChdORVNURURfRU5VTV9VTlNQ", 
+            "RUNJRklFRBAAEgcKA0ZPTxABEgcKA0JBUhACEgcKA0JBWhADEhAKA05FRxD/", 
+            "//////////8BQg0KC29uZW9mX2ZpZWxkIrsBChJOZXN0ZWRUZXN0QWxsVHlw", 
+            "ZXMSNAoFY2hpbGQYASABKAsyJS5wcm90b2J1Zl91bml0dGVzdC5OZXN0ZWRU", 
+            "ZXN0QWxsVHlwZXMSMAoHcGF5bG9hZBgCIAEoCzIfLnByb3RvYnVmX3VuaXR0", 
+            "ZXN0LlRlc3RBbGxUeXBlcxI9Cg5yZXBlYXRlZF9jaGlsZBgDIAMoCzIlLnBy", 
+            "b3RvYnVmX3VuaXR0ZXN0Lk5lc3RlZFRlc3RBbGxUeXBlcyI0ChRUZXN0RGVw", 
+            "cmVjYXRlZEZpZWxkcxIcChBkZXByZWNhdGVkX2ludDMyGAEgASgFQgIYASIb", 
+            "Cg5Gb3JlaWduTWVzc2FnZRIJCgFjGAEgASgFIjAKElRlc3RSZXNlcnZlZEZp", 
+            "ZWxkc0oECAIQA0oECA8QEEoECAkQDFIDYmFyUgNiYXoiWgoRVGVzdEZvcmVp", 
+            "Z25OZXN0ZWQSRQoOZm9yZWlnbl9uZXN0ZWQYASABKAsyLS5wcm90b2J1Zl91", 
+            "bml0dGVzdC5UZXN0QWxsVHlwZXMuTmVzdGVkTWVzc2FnZSI0ChhUZXN0UmVh", 
+            "bGx5TGFyZ2VUYWdOdW1iZXISCQoBYRgBIAEoBRINCgJiYhj///9/IAEoBSJV", 
+            "ChRUZXN0UmVjdXJzaXZlTWVzc2FnZRIyCgFhGAEgASgLMicucHJvdG9idWZf", 
+            "dW5pdHRlc3QuVGVzdFJlY3Vyc2l2ZU1lc3NhZ2USCQoBaRgCIAEoBSJLChRU", 
+            "ZXN0TXV0dWFsUmVjdXJzaW9uQRIzCgJiYhgBIAEoCzInLnByb3RvYnVmX3Vu", 
+            "aXR0ZXN0LlRlc3RNdXR1YWxSZWN1cnNpb25CImIKFFRlc3RNdXR1YWxSZWN1", 
+            "cnNpb25CEjIKAWEYASABKAsyJy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TXV0", 
+            "dWFsUmVjdXJzaW9uQRIWCg5vcHRpb25hbF9pbnQzMhgCIAEoBSLrAgoXVGVz", 
+            "dENhbWVsQ2FzZUZpZWxkTmFtZXMSFgoOUHJpbWl0aXZlRmllbGQYASABKAUS", 
+            "EwoLU3RyaW5nRmllbGQYAiABKAkSMQoJRW51bUZpZWxkGAMgASgOMh4ucHJv", 
+            "dG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW0SNwoMTWVzc2FnZUZpZWxkGAQg", 
+            "ASgLMiEucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2USHgoWUmVw", 
+            "ZWF0ZWRQcmltaXRpdmVGaWVsZBgHIAMoBRIbChNSZXBlYXRlZFN0cmluZ0Zp", 
+            "ZWxkGAggAygJEjkKEVJlcGVhdGVkRW51bUZpZWxkGAkgAygOMh4ucHJvdG9i", 
+            "dWZfdW5pdHRlc3QuRm9yZWlnbkVudW0SPwoUUmVwZWF0ZWRNZXNzYWdlRmll", 
+            "bGQYCiADKAsyIS5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZSLH", 
+            "AQoSVGVzdEZpZWxkT3JkZXJpbmdzEhEKCW15X3N0cmluZxgLIAEoCRIOCgZt", 
+            "eV9pbnQYASABKAMSEAoIbXlfZmxvYXQYZSABKAISUwoVc2luZ2xlX25lc3Rl", 
+            "ZF9tZXNzYWdlGMgBIAEoCzIzLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RGaWVs", 
+            "ZE9yZGVyaW5ncy5OZXN0ZWRNZXNzYWdlGicKDU5lc3RlZE1lc3NhZ2USCgoC", 
+            "b28YAiABKAMSCgoCYmIYASABKAUiSwoRU3BhcnNlRW51bU1lc3NhZ2USNgoL", 
+            "c3BhcnNlX2VudW0YASABKA4yIS5wcm90b2J1Zl91bml0dGVzdC5UZXN0U3Bh", 
+            "cnNlRW51bSIZCglPbmVTdHJpbmcSDAoEZGF0YRgBIAEoCSIaCgpNb3JlU3Ry", 
+            "aW5nEgwKBGRhdGEYASADKAkiGAoIT25lQnl0ZXMSDAoEZGF0YRgBIAEoDCIZ", 
+            "CglNb3JlQnl0ZXMSDAoEZGF0YRgBIAEoDCIcCgxJbnQzMk1lc3NhZ2USDAoE", 
+            "ZGF0YRgBIAEoBSIdCg1VaW50MzJNZXNzYWdlEgwKBGRhdGEYASABKA0iHAoM", 
+            "SW50NjRNZXNzYWdlEgwKBGRhdGEYASABKAMiHQoNVWludDY0TWVzc2FnZRIM", 
+            "CgRkYXRhGAEgASgEIhsKC0Jvb2xNZXNzYWdlEgwKBGRhdGEYASABKAgicwoJ", 
+            "VGVzdE9uZW9mEhEKB2Zvb19pbnQYASABKAVIABIUCgpmb29fc3RyaW5nGAIg", 
+            "ASgJSAASNgoLZm9vX21lc3NhZ2UYAyABKAsyHy5wcm90b2J1Zl91bml0dGVz", 
+            "dC5UZXN0QWxsVHlwZXNIAEIFCgNmb28iqgMKD1Rlc3RQYWNrZWRUeXBlcxIY", 
+            "CgxwYWNrZWRfaW50MzIYWiADKAVCAhABEhgKDHBhY2tlZF9pbnQ2NBhbIAMo", 
+            "A0ICEAESGQoNcGFja2VkX3VpbnQzMhhcIAMoDUICEAESGQoNcGFja2VkX3Vp", 
+            "bnQ2NBhdIAMoBEICEAESGQoNcGFja2VkX3NpbnQzMhheIAMoEUICEAESGQoN", 
+            "cGFja2VkX3NpbnQ2NBhfIAMoEkICEAESGgoOcGFja2VkX2ZpeGVkMzIYYCAD", 
+            "KAdCAhABEhoKDnBhY2tlZF9maXhlZDY0GGEgAygGQgIQARIbCg9wYWNrZWRf", 
+            "c2ZpeGVkMzIYYiADKA9CAhABEhsKD3BhY2tlZF9zZml4ZWQ2NBhjIAMoEEIC", 
+            "EAESGAoMcGFja2VkX2Zsb2F0GGQgAygCQgIQARIZCg1wYWNrZWRfZG91Ymxl", 
+            "GGUgAygBQgIQARIXCgtwYWNrZWRfYm9vbBhmIAMoCEICEAESNwoLcGFja2Vk", 
+            "X2VudW0YZyADKA4yHi5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bUIC", 
+            "EAEiyAMKEVRlc3RVbnBhY2tlZFR5cGVzEhoKDnVucGFja2VkX2ludDMyGFog", 
+            "AygFQgIQABIaCg51bnBhY2tlZF9pbnQ2NBhbIAMoA0ICEAASGwoPdW5wYWNr", 
+            "ZWRfdWludDMyGFwgAygNQgIQABIbCg91bnBhY2tlZF91aW50NjQYXSADKARC", 
+            "AhAAEhsKD3VucGFja2VkX3NpbnQzMhheIAMoEUICEAASGwoPdW5wYWNrZWRf", 
+            "c2ludDY0GF8gAygSQgIQABIcChB1bnBhY2tlZF9maXhlZDMyGGAgAygHQgIQ", 
+            "ABIcChB1bnBhY2tlZF9maXhlZDY0GGEgAygGQgIQABIdChF1bnBhY2tlZF9z", 
+            "Zml4ZWQzMhhiIAMoD0ICEAASHQoRdW5wYWNrZWRfc2ZpeGVkNjQYYyADKBBC", 
+            "AhAAEhoKDnVucGFja2VkX2Zsb2F0GGQgAygCQgIQABIbCg91bnBhY2tlZF9k", 
+            "b3VibGUYZSADKAFCAhAAEhkKDXVucGFja2VkX2Jvb2wYZiADKAhCAhAAEjkK", 
+            "DXVucGFja2VkX2VudW0YZyADKA4yHi5wcm90b2J1Zl91bml0dGVzdC5Gb3Jl", 
+            "aWduRW51bUICEAAiwAEKI1Rlc3RSZXBlYXRlZFNjYWxhckRpZmZlcmVudFRh", 
+            "Z1NpemVzEhgKEHJlcGVhdGVkX2ZpeGVkMzIYDCADKAcSFgoOcmVwZWF0ZWRf", 
+            "aW50MzIYDSADKAUSGQoQcmVwZWF0ZWRfZml4ZWQ2NBj+DyADKAYSFwoOcmVw", 
+            "ZWF0ZWRfaW50NjQY/w8gAygDEhgKDnJlcGVhdGVkX2Zsb2F0GP7/DyADKAIS", 
+            "GQoPcmVwZWF0ZWRfdWludDY0GP//DyADKAQiKAobVGVzdENvbW1lbnRJbmpl", 
+            "Y3Rpb25NZXNzYWdlEgkKAWEYASABKAkiDAoKRm9vUmVxdWVzdCINCgtGb29S", 
+            "ZXNwb25zZSISChBGb29DbGllbnRNZXNzYWdlIhIKEEZvb1NlcnZlck1lc3Nh", 
+            "Z2UiDAoKQmFyUmVxdWVzdCINCgtCYXJSZXNwb25zZSpZCgtGb3JlaWduRW51", 
+            "bRIXChNGT1JFSUdOX1VOU1BFQ0lGSUVEEAASDwoLRk9SRUlHTl9GT08QBBIP", 
+            "CgtGT1JFSUdOX0JBUhAFEg8KC0ZPUkVJR05fQkFaEAYqdQoUVGVzdEVudW1X", 
+            "aXRoRHVwVmFsdWUSKAokVEVTVF9FTlVNX1dJVEhfRFVQX1ZBTFVFX1VOU1BF", 
+            "Q0lGSUVEEAASCAoERk9PMRABEggKBEJBUjEQAhIHCgNCQVoQAxIICgRGT08y", 
+            "EAESCAoEQkFSMhACGgIQASqdAQoOVGVzdFNwYXJzZUVudW0SIAocVEVTVF9T", 
+            "UEFSU0VfRU5VTV9VTlNQRUNJRklFRBAAEgwKCFNQQVJTRV9BEHsSDgoIU1BB", 
+            "UlNFX0IQpucDEg8KCFNQQVJTRV9DELKxgAYSFQoIU1BBUlNFX0QQ8f//////", 
+            "////ARIVCghTUEFSU0VfRRC03vz///////8BEgwKCFNQQVJTRV9HEAIymQEK", 
+            "C1Rlc3RTZXJ2aWNlEkQKA0ZvbxIdLnByb3RvYnVmX3VuaXR0ZXN0LkZvb1Jl", 
+            "cXVlc3QaHi5wcm90b2J1Zl91bml0dGVzdC5Gb29SZXNwb25zZRJECgNCYXIS", 
+            "HS5wcm90b2J1Zl91bml0dGVzdC5CYXJSZXF1ZXN0Gh4ucHJvdG9idWZfdW5p", 
+            "dHRlc3QuQmFyUmVzcG9uc2VCOkINVW5pdHRlc3RQcm90b0gBgAEBiAEBkAEB", 
+            "+AEBqgIaR29vZ2xlLlByb3RvYnVmLlRlc3RQcm90b3NiBnByb3RvMw=="));
+      descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+          new pbr::FileDescriptor[] { global::Google.Protobuf.TestProtos.UnittestImportProto3.Descriptor, },
+          new pbr::GeneratedCodeInfo(new[] {typeof(global::Google.Protobuf.TestProtos.ForeignEnum), typeof(global::Google.Protobuf.TestProtos.TestEnumWithDupValue), typeof(global::Google.Protobuf.TestProtos.TestSparseEnum), }, new pbr::GeneratedCodeInfo[] {
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestAllTypes), new[]{ "SingleInt32", "SingleInt64", "SingleUint32", "SingleUint64", "SingleSint32", "SingleSint64", "SingleFixed32", "SingleFixed64", "SingleSfixed32", "SingleSfixed64", "SingleFloat", "SingleDouble", "SingleBool", "SingleString", "SingleBytes", "SingleNestedMessage", "SingleForeignMessage", "SingleImportMessage", "SingleNestedEnum", "SingleForeignEnum", "SingleImportEnum", "SinglePublicImportMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedImportMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedImportEnum", "RepeatedPublicImportMessage", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes" }, new[]{ "OneofField" }, new[]{ typeof(global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) }, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage), new[]{ "Bb" }, null, null, null)}),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.NestedTestAllTypes), new[]{ "Child", "Payload", "RepeatedChild" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestDeprecatedFields), new[]{ "DeprecatedInt32" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.ForeignMessage), new[]{ "C" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestReservedFields), null, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestForeignNested), new[]{ "ForeignNested" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestReallyLargeTagNumber), new[]{ "A", "Bb" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestRecursiveMessage), new[]{ "A", "I" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestMutualRecursionA), new[]{ "Bb" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestMutualRecursionB), new[]{ "A", "OptionalInt32" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestCamelCaseFieldNames), new[]{ "PrimitiveField", "StringField", "EnumField", "MessageField", "RepeatedPrimitiveField", "RepeatedStringField", "RepeatedEnumField", "RepeatedMessageField" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestFieldOrderings), new[]{ "MyString", "MyInt", "MyFloat", "SingleNestedMessage" }, null, null, new pbr::GeneratedCodeInfo[] { new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage), new[]{ "Oo", "Bb" }, null, null, null)}),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.SparseEnumMessage), new[]{ "SparseEnum" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.OneString), new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.MoreString), new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.OneBytes), new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.MoreBytes), new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.Int32Message), new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.Uint32Message), new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.Int64Message), new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.Uint64Message), new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.BoolMessage), new[]{ "Data" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestOneof), new[]{ "FooInt", "FooString", "FooMessage" }, new[]{ "Foo" }, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestPackedTypes), new[]{ "PackedInt32", "PackedInt64", "PackedUint32", "PackedUint64", "PackedSint32", "PackedSint64", "PackedFixed32", "PackedFixed64", "PackedSfixed32", "PackedSfixed64", "PackedFloat", "PackedDouble", "PackedBool", "PackedEnum" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestUnpackedTypes), new[]{ "UnpackedInt32", "UnpackedInt64", "UnpackedUint32", "UnpackedUint64", "UnpackedSint32", "UnpackedSint64", "UnpackedFixed32", "UnpackedFixed64", "UnpackedSfixed32", "UnpackedSfixed64", "UnpackedFloat", "UnpackedDouble", "UnpackedBool", "UnpackedEnum" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestRepeatedScalarDifferentTagSizes), new[]{ "RepeatedFixed32", "RepeatedInt32", "RepeatedFixed64", "RepeatedInt64", "RepeatedFloat", "RepeatedUint64" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestCommentInjectionMessage), new[]{ "A" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.FooRequest), null, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.FooResponse), null, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.FooClientMessage), null, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.FooServerMessage), null, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.BarRequest), null, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.BarResponse), null, null, null, null)
+          }));
+    }
+    #endregion
+
+  }
+  #region Enums
+  public enum ForeignEnum {
+    FOREIGN_UNSPECIFIED = 0,
+    FOREIGN_FOO = 4,
+    FOREIGN_BAR = 5,
+    FOREIGN_BAZ = 6,
+  }
+
+  public enum TestEnumWithDupValue {
+    TEST_ENUM_WITH_DUP_VALUE_UNSPECIFIED = 0,
+    FOO1 = 1,
+    BAR1 = 2,
+    BAZ = 3,
+    FOO2 = 1,
+    BAR2 = 2,
+  }
+
+  public enum TestSparseEnum {
+    TEST_SPARSE_ENUM_UNSPECIFIED = 0,
+    SPARSE_A = 123,
+    SPARSE_B = 62374,
+    SPARSE_C = 12589234,
+    SPARSE_D = -15,
+    SPARSE_E = -53452,
+    SPARSE_G = 2,
+  }
+
+  #endregion
+
+  #region Messages
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestAllTypes : pb::IMessage<TestAllTypes> {
+    private static readonly pb::MessageParser<TestAllTypes> _parser = new pb::MessageParser<TestAllTypes>(() => new TestAllTypes());
+    public static pb::MessageParser<TestAllTypes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestAllTypes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestAllTypes(TestAllTypes other) : this() {
+      singleInt32_ = other.singleInt32_;
+      singleInt64_ = other.singleInt64_;
+      singleUint32_ = other.singleUint32_;
+      singleUint64_ = other.singleUint64_;
+      singleSint32_ = other.singleSint32_;
+      singleSint64_ = other.singleSint64_;
+      singleFixed32_ = other.singleFixed32_;
+      singleFixed64_ = other.singleFixed64_;
+      singleSfixed32_ = other.singleSfixed32_;
+      singleSfixed64_ = other.singleSfixed64_;
+      singleFloat_ = other.singleFloat_;
+      singleDouble_ = other.singleDouble_;
+      singleBool_ = other.singleBool_;
+      singleString_ = other.singleString_;
+      singleBytes_ = other.singleBytes_;
+      SingleNestedMessage = other.singleNestedMessage_ != null ? other.SingleNestedMessage.Clone() : null;
+      SingleForeignMessage = other.singleForeignMessage_ != null ? other.SingleForeignMessage.Clone() : null;
+      SingleImportMessage = other.singleImportMessage_ != null ? other.SingleImportMessage.Clone() : null;
+      singleNestedEnum_ = other.singleNestedEnum_;
+      singleForeignEnum_ = other.singleForeignEnum_;
+      singleImportEnum_ = other.singleImportEnum_;
+      SinglePublicImportMessage = other.singlePublicImportMessage_ != null ? other.SinglePublicImportMessage.Clone() : null;
+      repeatedInt32_ = other.repeatedInt32_.Clone();
+      repeatedInt64_ = other.repeatedInt64_.Clone();
+      repeatedUint32_ = other.repeatedUint32_.Clone();
+      repeatedUint64_ = other.repeatedUint64_.Clone();
+      repeatedSint32_ = other.repeatedSint32_.Clone();
+      repeatedSint64_ = other.repeatedSint64_.Clone();
+      repeatedFixed32_ = other.repeatedFixed32_.Clone();
+      repeatedFixed64_ = other.repeatedFixed64_.Clone();
+      repeatedSfixed32_ = other.repeatedSfixed32_.Clone();
+      repeatedSfixed64_ = other.repeatedSfixed64_.Clone();
+      repeatedFloat_ = other.repeatedFloat_.Clone();
+      repeatedDouble_ = other.repeatedDouble_.Clone();
+      repeatedBool_ = other.repeatedBool_.Clone();
+      repeatedString_ = other.repeatedString_.Clone();
+      repeatedBytes_ = other.repeatedBytes_.Clone();
+      repeatedNestedMessage_ = other.repeatedNestedMessage_.Clone();
+      repeatedForeignMessage_ = other.repeatedForeignMessage_.Clone();
+      repeatedImportMessage_ = other.repeatedImportMessage_.Clone();
+      repeatedNestedEnum_ = other.repeatedNestedEnum_.Clone();
+      repeatedForeignEnum_ = other.repeatedForeignEnum_.Clone();
+      repeatedImportEnum_ = other.repeatedImportEnum_.Clone();
+      repeatedPublicImportMessage_ = other.repeatedPublicImportMessage_.Clone();
+      switch (other.OneofFieldCase) {
+        case OneofFieldOneofCase.OneofUint32:
+          OneofUint32 = other.OneofUint32;
+          break;
+        case OneofFieldOneofCase.OneofNestedMessage:
+          OneofNestedMessage = other.OneofNestedMessage.Clone();
+          break;
+        case OneofFieldOneofCase.OneofString:
+          OneofString = other.OneofString;
+          break;
+        case OneofFieldOneofCase.OneofBytes:
+          OneofBytes = other.OneofBytes;
+          break;
+      }
+
+    }
+
+    public TestAllTypes Clone() {
+      return new TestAllTypes(this);
+    }
+
+    public const int SingleInt32FieldNumber = 1;
+    private int singleInt32_;
+    public int SingleInt32 {
+      get { return singleInt32_; }
+      set {
+        singleInt32_ = value;
+      }
+    }
+
+    public const int SingleInt64FieldNumber = 2;
+    private long singleInt64_;
+    public long SingleInt64 {
+      get { return singleInt64_; }
+      set {
+        singleInt64_ = value;
+      }
+    }
+
+    public const int SingleUint32FieldNumber = 3;
+    private uint singleUint32_;
+    public uint SingleUint32 {
+      get { return singleUint32_; }
+      set {
+        singleUint32_ = value;
+      }
+    }
+
+    public const int SingleUint64FieldNumber = 4;
+    private ulong singleUint64_;
+    public ulong SingleUint64 {
+      get { return singleUint64_; }
+      set {
+        singleUint64_ = value;
+      }
+    }
+
+    public const int SingleSint32FieldNumber = 5;
+    private int singleSint32_;
+    public int SingleSint32 {
+      get { return singleSint32_; }
+      set {
+        singleSint32_ = value;
+      }
+    }
+
+    public const int SingleSint64FieldNumber = 6;
+    private long singleSint64_;
+    public long SingleSint64 {
+      get { return singleSint64_; }
+      set {
+        singleSint64_ = value;
+      }
+    }
+
+    public const int SingleFixed32FieldNumber = 7;
+    private uint singleFixed32_;
+    public uint SingleFixed32 {
+      get { return singleFixed32_; }
+      set {
+        singleFixed32_ = value;
+      }
+    }
+
+    public const int SingleFixed64FieldNumber = 8;
+    private ulong singleFixed64_;
+    public ulong SingleFixed64 {
+      get { return singleFixed64_; }
+      set {
+        singleFixed64_ = value;
+      }
+    }
+
+    public const int SingleSfixed32FieldNumber = 9;
+    private int singleSfixed32_;
+    public int SingleSfixed32 {
+      get { return singleSfixed32_; }
+      set {
+        singleSfixed32_ = value;
+      }
+    }
+
+    public const int SingleSfixed64FieldNumber = 10;
+    private long singleSfixed64_;
+    public long SingleSfixed64 {
+      get { return singleSfixed64_; }
+      set {
+        singleSfixed64_ = value;
+      }
+    }
+
+    public const int SingleFloatFieldNumber = 11;
+    private float singleFloat_;
+    public float SingleFloat {
+      get { return singleFloat_; }
+      set {
+        singleFloat_ = value;
+      }
+    }
+
+    public const int SingleDoubleFieldNumber = 12;
+    private double singleDouble_;
+    public double SingleDouble {
+      get { return singleDouble_; }
+      set {
+        singleDouble_ = value;
+      }
+    }
+
+    public const int SingleBoolFieldNumber = 13;
+    private bool singleBool_;
+    public bool SingleBool {
+      get { return singleBool_; }
+      set {
+        singleBool_ = value;
+      }
+    }
+
+    public const int SingleStringFieldNumber = 14;
+    private string singleString_ = "";
+    public string SingleString {
+      get { return singleString_; }
+      set {
+        singleString_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public const int SingleBytesFieldNumber = 15;
+    private pb::ByteString singleBytes_ = pb::ByteString.Empty;
+    public pb::ByteString SingleBytes {
+      get { return singleBytes_; }
+      set {
+        singleBytes_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public const int SingleNestedMessageFieldNumber = 18;
+    private global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage singleNestedMessage_;
+    public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage SingleNestedMessage {
+      get { return singleNestedMessage_; }
+      set {
+        singleNestedMessage_ = value;
+      }
+    }
+
+    public const int SingleForeignMessageFieldNumber = 19;
+    private global::Google.Protobuf.TestProtos.ForeignMessage singleForeignMessage_;
+    public global::Google.Protobuf.TestProtos.ForeignMessage SingleForeignMessage {
+      get { return singleForeignMessage_; }
+      set {
+        singleForeignMessage_ = value;
+      }
+    }
+
+    public const int SingleImportMessageFieldNumber = 20;
+    private global::Google.Protobuf.TestProtos.ImportMessage singleImportMessage_;
+    public global::Google.Protobuf.TestProtos.ImportMessage SingleImportMessage {
+      get { return singleImportMessage_; }
+      set {
+        singleImportMessage_ = value;
+      }
+    }
+
+    public const int SingleNestedEnumFieldNumber = 21;
+    private global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum singleNestedEnum_ = global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.NESTED_ENUM_UNSPECIFIED;
+    public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum SingleNestedEnum {
+      get { return singleNestedEnum_; }
+      set {
+        singleNestedEnum_ = value;
+      }
+    }
+
+    public const int SingleForeignEnumFieldNumber = 22;
+    private global::Google.Protobuf.TestProtos.ForeignEnum singleForeignEnum_ = global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED;
+    public global::Google.Protobuf.TestProtos.ForeignEnum SingleForeignEnum {
+      get { return singleForeignEnum_; }
+      set {
+        singleForeignEnum_ = value;
+      }
+    }
+
+    public const int SingleImportEnumFieldNumber = 23;
+    private global::Google.Protobuf.TestProtos.ImportEnum singleImportEnum_ = global::Google.Protobuf.TestProtos.ImportEnum.IMPORT_ENUM_UNSPECIFIED;
+    public global::Google.Protobuf.TestProtos.ImportEnum SingleImportEnum {
+      get { return singleImportEnum_; }
+      set {
+        singleImportEnum_ = value;
+      }
+    }
+
+    public const int SinglePublicImportMessageFieldNumber = 26;
+    private global::Google.Protobuf.TestProtos.PublicImportMessage singlePublicImportMessage_;
+    public global::Google.Protobuf.TestProtos.PublicImportMessage SinglePublicImportMessage {
+      get { return singlePublicImportMessage_; }
+      set {
+        singlePublicImportMessage_ = value;
+      }
+    }
+
+    public const int RepeatedInt32FieldNumber = 31;
+    private static readonly pb::FieldCodec<int> _repeated_repeatedInt32_codec
+        = pb::FieldCodec.ForInt32(250);
+    private readonly pbc::RepeatedField<int> repeatedInt32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> RepeatedInt32 {
+      get { return repeatedInt32_; }
+    }
+
+    public const int RepeatedInt64FieldNumber = 32;
+    private static readonly pb::FieldCodec<long> _repeated_repeatedInt64_codec
+        = pb::FieldCodec.ForInt64(258);
+    private readonly pbc::RepeatedField<long> repeatedInt64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> RepeatedInt64 {
+      get { return repeatedInt64_; }
+    }
+
+    public const int RepeatedUint32FieldNumber = 33;
+    private static readonly pb::FieldCodec<uint> _repeated_repeatedUint32_codec
+        = pb::FieldCodec.ForUInt32(266);
+    private readonly pbc::RepeatedField<uint> repeatedUint32_ = new pbc::RepeatedField<uint>();
+    public pbc::RepeatedField<uint> RepeatedUint32 {
+      get { return repeatedUint32_; }
+    }
+
+    public const int RepeatedUint64FieldNumber = 34;
+    private static readonly pb::FieldCodec<ulong> _repeated_repeatedUint64_codec
+        = pb::FieldCodec.ForUInt64(274);
+    private readonly pbc::RepeatedField<ulong> repeatedUint64_ = new pbc::RepeatedField<ulong>();
+    public pbc::RepeatedField<ulong> RepeatedUint64 {
+      get { return repeatedUint64_; }
+    }
+
+    public const int RepeatedSint32FieldNumber = 35;
+    private static readonly pb::FieldCodec<int> _repeated_repeatedSint32_codec
+        = pb::FieldCodec.ForSInt32(282);
+    private readonly pbc::RepeatedField<int> repeatedSint32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> RepeatedSint32 {
+      get { return repeatedSint32_; }
+    }
+
+    public const int RepeatedSint64FieldNumber = 36;
+    private static readonly pb::FieldCodec<long> _repeated_repeatedSint64_codec
+        = pb::FieldCodec.ForSInt64(290);
+    private readonly pbc::RepeatedField<long> repeatedSint64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> RepeatedSint64 {
+      get { return repeatedSint64_; }
+    }
+
+    public const int RepeatedFixed32FieldNumber = 37;
+    private static readonly pb::FieldCodec<uint> _repeated_repeatedFixed32_codec
+        = pb::FieldCodec.ForFixed32(298);
+    private readonly pbc::RepeatedField<uint> repeatedFixed32_ = new pbc::RepeatedField<uint>();
+    public pbc::RepeatedField<uint> RepeatedFixed32 {
+      get { return repeatedFixed32_; }
+    }
+
+    public const int RepeatedFixed64FieldNumber = 38;
+    private static readonly pb::FieldCodec<ulong> _repeated_repeatedFixed64_codec
+        = pb::FieldCodec.ForFixed64(306);
+    private readonly pbc::RepeatedField<ulong> repeatedFixed64_ = new pbc::RepeatedField<ulong>();
+    public pbc::RepeatedField<ulong> RepeatedFixed64 {
+      get { return repeatedFixed64_; }
+    }
+
+    public const int RepeatedSfixed32FieldNumber = 39;
+    private static readonly pb::FieldCodec<int> _repeated_repeatedSfixed32_codec
+        = pb::FieldCodec.ForSFixed32(314);
+    private readonly pbc::RepeatedField<int> repeatedSfixed32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> RepeatedSfixed32 {
+      get { return repeatedSfixed32_; }
+    }
+
+    public const int RepeatedSfixed64FieldNumber = 40;
+    private static readonly pb::FieldCodec<long> _repeated_repeatedSfixed64_codec
+        = pb::FieldCodec.ForSFixed64(322);
+    private readonly pbc::RepeatedField<long> repeatedSfixed64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> RepeatedSfixed64 {
+      get { return repeatedSfixed64_; }
+    }
+
+    public const int RepeatedFloatFieldNumber = 41;
+    private static readonly pb::FieldCodec<float> _repeated_repeatedFloat_codec
+        = pb::FieldCodec.ForFloat(330);
+    private readonly pbc::RepeatedField<float> repeatedFloat_ = new pbc::RepeatedField<float>();
+    public pbc::RepeatedField<float> RepeatedFloat {
+      get { return repeatedFloat_; }
+    }
+
+    public const int RepeatedDoubleFieldNumber = 42;
+    private static readonly pb::FieldCodec<double> _repeated_repeatedDouble_codec
+        = pb::FieldCodec.ForDouble(338);
+    private readonly pbc::RepeatedField<double> repeatedDouble_ = new pbc::RepeatedField<double>();
+    public pbc::RepeatedField<double> RepeatedDouble {
+      get { return repeatedDouble_; }
+    }
+
+    public const int RepeatedBoolFieldNumber = 43;
+    private static readonly pb::FieldCodec<bool> _repeated_repeatedBool_codec
+        = pb::FieldCodec.ForBool(346);
+    private readonly pbc::RepeatedField<bool> repeatedBool_ = new pbc::RepeatedField<bool>();
+    public pbc::RepeatedField<bool> RepeatedBool {
+      get { return repeatedBool_; }
+    }
+
+    public const int RepeatedStringFieldNumber = 44;
+    private static readonly pb::FieldCodec<string> _repeated_repeatedString_codec
+        = pb::FieldCodec.ForString(354);
+    private readonly pbc::RepeatedField<string> repeatedString_ = new pbc::RepeatedField<string>();
+    public pbc::RepeatedField<string> RepeatedString {
+      get { return repeatedString_; }
+    }
+
+    public const int RepeatedBytesFieldNumber = 45;
+    private static readonly pb::FieldCodec<pb::ByteString> _repeated_repeatedBytes_codec
+        = pb::FieldCodec.ForBytes(362);
+    private readonly pbc::RepeatedField<pb::ByteString> repeatedBytes_ = new pbc::RepeatedField<pb::ByteString>();
+    public pbc::RepeatedField<pb::ByteString> RepeatedBytes {
+      get { return repeatedBytes_; }
+    }
+
+    public const int RepeatedNestedMessageFieldNumber = 48;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage> _repeated_repeatedNestedMessage_codec
+        = pb::FieldCodec.ForMessage(386, global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage> repeatedNestedMessage_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage> RepeatedNestedMessage {
+      get { return repeatedNestedMessage_; }
+    }
+
+    public const int RepeatedForeignMessageFieldNumber = 49;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.ForeignMessage> _repeated_repeatedForeignMessage_codec
+        = pb::FieldCodec.ForMessage(394, global::Google.Protobuf.TestProtos.ForeignMessage.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignMessage> repeatedForeignMessage_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignMessage>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignMessage> RepeatedForeignMessage {
+      get { return repeatedForeignMessage_; }
+    }
+
+    public const int RepeatedImportMessageFieldNumber = 50;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.ImportMessage> _repeated_repeatedImportMessage_codec
+        = pb::FieldCodec.ForMessage(402, global::Google.Protobuf.TestProtos.ImportMessage.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportMessage> repeatedImportMessage_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportMessage>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportMessage> RepeatedImportMessage {
+      get { return repeatedImportMessage_; }
+    }
+
+    public const int RepeatedNestedEnumFieldNumber = 51;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum> _repeated_repeatedNestedEnum_codec
+        = pb::FieldCodec.ForEnum(410, x => (int) x, x => (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) x);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum> repeatedNestedEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum> RepeatedNestedEnum {
+      get { return repeatedNestedEnum_; }
+    }
+
+    public const int RepeatedForeignEnumFieldNumber = 52;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.ForeignEnum> _repeated_repeatedForeignEnum_codec
+        = pb::FieldCodec.ForEnum(418, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> repeatedForeignEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> RepeatedForeignEnum {
+      get { return repeatedForeignEnum_; }
+    }
+
+    public const int RepeatedImportEnumFieldNumber = 53;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.ImportEnum> _repeated_repeatedImportEnum_codec
+        = pb::FieldCodec.ForEnum(426, x => (int) x, x => (global::Google.Protobuf.TestProtos.ImportEnum) x);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportEnum> repeatedImportEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportEnum>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ImportEnum> RepeatedImportEnum {
+      get { return repeatedImportEnum_; }
+    }
+
+    public const int RepeatedPublicImportMessageFieldNumber = 54;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.PublicImportMessage> _repeated_repeatedPublicImportMessage_codec
+        = pb::FieldCodec.ForMessage(434, global::Google.Protobuf.TestProtos.PublicImportMessage.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.PublicImportMessage> repeatedPublicImportMessage_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.PublicImportMessage>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.PublicImportMessage> RepeatedPublicImportMessage {
+      get { return repeatedPublicImportMessage_; }
+    }
+
+    public const int OneofUint32FieldNumber = 111;
+    public uint OneofUint32 {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32 ? (uint) oneofField_ : 0; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = OneofFieldOneofCase.OneofUint32;
+      }
+    }
+
+    public const int OneofNestedMessageFieldNumber = 112;
+    public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage OneofNestedMessage {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.OneofNestedMessage;
+      }
+    }
+
+    public const int OneofStringFieldNumber = 113;
+    public string OneofString {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) oneofField_ : ""; }
+      set {
+        oneofField_ = pb::Preconditions.CheckNotNull(value, "value");
+        oneofFieldCase_ = OneofFieldOneofCase.OneofString;
+      }
+    }
+
+    public const int OneofBytesFieldNumber = 114;
+    public pb::ByteString OneofBytes {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; }
+      set {
+        oneofField_ = pb::Preconditions.CheckNotNull(value, "value");
+        oneofFieldCase_ = OneofFieldOneofCase.OneofBytes;
+      }
+    }
+
+    private object oneofField_;
+    public enum OneofFieldOneofCase {
+      None = 0,
+      OneofUint32 = 111,
+      OneofNestedMessage = 112,
+      OneofString = 113,
+      OneofBytes = 114,
+    }
+    private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None;
+    public OneofFieldOneofCase OneofFieldCase {
+      get { return oneofFieldCase_; }
+    }
+
+    public void ClearOneofField() {
+      oneofFieldCase_ = OneofFieldOneofCase.None;
+      oneofField_ = null;
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestAllTypes);
+    }
+
+    public bool Equals(TestAllTypes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (SingleInt32 != other.SingleInt32) return false;
+      if (SingleInt64 != other.SingleInt64) return false;
+      if (SingleUint32 != other.SingleUint32) return false;
+      if (SingleUint64 != other.SingleUint64) return false;
+      if (SingleSint32 != other.SingleSint32) return false;
+      if (SingleSint64 != other.SingleSint64) return false;
+      if (SingleFixed32 != other.SingleFixed32) return false;
+      if (SingleFixed64 != other.SingleFixed64) return false;
+      if (SingleSfixed32 != other.SingleSfixed32) return false;
+      if (SingleSfixed64 != other.SingleSfixed64) return false;
+      if (SingleFloat != other.SingleFloat) return false;
+      if (SingleDouble != other.SingleDouble) return false;
+      if (SingleBool != other.SingleBool) return false;
+      if (SingleString != other.SingleString) return false;
+      if (SingleBytes != other.SingleBytes) return false;
+      if (!object.Equals(SingleNestedMessage, other.SingleNestedMessage)) return false;
+      if (!object.Equals(SingleForeignMessage, other.SingleForeignMessage)) return false;
+      if (!object.Equals(SingleImportMessage, other.SingleImportMessage)) return false;
+      if (SingleNestedEnum != other.SingleNestedEnum) return false;
+      if (SingleForeignEnum != other.SingleForeignEnum) return false;
+      if (SingleImportEnum != other.SingleImportEnum) return false;
+      if (!object.Equals(SinglePublicImportMessage, other.SinglePublicImportMessage)) return false;
+      if(!repeatedInt32_.Equals(other.repeatedInt32_)) return false;
+      if(!repeatedInt64_.Equals(other.repeatedInt64_)) return false;
+      if(!repeatedUint32_.Equals(other.repeatedUint32_)) return false;
+      if(!repeatedUint64_.Equals(other.repeatedUint64_)) return false;
+      if(!repeatedSint32_.Equals(other.repeatedSint32_)) return false;
+      if(!repeatedSint64_.Equals(other.repeatedSint64_)) return false;
+      if(!repeatedFixed32_.Equals(other.repeatedFixed32_)) return false;
+      if(!repeatedFixed64_.Equals(other.repeatedFixed64_)) return false;
+      if(!repeatedSfixed32_.Equals(other.repeatedSfixed32_)) return false;
+      if(!repeatedSfixed64_.Equals(other.repeatedSfixed64_)) return false;
+      if(!repeatedFloat_.Equals(other.repeatedFloat_)) return false;
+      if(!repeatedDouble_.Equals(other.repeatedDouble_)) return false;
+      if(!repeatedBool_.Equals(other.repeatedBool_)) return false;
+      if(!repeatedString_.Equals(other.repeatedString_)) return false;
+      if(!repeatedBytes_.Equals(other.repeatedBytes_)) return false;
+      if(!repeatedNestedMessage_.Equals(other.repeatedNestedMessage_)) return false;
+      if(!repeatedForeignMessage_.Equals(other.repeatedForeignMessage_)) return false;
+      if(!repeatedImportMessage_.Equals(other.repeatedImportMessage_)) return false;
+      if(!repeatedNestedEnum_.Equals(other.repeatedNestedEnum_)) return false;
+      if(!repeatedForeignEnum_.Equals(other.repeatedForeignEnum_)) return false;
+      if(!repeatedImportEnum_.Equals(other.repeatedImportEnum_)) return false;
+      if(!repeatedPublicImportMessage_.Equals(other.repeatedPublicImportMessage_)) return false;
+      if (OneofUint32 != other.OneofUint32) return false;
+      if (!object.Equals(OneofNestedMessage, other.OneofNestedMessage)) return false;
+      if (OneofString != other.OneofString) return false;
+      if (OneofBytes != other.OneofBytes) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (SingleInt32 != 0) hash ^= SingleInt32.GetHashCode();
+      if (SingleInt64 != 0L) hash ^= SingleInt64.GetHashCode();
+      if (SingleUint32 != 0) hash ^= SingleUint32.GetHashCode();
+      if (SingleUint64 != 0UL) hash ^= SingleUint64.GetHashCode();
+      if (SingleSint32 != 0) hash ^= SingleSint32.GetHashCode();
+      if (SingleSint64 != 0L) hash ^= SingleSint64.GetHashCode();
+      if (SingleFixed32 != 0) hash ^= SingleFixed32.GetHashCode();
+      if (SingleFixed64 != 0UL) hash ^= SingleFixed64.GetHashCode();
+      if (SingleSfixed32 != 0) hash ^= SingleSfixed32.GetHashCode();
+      if (SingleSfixed64 != 0L) hash ^= SingleSfixed64.GetHashCode();
+      if (SingleFloat != 0F) hash ^= SingleFloat.GetHashCode();
+      if (SingleDouble != 0D) hash ^= SingleDouble.GetHashCode();
+      if (SingleBool != false) hash ^= SingleBool.GetHashCode();
+      if (SingleString.Length != 0) hash ^= SingleString.GetHashCode();
+      if (SingleBytes.Length != 0) hash ^= SingleBytes.GetHashCode();
+      if (singleNestedMessage_ != null) hash ^= SingleNestedMessage.GetHashCode();
+      if (singleForeignMessage_ != null) hash ^= SingleForeignMessage.GetHashCode();
+      if (singleImportMessage_ != null) hash ^= SingleImportMessage.GetHashCode();
+      if (SingleNestedEnum != global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.NESTED_ENUM_UNSPECIFIED) hash ^= SingleNestedEnum.GetHashCode();
+      if (SingleForeignEnum != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) hash ^= SingleForeignEnum.GetHashCode();
+      if (SingleImportEnum != global::Google.Protobuf.TestProtos.ImportEnum.IMPORT_ENUM_UNSPECIFIED) hash ^= SingleImportEnum.GetHashCode();
+      if (singlePublicImportMessage_ != null) hash ^= SinglePublicImportMessage.GetHashCode();
+      hash ^= repeatedInt32_.GetHashCode();
+      hash ^= repeatedInt64_.GetHashCode();
+      hash ^= repeatedUint32_.GetHashCode();
+      hash ^= repeatedUint64_.GetHashCode();
+      hash ^= repeatedSint32_.GetHashCode();
+      hash ^= repeatedSint64_.GetHashCode();
+      hash ^= repeatedFixed32_.GetHashCode();
+      hash ^= repeatedFixed64_.GetHashCode();
+      hash ^= repeatedSfixed32_.GetHashCode();
+      hash ^= repeatedSfixed64_.GetHashCode();
+      hash ^= repeatedFloat_.GetHashCode();
+      hash ^= repeatedDouble_.GetHashCode();
+      hash ^= repeatedBool_.GetHashCode();
+      hash ^= repeatedString_.GetHashCode();
+      hash ^= repeatedBytes_.GetHashCode();
+      hash ^= repeatedNestedMessage_.GetHashCode();
+      hash ^= repeatedForeignMessage_.GetHashCode();
+      hash ^= repeatedImportMessage_.GetHashCode();
+      hash ^= repeatedNestedEnum_.GetHashCode();
+      hash ^= repeatedForeignEnum_.GetHashCode();
+      hash ^= repeatedImportEnum_.GetHashCode();
+      hash ^= repeatedPublicImportMessage_.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) hash ^= OneofUint32.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) hash ^= OneofNestedMessage.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) hash ^= OneofString.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) hash ^= OneofBytes.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (SingleInt32 != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(SingleInt32);
+      }
+      if (SingleInt64 != 0L) {
+        output.WriteRawTag(16);
+        output.WriteInt64(SingleInt64);
+      }
+      if (SingleUint32 != 0) {
+        output.WriteRawTag(24);
+        output.WriteUInt32(SingleUint32);
+      }
+      if (SingleUint64 != 0UL) {
+        output.WriteRawTag(32);
+        output.WriteUInt64(SingleUint64);
+      }
+      if (SingleSint32 != 0) {
+        output.WriteRawTag(40);
+        output.WriteSInt32(SingleSint32);
+      }
+      if (SingleSint64 != 0L) {
+        output.WriteRawTag(48);
+        output.WriteSInt64(SingleSint64);
+      }
+      if (SingleFixed32 != 0) {
+        output.WriteRawTag(61);
+        output.WriteFixed32(SingleFixed32);
+      }
+      if (SingleFixed64 != 0UL) {
+        output.WriteRawTag(65);
+        output.WriteFixed64(SingleFixed64);
+      }
+      if (SingleSfixed32 != 0) {
+        output.WriteRawTag(77);
+        output.WriteSFixed32(SingleSfixed32);
+      }
+      if (SingleSfixed64 != 0L) {
+        output.WriteRawTag(81);
+        output.WriteSFixed64(SingleSfixed64);
+      }
+      if (SingleFloat != 0F) {
+        output.WriteRawTag(93);
+        output.WriteFloat(SingleFloat);
+      }
+      if (SingleDouble != 0D) {
+        output.WriteRawTag(97);
+        output.WriteDouble(SingleDouble);
+      }
+      if (SingleBool != false) {
+        output.WriteRawTag(104);
+        output.WriteBool(SingleBool);
+      }
+      if (SingleString.Length != 0) {
+        output.WriteRawTag(114);
+        output.WriteString(SingleString);
+      }
+      if (SingleBytes.Length != 0) {
+        output.WriteRawTag(122);
+        output.WriteBytes(SingleBytes);
+      }
+      if (singleNestedMessage_ != null) {
+        output.WriteRawTag(146, 1);
+        output.WriteMessage(SingleNestedMessage);
+      }
+      if (singleForeignMessage_ != null) {
+        output.WriteRawTag(154, 1);
+        output.WriteMessage(SingleForeignMessage);
+      }
+      if (singleImportMessage_ != null) {
+        output.WriteRawTag(162, 1);
+        output.WriteMessage(SingleImportMessage);
+      }
+      if (SingleNestedEnum != global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.NESTED_ENUM_UNSPECIFIED) {
+        output.WriteRawTag(168, 1);
+        output.WriteEnum((int) SingleNestedEnum);
+      }
+      if (SingleForeignEnum != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) {
+        output.WriteRawTag(176, 1);
+        output.WriteEnum((int) SingleForeignEnum);
+      }
+      if (SingleImportEnum != global::Google.Protobuf.TestProtos.ImportEnum.IMPORT_ENUM_UNSPECIFIED) {
+        output.WriteRawTag(184, 1);
+        output.WriteEnum((int) SingleImportEnum);
+      }
+      if (singlePublicImportMessage_ != null) {
+        output.WriteRawTag(210, 1);
+        output.WriteMessage(SinglePublicImportMessage);
+      }
+      repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec);
+      repeatedInt64_.WriteTo(output, _repeated_repeatedInt64_codec);
+      repeatedUint32_.WriteTo(output, _repeated_repeatedUint32_codec);
+      repeatedUint64_.WriteTo(output, _repeated_repeatedUint64_codec);
+      repeatedSint32_.WriteTo(output, _repeated_repeatedSint32_codec);
+      repeatedSint64_.WriteTo(output, _repeated_repeatedSint64_codec);
+      repeatedFixed32_.WriteTo(output, _repeated_repeatedFixed32_codec);
+      repeatedFixed64_.WriteTo(output, _repeated_repeatedFixed64_codec);
+      repeatedSfixed32_.WriteTo(output, _repeated_repeatedSfixed32_codec);
+      repeatedSfixed64_.WriteTo(output, _repeated_repeatedSfixed64_codec);
+      repeatedFloat_.WriteTo(output, _repeated_repeatedFloat_codec);
+      repeatedDouble_.WriteTo(output, _repeated_repeatedDouble_codec);
+      repeatedBool_.WriteTo(output, _repeated_repeatedBool_codec);
+      repeatedString_.WriteTo(output, _repeated_repeatedString_codec);
+      repeatedBytes_.WriteTo(output, _repeated_repeatedBytes_codec);
+      repeatedNestedMessage_.WriteTo(output, _repeated_repeatedNestedMessage_codec);
+      repeatedForeignMessage_.WriteTo(output, _repeated_repeatedForeignMessage_codec);
+      repeatedImportMessage_.WriteTo(output, _repeated_repeatedImportMessage_codec);
+      repeatedNestedEnum_.WriteTo(output, _repeated_repeatedNestedEnum_codec);
+      repeatedForeignEnum_.WriteTo(output, _repeated_repeatedForeignEnum_codec);
+      repeatedImportEnum_.WriteTo(output, _repeated_repeatedImportEnum_codec);
+      repeatedPublicImportMessage_.WriteTo(output, _repeated_repeatedPublicImportMessage_codec);
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) {
+        output.WriteRawTag(248, 6);
+        output.WriteUInt32(OneofUint32);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
+        output.WriteRawTag(130, 7);
+        output.WriteMessage(OneofNestedMessage);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) {
+        output.WriteRawTag(138, 7);
+        output.WriteString(OneofString);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) {
+        output.WriteRawTag(146, 7);
+        output.WriteBytes(OneofBytes);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (SingleInt32 != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(SingleInt32);
+      }
+      if (SingleInt64 != 0L) {
+        size += 1 + pb::CodedOutputStream.ComputeInt64Size(SingleInt64);
+      }
+      if (SingleUint32 != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeUInt32Size(SingleUint32);
+      }
+      if (SingleUint64 != 0UL) {
+        size += 1 + pb::CodedOutputStream.ComputeUInt64Size(SingleUint64);
+      }
+      if (SingleSint32 != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeSInt32Size(SingleSint32);
+      }
+      if (SingleSint64 != 0L) {
+        size += 1 + pb::CodedOutputStream.ComputeSInt64Size(SingleSint64);
+      }
+      if (SingleFixed32 != 0) {
+        size += 1 + 4;
+      }
+      if (SingleFixed64 != 0UL) {
+        size += 1 + 8;
+      }
+      if (SingleSfixed32 != 0) {
+        size += 1 + 4;
+      }
+      if (SingleSfixed64 != 0L) {
+        size += 1 + 8;
+      }
+      if (SingleFloat != 0F) {
+        size += 1 + 4;
+      }
+      if (SingleDouble != 0D) {
+        size += 1 + 8;
+      }
+      if (SingleBool != false) {
+        size += 1 + 1;
+      }
+      if (SingleString.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(SingleString);
+      }
+      if (SingleBytes.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeBytesSize(SingleBytes);
+      }
+      if (singleNestedMessage_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(SingleNestedMessage);
+      }
+      if (singleForeignMessage_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(SingleForeignMessage);
+      }
+      if (singleImportMessage_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(SingleImportMessage);
+      }
+      if (SingleNestedEnum != global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.NESTED_ENUM_UNSPECIFIED) {
+        size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) SingleNestedEnum);
+      }
+      if (SingleForeignEnum != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) {
+        size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) SingleForeignEnum);
+      }
+      if (SingleImportEnum != global::Google.Protobuf.TestProtos.ImportEnum.IMPORT_ENUM_UNSPECIFIED) {
+        size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) SingleImportEnum);
+      }
+      if (singlePublicImportMessage_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(SinglePublicImportMessage);
+      }
+      size += repeatedInt32_.CalculateSize(_repeated_repeatedInt32_codec);
+      size += repeatedInt64_.CalculateSize(_repeated_repeatedInt64_codec);
+      size += repeatedUint32_.CalculateSize(_repeated_repeatedUint32_codec);
+      size += repeatedUint64_.CalculateSize(_repeated_repeatedUint64_codec);
+      size += repeatedSint32_.CalculateSize(_repeated_repeatedSint32_codec);
+      size += repeatedSint64_.CalculateSize(_repeated_repeatedSint64_codec);
+      size += repeatedFixed32_.CalculateSize(_repeated_repeatedFixed32_codec);
+      size += repeatedFixed64_.CalculateSize(_repeated_repeatedFixed64_codec);
+      size += repeatedSfixed32_.CalculateSize(_repeated_repeatedSfixed32_codec);
+      size += repeatedSfixed64_.CalculateSize(_repeated_repeatedSfixed64_codec);
+      size += repeatedFloat_.CalculateSize(_repeated_repeatedFloat_codec);
+      size += repeatedDouble_.CalculateSize(_repeated_repeatedDouble_codec);
+      size += repeatedBool_.CalculateSize(_repeated_repeatedBool_codec);
+      size += repeatedString_.CalculateSize(_repeated_repeatedString_codec);
+      size += repeatedBytes_.CalculateSize(_repeated_repeatedBytes_codec);
+      size += repeatedNestedMessage_.CalculateSize(_repeated_repeatedNestedMessage_codec);
+      size += repeatedForeignMessage_.CalculateSize(_repeated_repeatedForeignMessage_codec);
+      size += repeatedImportMessage_.CalculateSize(_repeated_repeatedImportMessage_codec);
+      size += repeatedNestedEnum_.CalculateSize(_repeated_repeatedNestedEnum_codec);
+      size += repeatedForeignEnum_.CalculateSize(_repeated_repeatedForeignEnum_codec);
+      size += repeatedImportEnum_.CalculateSize(_repeated_repeatedImportEnum_codec);
+      size += repeatedPublicImportMessage_.CalculateSize(_repeated_repeatedPublicImportMessage_codec);
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) {
+        size += 2 + pb::CodedOutputStream.ComputeUInt32Size(OneofUint32);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(OneofNestedMessage);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) {
+        size += 2 + pb::CodedOutputStream.ComputeStringSize(OneofString);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) {
+        size += 2 + pb::CodedOutputStream.ComputeBytesSize(OneofBytes);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestAllTypes other) {
+      if (other == null) {
+        return;
+      }
+      if (other.SingleInt32 != 0) {
+        SingleInt32 = other.SingleInt32;
+      }
+      if (other.SingleInt64 != 0L) {
+        SingleInt64 = other.SingleInt64;
+      }
+      if (other.SingleUint32 != 0) {
+        SingleUint32 = other.SingleUint32;
+      }
+      if (other.SingleUint64 != 0UL) {
+        SingleUint64 = other.SingleUint64;
+      }
+      if (other.SingleSint32 != 0) {
+        SingleSint32 = other.SingleSint32;
+      }
+      if (other.SingleSint64 != 0L) {
+        SingleSint64 = other.SingleSint64;
+      }
+      if (other.SingleFixed32 != 0) {
+        SingleFixed32 = other.SingleFixed32;
+      }
+      if (other.SingleFixed64 != 0UL) {
+        SingleFixed64 = other.SingleFixed64;
+      }
+      if (other.SingleSfixed32 != 0) {
+        SingleSfixed32 = other.SingleSfixed32;
+      }
+      if (other.SingleSfixed64 != 0L) {
+        SingleSfixed64 = other.SingleSfixed64;
+      }
+      if (other.SingleFloat != 0F) {
+        SingleFloat = other.SingleFloat;
+      }
+      if (other.SingleDouble != 0D) {
+        SingleDouble = other.SingleDouble;
+      }
+      if (other.SingleBool != false) {
+        SingleBool = other.SingleBool;
+      }
+      if (other.SingleString.Length != 0) {
+        SingleString = other.SingleString;
+      }
+      if (other.SingleBytes.Length != 0) {
+        SingleBytes = other.SingleBytes;
+      }
+      if (other.singleNestedMessage_ != null) {
+        if (singleNestedMessage_ == null) {
+          singleNestedMessage_ = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
+        }
+        SingleNestedMessage.MergeFrom(other.SingleNestedMessage);
+      }
+      if (other.singleForeignMessage_ != null) {
+        if (singleForeignMessage_ == null) {
+          singleForeignMessage_ = new global::Google.Protobuf.TestProtos.ForeignMessage();
+        }
+        SingleForeignMessage.MergeFrom(other.SingleForeignMessage);
+      }
+      if (other.singleImportMessage_ != null) {
+        if (singleImportMessage_ == null) {
+          singleImportMessage_ = new global::Google.Protobuf.TestProtos.ImportMessage();
+        }
+        SingleImportMessage.MergeFrom(other.SingleImportMessage);
+      }
+      if (other.SingleNestedEnum != global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.NESTED_ENUM_UNSPECIFIED) {
+        SingleNestedEnum = other.SingleNestedEnum;
+      }
+      if (other.SingleForeignEnum != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) {
+        SingleForeignEnum = other.SingleForeignEnum;
+      }
+      if (other.SingleImportEnum != global::Google.Protobuf.TestProtos.ImportEnum.IMPORT_ENUM_UNSPECIFIED) {
+        SingleImportEnum = other.SingleImportEnum;
+      }
+      if (other.singlePublicImportMessage_ != null) {
+        if (singlePublicImportMessage_ == null) {
+          singlePublicImportMessage_ = new global::Google.Protobuf.TestProtos.PublicImportMessage();
+        }
+        SinglePublicImportMessage.MergeFrom(other.SinglePublicImportMessage);
+      }
+      repeatedInt32_.Add(other.repeatedInt32_);
+      repeatedInt64_.Add(other.repeatedInt64_);
+      repeatedUint32_.Add(other.repeatedUint32_);
+      repeatedUint64_.Add(other.repeatedUint64_);
+      repeatedSint32_.Add(other.repeatedSint32_);
+      repeatedSint64_.Add(other.repeatedSint64_);
+      repeatedFixed32_.Add(other.repeatedFixed32_);
+      repeatedFixed64_.Add(other.repeatedFixed64_);
+      repeatedSfixed32_.Add(other.repeatedSfixed32_);
+      repeatedSfixed64_.Add(other.repeatedSfixed64_);
+      repeatedFloat_.Add(other.repeatedFloat_);
+      repeatedDouble_.Add(other.repeatedDouble_);
+      repeatedBool_.Add(other.repeatedBool_);
+      repeatedString_.Add(other.repeatedString_);
+      repeatedBytes_.Add(other.repeatedBytes_);
+      repeatedNestedMessage_.Add(other.repeatedNestedMessage_);
+      repeatedForeignMessage_.Add(other.repeatedForeignMessage_);
+      repeatedImportMessage_.Add(other.repeatedImportMessage_);
+      repeatedNestedEnum_.Add(other.repeatedNestedEnum_);
+      repeatedForeignEnum_.Add(other.repeatedForeignEnum_);
+      repeatedImportEnum_.Add(other.repeatedImportEnum_);
+      repeatedPublicImportMessage_.Add(other.repeatedPublicImportMessage_);
+      switch (other.OneofFieldCase) {
+        case OneofFieldOneofCase.OneofUint32:
+          OneofUint32 = other.OneofUint32;
+          break;
+        case OneofFieldOneofCase.OneofNestedMessage:
+          OneofNestedMessage = other.OneofNestedMessage;
+          break;
+        case OneofFieldOneofCase.OneofString:
+          OneofString = other.OneofString;
+          break;
+        case OneofFieldOneofCase.OneofBytes:
+          OneofBytes = other.OneofBytes;
+          break;
+      }
+
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            SingleInt32 = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            SingleInt64 = input.ReadInt64();
+            break;
+          }
+          case 24: {
+            SingleUint32 = input.ReadUInt32();
+            break;
+          }
+          case 32: {
+            SingleUint64 = input.ReadUInt64();
+            break;
+          }
+          case 40: {
+            SingleSint32 = input.ReadSInt32();
+            break;
+          }
+          case 48: {
+            SingleSint64 = input.ReadSInt64();
+            break;
+          }
+          case 61: {
+            SingleFixed32 = input.ReadFixed32();
+            break;
+          }
+          case 65: {
+            SingleFixed64 = input.ReadFixed64();
+            break;
+          }
+          case 77: {
+            SingleSfixed32 = input.ReadSFixed32();
+            break;
+          }
+          case 81: {
+            SingleSfixed64 = input.ReadSFixed64();
+            break;
+          }
+          case 93: {
+            SingleFloat = input.ReadFloat();
+            break;
+          }
+          case 97: {
+            SingleDouble = input.ReadDouble();
+            break;
+          }
+          case 104: {
+            SingleBool = input.ReadBool();
+            break;
+          }
+          case 114: {
+            SingleString = input.ReadString();
+            break;
+          }
+          case 122: {
+            SingleBytes = input.ReadBytes();
+            break;
+          }
+          case 146: {
+            if (singleNestedMessage_ == null) {
+              singleNestedMessage_ = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
+            }
+            input.ReadMessage(singleNestedMessage_);
+            break;
+          }
+          case 154: {
+            if (singleForeignMessage_ == null) {
+              singleForeignMessage_ = new global::Google.Protobuf.TestProtos.ForeignMessage();
+            }
+            input.ReadMessage(singleForeignMessage_);
+            break;
+          }
+          case 162: {
+            if (singleImportMessage_ == null) {
+              singleImportMessage_ = new global::Google.Protobuf.TestProtos.ImportMessage();
+            }
+            input.ReadMessage(singleImportMessage_);
+            break;
+          }
+          case 168: {
+            singleNestedEnum_ = (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) input.ReadEnum();
+            break;
+          }
+          case 176: {
+            singleForeignEnum_ = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum();
+            break;
+          }
+          case 184: {
+            singleImportEnum_ = (global::Google.Protobuf.TestProtos.ImportEnum) input.ReadEnum();
+            break;
+          }
+          case 210: {
+            if (singlePublicImportMessage_ == null) {
+              singlePublicImportMessage_ = new global::Google.Protobuf.TestProtos.PublicImportMessage();
+            }
+            input.ReadMessage(singlePublicImportMessage_);
+            break;
+          }
+          case 250:
+          case 248: {
+            repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec);
+            break;
+          }
+          case 258:
+          case 256: {
+            repeatedInt64_.AddEntriesFrom(input, _repeated_repeatedInt64_codec);
+            break;
+          }
+          case 266:
+          case 264: {
+            repeatedUint32_.AddEntriesFrom(input, _repeated_repeatedUint32_codec);
+            break;
+          }
+          case 274:
+          case 272: {
+            repeatedUint64_.AddEntriesFrom(input, _repeated_repeatedUint64_codec);
+            break;
+          }
+          case 282:
+          case 280: {
+            repeatedSint32_.AddEntriesFrom(input, _repeated_repeatedSint32_codec);
+            break;
+          }
+          case 290:
+          case 288: {
+            repeatedSint64_.AddEntriesFrom(input, _repeated_repeatedSint64_codec);
+            break;
+          }
+          case 298:
+          case 301: {
+            repeatedFixed32_.AddEntriesFrom(input, _repeated_repeatedFixed32_codec);
+            break;
+          }
+          case 306:
+          case 305: {
+            repeatedFixed64_.AddEntriesFrom(input, _repeated_repeatedFixed64_codec);
+            break;
+          }
+          case 314:
+          case 317: {
+            repeatedSfixed32_.AddEntriesFrom(input, _repeated_repeatedSfixed32_codec);
+            break;
+          }
+          case 322:
+          case 321: {
+            repeatedSfixed64_.AddEntriesFrom(input, _repeated_repeatedSfixed64_codec);
+            break;
+          }
+          case 330:
+          case 333: {
+            repeatedFloat_.AddEntriesFrom(input, _repeated_repeatedFloat_codec);
+            break;
+          }
+          case 338:
+          case 337: {
+            repeatedDouble_.AddEntriesFrom(input, _repeated_repeatedDouble_codec);
+            break;
+          }
+          case 346:
+          case 344: {
+            repeatedBool_.AddEntriesFrom(input, _repeated_repeatedBool_codec);
+            break;
+          }
+          case 354: {
+            repeatedString_.AddEntriesFrom(input, _repeated_repeatedString_codec);
+            break;
+          }
+          case 362: {
+            repeatedBytes_.AddEntriesFrom(input, _repeated_repeatedBytes_codec);
+            break;
+          }
+          case 386: {
+            repeatedNestedMessage_.AddEntriesFrom(input, _repeated_repeatedNestedMessage_codec);
+            break;
+          }
+          case 394: {
+            repeatedForeignMessage_.AddEntriesFrom(input, _repeated_repeatedForeignMessage_codec);
+            break;
+          }
+          case 402: {
+            repeatedImportMessage_.AddEntriesFrom(input, _repeated_repeatedImportMessage_codec);
+            break;
+          }
+          case 410:
+          case 408: {
+            repeatedNestedEnum_.AddEntriesFrom(input, _repeated_repeatedNestedEnum_codec);
+            break;
+          }
+          case 418:
+          case 416: {
+            repeatedForeignEnum_.AddEntriesFrom(input, _repeated_repeatedForeignEnum_codec);
+            break;
+          }
+          case 426:
+          case 424: {
+            repeatedImportEnum_.AddEntriesFrom(input, _repeated_repeatedImportEnum_codec);
+            break;
+          }
+          case 434: {
+            repeatedPublicImportMessage_.AddEntriesFrom(input, _repeated_repeatedPublicImportMessage_codec);
+            break;
+          }
+          case 888: {
+            OneofUint32 = input.ReadUInt32();
+            break;
+          }
+          case 898: {
+            global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage subBuilder = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
+            if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
+              subBuilder.MergeFrom(OneofNestedMessage);
+            }
+            input.ReadMessage(subBuilder);
+            OneofNestedMessage = subBuilder;
+            break;
+          }
+          case 906: {
+            OneofString = input.ReadString();
+            break;
+          }
+          case 914: {
+            OneofBytes = input.ReadBytes();
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      public enum NestedEnum {
+        NESTED_ENUM_UNSPECIFIED = 0,
+        FOO = 1,
+        BAR = 2,
+        BAZ = 3,
+        NEG = -1,
+      }
+
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class NestedMessage : pb::IMessage<NestedMessage> {
+        private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
+        public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
+
+        public static pbr::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.TestAllTypes.Descriptor.NestedTypes[0]; }
+        }
+
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
+        }
+
+        public NestedMessage() {
+          OnConstruction();
+        }
+
+        partial void OnConstruction();
+
+        public NestedMessage(NestedMessage other) : this() {
+          bb_ = other.bb_;
+        }
+
+        public NestedMessage Clone() {
+          return new NestedMessage(this);
+        }
+
+        public const int BbFieldNumber = 1;
+        private int bb_;
+        public int Bb {
+          get { return bb_; }
+          set {
+            bb_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as NestedMessage);
+        }
+
+        public bool Equals(NestedMessage other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Bb != other.Bb) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Bb != 0) hash ^= Bb.GetHashCode();
+          return hash;
+        }
+
+        public override string ToString() {
+          return pb::JsonFormatter.Default.Format(this);
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Bb != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Bb);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Bb != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Bb);
+          }
+          return size;
+        }
+
+        public void MergeFrom(NestedMessage other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Bb != 0) {
+            Bb = other.Bb;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                input.SkipLastField();
+                break;
+              case 8: {
+                Bb = input.ReadInt32();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class NestedTestAllTypes : pb::IMessage<NestedTestAllTypes> {
+    private static readonly pb::MessageParser<NestedTestAllTypes> _parser = new pb::MessageParser<NestedTestAllTypes>(() => new NestedTestAllTypes());
+    public static pb::MessageParser<NestedTestAllTypes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[1]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public NestedTestAllTypes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public NestedTestAllTypes(NestedTestAllTypes other) : this() {
+      Child = other.child_ != null ? other.Child.Clone() : null;
+      Payload = other.payload_ != null ? other.Payload.Clone() : null;
+      repeatedChild_ = other.repeatedChild_.Clone();
+    }
+
+    public NestedTestAllTypes Clone() {
+      return new NestedTestAllTypes(this);
+    }
+
+    public const int ChildFieldNumber = 1;
+    private global::Google.Protobuf.TestProtos.NestedTestAllTypes child_;
+    public global::Google.Protobuf.TestProtos.NestedTestAllTypes Child {
+      get { return child_; }
+      set {
+        child_ = value;
+      }
+    }
+
+    public const int PayloadFieldNumber = 2;
+    private global::Google.Protobuf.TestProtos.TestAllTypes payload_;
+    public global::Google.Protobuf.TestProtos.TestAllTypes Payload {
+      get { return payload_; }
+      set {
+        payload_ = value;
+      }
+    }
+
+    public const int RepeatedChildFieldNumber = 3;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.NestedTestAllTypes> _repeated_repeatedChild_codec
+        = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.TestProtos.NestedTestAllTypes.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.NestedTestAllTypes> repeatedChild_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.NestedTestAllTypes>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.NestedTestAllTypes> RepeatedChild {
+      get { return repeatedChild_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as NestedTestAllTypes);
+    }
+
+    public bool Equals(NestedTestAllTypes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(Child, other.Child)) return false;
+      if (!object.Equals(Payload, other.Payload)) return false;
+      if(!repeatedChild_.Equals(other.repeatedChild_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (child_ != null) hash ^= Child.GetHashCode();
+      if (payload_ != null) hash ^= Payload.GetHashCode();
+      hash ^= repeatedChild_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (child_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(Child);
+      }
+      if (payload_ != null) {
+        output.WriteRawTag(18);
+        output.WriteMessage(Payload);
+      }
+      repeatedChild_.WriteTo(output, _repeated_repeatedChild_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (child_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Child);
+      }
+      if (payload_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload);
+      }
+      size += repeatedChild_.CalculateSize(_repeated_repeatedChild_codec);
+      return size;
+    }
+
+    public void MergeFrom(NestedTestAllTypes other) {
+      if (other == null) {
+        return;
+      }
+      if (other.child_ != null) {
+        if (child_ == null) {
+          child_ = new global::Google.Protobuf.TestProtos.NestedTestAllTypes();
+        }
+        Child.MergeFrom(other.Child);
+      }
+      if (other.payload_ != null) {
+        if (payload_ == null) {
+          payload_ = new global::Google.Protobuf.TestProtos.TestAllTypes();
+        }
+        Payload.MergeFrom(other.Payload);
+      }
+      repeatedChild_.Add(other.repeatedChild_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            if (child_ == null) {
+              child_ = new global::Google.Protobuf.TestProtos.NestedTestAllTypes();
+            }
+            input.ReadMessage(child_);
+            break;
+          }
+          case 18: {
+            if (payload_ == null) {
+              payload_ = new global::Google.Protobuf.TestProtos.TestAllTypes();
+            }
+            input.ReadMessage(payload_);
+            break;
+          }
+          case 26: {
+            repeatedChild_.AddEntriesFrom(input, _repeated_repeatedChild_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestDeprecatedFields : pb::IMessage<TestDeprecatedFields> {
+    private static readonly pb::MessageParser<TestDeprecatedFields> _parser = new pb::MessageParser<TestDeprecatedFields>(() => new TestDeprecatedFields());
+    public static pb::MessageParser<TestDeprecatedFields> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[2]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestDeprecatedFields() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestDeprecatedFields(TestDeprecatedFields other) : this() {
+      deprecatedInt32_ = other.deprecatedInt32_;
+    }
+
+    public TestDeprecatedFields Clone() {
+      return new TestDeprecatedFields(this);
+    }
+
+    public const int DeprecatedInt32FieldNumber = 1;
+    private int deprecatedInt32_;
+    [global::System.ObsoleteAttribute()]
+    public int DeprecatedInt32 {
+      get { return deprecatedInt32_; }
+      set {
+        deprecatedInt32_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestDeprecatedFields);
+    }
+
+    public bool Equals(TestDeprecatedFields other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (DeprecatedInt32 != other.DeprecatedInt32) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (DeprecatedInt32 != 0) hash ^= DeprecatedInt32.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (DeprecatedInt32 != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(DeprecatedInt32);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (DeprecatedInt32 != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(DeprecatedInt32);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestDeprecatedFields other) {
+      if (other == null) {
+        return;
+      }
+      if (other.DeprecatedInt32 != 0) {
+        DeprecatedInt32 = other.DeprecatedInt32;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            DeprecatedInt32 = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class ForeignMessage : pb::IMessage<ForeignMessage> {
+    private static readonly pb::MessageParser<ForeignMessage> _parser = new pb::MessageParser<ForeignMessage>(() => new ForeignMessage());
+    public static pb::MessageParser<ForeignMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[3]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public ForeignMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public ForeignMessage(ForeignMessage other) : this() {
+      c_ = other.c_;
+    }
+
+    public ForeignMessage Clone() {
+      return new ForeignMessage(this);
+    }
+
+    public const int CFieldNumber = 1;
+    private int c_;
+    public int C {
+      get { return c_; }
+      set {
+        c_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as ForeignMessage);
+    }
+
+    public bool Equals(ForeignMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (C != other.C) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (C != 0) hash ^= C.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (C != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(C);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (C != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(C);
+      }
+      return size;
+    }
+
+    public void MergeFrom(ForeignMessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.C != 0) {
+        C = other.C;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            C = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestReservedFields : pb::IMessage<TestReservedFields> {
+    private static readonly pb::MessageParser<TestReservedFields> _parser = new pb::MessageParser<TestReservedFields>(() => new TestReservedFields());
+    public static pb::MessageParser<TestReservedFields> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[4]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestReservedFields() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestReservedFields(TestReservedFields other) : this() {
+    }
+
+    public TestReservedFields Clone() {
+      return new TestReservedFields(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestReservedFields);
+    }
+
+    public bool Equals(TestReservedFields other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(TestReservedFields other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestForeignNested : pb::IMessage<TestForeignNested> {
+    private static readonly pb::MessageParser<TestForeignNested> _parser = new pb::MessageParser<TestForeignNested>(() => new TestForeignNested());
+    public static pb::MessageParser<TestForeignNested> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[5]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestForeignNested() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestForeignNested(TestForeignNested other) : this() {
+      ForeignNested = other.foreignNested_ != null ? other.ForeignNested.Clone() : null;
+    }
+
+    public TestForeignNested Clone() {
+      return new TestForeignNested(this);
+    }
+
+    public const int ForeignNestedFieldNumber = 1;
+    private global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage foreignNested_;
+    public global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage ForeignNested {
+      get { return foreignNested_; }
+      set {
+        foreignNested_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestForeignNested);
+    }
+
+    public bool Equals(TestForeignNested other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(ForeignNested, other.ForeignNested)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (foreignNested_ != null) hash ^= ForeignNested.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (foreignNested_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(ForeignNested);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (foreignNested_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ForeignNested);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestForeignNested other) {
+      if (other == null) {
+        return;
+      }
+      if (other.foreignNested_ != null) {
+        if (foreignNested_ == null) {
+          foreignNested_ = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
+        }
+        ForeignNested.MergeFrom(other.ForeignNested);
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            if (foreignNested_ == null) {
+              foreignNested_ = new global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage();
+            }
+            input.ReadMessage(foreignNested_);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestReallyLargeTagNumber : pb::IMessage<TestReallyLargeTagNumber> {
+    private static readonly pb::MessageParser<TestReallyLargeTagNumber> _parser = new pb::MessageParser<TestReallyLargeTagNumber>(() => new TestReallyLargeTagNumber());
+    public static pb::MessageParser<TestReallyLargeTagNumber> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[6]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestReallyLargeTagNumber() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestReallyLargeTagNumber(TestReallyLargeTagNumber other) : this() {
+      a_ = other.a_;
+      bb_ = other.bb_;
+    }
+
+    public TestReallyLargeTagNumber Clone() {
+      return new TestReallyLargeTagNumber(this);
+    }
+
+    public const int AFieldNumber = 1;
+    private int a_;
+    public int A {
+      get { return a_; }
+      set {
+        a_ = value;
+      }
+    }
+
+    public const int BbFieldNumber = 268435455;
+    private int bb_;
+    public int Bb {
+      get { return bb_; }
+      set {
+        bb_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestReallyLargeTagNumber);
+    }
+
+    public bool Equals(TestReallyLargeTagNumber other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (A != other.A) return false;
+      if (Bb != other.Bb) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (A != 0) hash ^= A.GetHashCode();
+      if (Bb != 0) hash ^= Bb.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (A != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(A);
+      }
+      if (Bb != 0) {
+        output.WriteRawTag(248, 255, 255, 255, 7);
+        output.WriteInt32(Bb);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (A != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(A);
+      }
+      if (Bb != 0) {
+        size += 5 + pb::CodedOutputStream.ComputeInt32Size(Bb);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestReallyLargeTagNumber other) {
+      if (other == null) {
+        return;
+      }
+      if (other.A != 0) {
+        A = other.A;
+      }
+      if (other.Bb != 0) {
+        Bb = other.Bb;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            A = input.ReadInt32();
+            break;
+          }
+          case 2147483640: {
+            Bb = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestRecursiveMessage : pb::IMessage<TestRecursiveMessage> {
+    private static readonly pb::MessageParser<TestRecursiveMessage> _parser = new pb::MessageParser<TestRecursiveMessage>(() => new TestRecursiveMessage());
+    public static pb::MessageParser<TestRecursiveMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[7]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestRecursiveMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestRecursiveMessage(TestRecursiveMessage other) : this() {
+      A = other.a_ != null ? other.A.Clone() : null;
+      i_ = other.i_;
+    }
+
+    public TestRecursiveMessage Clone() {
+      return new TestRecursiveMessage(this);
+    }
+
+    public const int AFieldNumber = 1;
+    private global::Google.Protobuf.TestProtos.TestRecursiveMessage a_;
+    public global::Google.Protobuf.TestProtos.TestRecursiveMessage A {
+      get { return a_; }
+      set {
+        a_ = value;
+      }
+    }
+
+    public const int IFieldNumber = 2;
+    private int i_;
+    public int I {
+      get { return i_; }
+      set {
+        i_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestRecursiveMessage);
+    }
+
+    public bool Equals(TestRecursiveMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(A, other.A)) return false;
+      if (I != other.I) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (a_ != null) hash ^= A.GetHashCode();
+      if (I != 0) hash ^= I.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (a_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(A);
+      }
+      if (I != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(I);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (a_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(A);
+      }
+      if (I != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(I);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestRecursiveMessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.a_ != null) {
+        if (a_ == null) {
+          a_ = new global::Google.Protobuf.TestProtos.TestRecursiveMessage();
+        }
+        A.MergeFrom(other.A);
+      }
+      if (other.I != 0) {
+        I = other.I;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            if (a_ == null) {
+              a_ = new global::Google.Protobuf.TestProtos.TestRecursiveMessage();
+            }
+            input.ReadMessage(a_);
+            break;
+          }
+          case 16: {
+            I = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestMutualRecursionA : pb::IMessage<TestMutualRecursionA> {
+    private static readonly pb::MessageParser<TestMutualRecursionA> _parser = new pb::MessageParser<TestMutualRecursionA>(() => new TestMutualRecursionA());
+    public static pb::MessageParser<TestMutualRecursionA> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[8]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestMutualRecursionA() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestMutualRecursionA(TestMutualRecursionA other) : this() {
+      Bb = other.bb_ != null ? other.Bb.Clone() : null;
+    }
+
+    public TestMutualRecursionA Clone() {
+      return new TestMutualRecursionA(this);
+    }
+
+    public const int BbFieldNumber = 1;
+    private global::Google.Protobuf.TestProtos.TestMutualRecursionB bb_;
+    public global::Google.Protobuf.TestProtos.TestMutualRecursionB Bb {
+      get { return bb_; }
+      set {
+        bb_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestMutualRecursionA);
+    }
+
+    public bool Equals(TestMutualRecursionA other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(Bb, other.Bb)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (bb_ != null) hash ^= Bb.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (bb_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(Bb);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (bb_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Bb);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestMutualRecursionA other) {
+      if (other == null) {
+        return;
+      }
+      if (other.bb_ != null) {
+        if (bb_ == null) {
+          bb_ = new global::Google.Protobuf.TestProtos.TestMutualRecursionB();
+        }
+        Bb.MergeFrom(other.Bb);
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            if (bb_ == null) {
+              bb_ = new global::Google.Protobuf.TestProtos.TestMutualRecursionB();
+            }
+            input.ReadMessage(bb_);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestMutualRecursionB : pb::IMessage<TestMutualRecursionB> {
+    private static readonly pb::MessageParser<TestMutualRecursionB> _parser = new pb::MessageParser<TestMutualRecursionB>(() => new TestMutualRecursionB());
+    public static pb::MessageParser<TestMutualRecursionB> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[9]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestMutualRecursionB() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestMutualRecursionB(TestMutualRecursionB other) : this() {
+      A = other.a_ != null ? other.A.Clone() : null;
+      optionalInt32_ = other.optionalInt32_;
+    }
+
+    public TestMutualRecursionB Clone() {
+      return new TestMutualRecursionB(this);
+    }
+
+    public const int AFieldNumber = 1;
+    private global::Google.Protobuf.TestProtos.TestMutualRecursionA a_;
+    public global::Google.Protobuf.TestProtos.TestMutualRecursionA A {
+      get { return a_; }
+      set {
+        a_ = value;
+      }
+    }
+
+    public const int OptionalInt32FieldNumber = 2;
+    private int optionalInt32_;
+    public int OptionalInt32 {
+      get { return optionalInt32_; }
+      set {
+        optionalInt32_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestMutualRecursionB);
+    }
+
+    public bool Equals(TestMutualRecursionB other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(A, other.A)) return false;
+      if (OptionalInt32 != other.OptionalInt32) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (a_ != null) hash ^= A.GetHashCode();
+      if (OptionalInt32 != 0) hash ^= OptionalInt32.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (a_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(A);
+      }
+      if (OptionalInt32 != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(OptionalInt32);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (a_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(A);
+      }
+      if (OptionalInt32 != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(OptionalInt32);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestMutualRecursionB other) {
+      if (other == null) {
+        return;
+      }
+      if (other.a_ != null) {
+        if (a_ == null) {
+          a_ = new global::Google.Protobuf.TestProtos.TestMutualRecursionA();
+        }
+        A.MergeFrom(other.A);
+      }
+      if (other.OptionalInt32 != 0) {
+        OptionalInt32 = other.OptionalInt32;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            if (a_ == null) {
+              a_ = new global::Google.Protobuf.TestProtos.TestMutualRecursionA();
+            }
+            input.ReadMessage(a_);
+            break;
+          }
+          case 16: {
+            OptionalInt32 = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestCamelCaseFieldNames : pb::IMessage<TestCamelCaseFieldNames> {
+    private static readonly pb::MessageParser<TestCamelCaseFieldNames> _parser = new pb::MessageParser<TestCamelCaseFieldNames>(() => new TestCamelCaseFieldNames());
+    public static pb::MessageParser<TestCamelCaseFieldNames> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[10]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestCamelCaseFieldNames() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestCamelCaseFieldNames(TestCamelCaseFieldNames other) : this() {
+      primitiveField_ = other.primitiveField_;
+      stringField_ = other.stringField_;
+      enumField_ = other.enumField_;
+      MessageField = other.messageField_ != null ? other.MessageField.Clone() : null;
+      repeatedPrimitiveField_ = other.repeatedPrimitiveField_.Clone();
+      repeatedStringField_ = other.repeatedStringField_.Clone();
+      repeatedEnumField_ = other.repeatedEnumField_.Clone();
+      repeatedMessageField_ = other.repeatedMessageField_.Clone();
+    }
+
+    public TestCamelCaseFieldNames Clone() {
+      return new TestCamelCaseFieldNames(this);
+    }
+
+    public const int PrimitiveFieldFieldNumber = 1;
+    private int primitiveField_;
+    public int PrimitiveField {
+      get { return primitiveField_; }
+      set {
+        primitiveField_ = value;
+      }
+    }
+
+    public const int StringFieldFieldNumber = 2;
+    private string stringField_ = "";
+    public string StringField {
+      get { return stringField_; }
+      set {
+        stringField_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public const int EnumFieldFieldNumber = 3;
+    private global::Google.Protobuf.TestProtos.ForeignEnum enumField_ = global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED;
+    public global::Google.Protobuf.TestProtos.ForeignEnum EnumField {
+      get { return enumField_; }
+      set {
+        enumField_ = value;
+      }
+    }
+
+    public const int MessageFieldFieldNumber = 4;
+    private global::Google.Protobuf.TestProtos.ForeignMessage messageField_;
+    public global::Google.Protobuf.TestProtos.ForeignMessage MessageField {
+      get { return messageField_; }
+      set {
+        messageField_ = value;
+      }
+    }
+
+    public const int RepeatedPrimitiveFieldFieldNumber = 7;
+    private static readonly pb::FieldCodec<int> _repeated_repeatedPrimitiveField_codec
+        = pb::FieldCodec.ForInt32(58);
+    private readonly pbc::RepeatedField<int> repeatedPrimitiveField_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> RepeatedPrimitiveField {
+      get { return repeatedPrimitiveField_; }
+    }
+
+    public const int RepeatedStringFieldFieldNumber = 8;
+    private static readonly pb::FieldCodec<string> _repeated_repeatedStringField_codec
+        = pb::FieldCodec.ForString(66);
+    private readonly pbc::RepeatedField<string> repeatedStringField_ = new pbc::RepeatedField<string>();
+    public pbc::RepeatedField<string> RepeatedStringField {
+      get { return repeatedStringField_; }
+    }
+
+    public const int RepeatedEnumFieldFieldNumber = 9;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.ForeignEnum> _repeated_repeatedEnumField_codec
+        = pb::FieldCodec.ForEnum(74, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> repeatedEnumField_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> RepeatedEnumField {
+      get { return repeatedEnumField_; }
+    }
+
+    public const int RepeatedMessageFieldFieldNumber = 10;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.ForeignMessage> _repeated_repeatedMessageField_codec
+        = pb::FieldCodec.ForMessage(82, global::Google.Protobuf.TestProtos.ForeignMessage.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignMessage> repeatedMessageField_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignMessage>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignMessage> RepeatedMessageField {
+      get { return repeatedMessageField_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestCamelCaseFieldNames);
+    }
+
+    public bool Equals(TestCamelCaseFieldNames other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (PrimitiveField != other.PrimitiveField) return false;
+      if (StringField != other.StringField) return false;
+      if (EnumField != other.EnumField) return false;
+      if (!object.Equals(MessageField, other.MessageField)) return false;
+      if(!repeatedPrimitiveField_.Equals(other.repeatedPrimitiveField_)) return false;
+      if(!repeatedStringField_.Equals(other.repeatedStringField_)) return false;
+      if(!repeatedEnumField_.Equals(other.repeatedEnumField_)) return false;
+      if(!repeatedMessageField_.Equals(other.repeatedMessageField_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      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();
+      if (messageField_ != null) hash ^= MessageField.GetHashCode();
+      hash ^= repeatedPrimitiveField_.GetHashCode();
+      hash ^= repeatedStringField_.GetHashCode();
+      hash ^= repeatedEnumField_.GetHashCode();
+      hash ^= repeatedMessageField_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (PrimitiveField != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(PrimitiveField);
+      }
+      if (StringField.Length != 0) {
+        output.WriteRawTag(18);
+        output.WriteString(StringField);
+      }
+      if (EnumField != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) {
+        output.WriteRawTag(24);
+        output.WriteEnum((int) EnumField);
+      }
+      if (messageField_ != null) {
+        output.WriteRawTag(34);
+        output.WriteMessage(MessageField);
+      }
+      repeatedPrimitiveField_.WriteTo(output, _repeated_repeatedPrimitiveField_codec);
+      repeatedStringField_.WriteTo(output, _repeated_repeatedStringField_codec);
+      repeatedEnumField_.WriteTo(output, _repeated_repeatedEnumField_codec);
+      repeatedMessageField_.WriteTo(output, _repeated_repeatedMessageField_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (PrimitiveField != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(PrimitiveField);
+      }
+      if (StringField.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(StringField);
+      }
+      if (EnumField != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) EnumField);
+      }
+      if (messageField_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(MessageField);
+      }
+      size += repeatedPrimitiveField_.CalculateSize(_repeated_repeatedPrimitiveField_codec);
+      size += repeatedStringField_.CalculateSize(_repeated_repeatedStringField_codec);
+      size += repeatedEnumField_.CalculateSize(_repeated_repeatedEnumField_codec);
+      size += repeatedMessageField_.CalculateSize(_repeated_repeatedMessageField_codec);
+      return size;
+    }
+
+    public void MergeFrom(TestCamelCaseFieldNames other) {
+      if (other == null) {
+        return;
+      }
+      if (other.PrimitiveField != 0) {
+        PrimitiveField = other.PrimitiveField;
+      }
+      if (other.StringField.Length != 0) {
+        StringField = other.StringField;
+      }
+      if (other.EnumField != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) {
+        EnumField = other.EnumField;
+      }
+      if (other.messageField_ != null) {
+        if (messageField_ == null) {
+          messageField_ = new global::Google.Protobuf.TestProtos.ForeignMessage();
+        }
+        MessageField.MergeFrom(other.MessageField);
+      }
+      repeatedPrimitiveField_.Add(other.repeatedPrimitiveField_);
+      repeatedStringField_.Add(other.repeatedStringField_);
+      repeatedEnumField_.Add(other.repeatedEnumField_);
+      repeatedMessageField_.Add(other.repeatedMessageField_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            PrimitiveField = input.ReadInt32();
+            break;
+          }
+          case 18: {
+            StringField = input.ReadString();
+            break;
+          }
+          case 24: {
+            enumField_ = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum();
+            break;
+          }
+          case 34: {
+            if (messageField_ == null) {
+              messageField_ = new global::Google.Protobuf.TestProtos.ForeignMessage();
+            }
+            input.ReadMessage(messageField_);
+            break;
+          }
+          case 58:
+          case 56: {
+            repeatedPrimitiveField_.AddEntriesFrom(input, _repeated_repeatedPrimitiveField_codec);
+            break;
+          }
+          case 66: {
+            repeatedStringField_.AddEntriesFrom(input, _repeated_repeatedStringField_codec);
+            break;
+          }
+          case 74:
+          case 72: {
+            repeatedEnumField_.AddEntriesFrom(input, _repeated_repeatedEnumField_codec);
+            break;
+          }
+          case 82: {
+            repeatedMessageField_.AddEntriesFrom(input, _repeated_repeatedMessageField_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestFieldOrderings : pb::IMessage<TestFieldOrderings> {
+    private static readonly pb::MessageParser<TestFieldOrderings> _parser = new pb::MessageParser<TestFieldOrderings>(() => new TestFieldOrderings());
+    public static pb::MessageParser<TestFieldOrderings> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[11]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestFieldOrderings() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestFieldOrderings(TestFieldOrderings other) : this() {
+      myString_ = other.myString_;
+      myInt_ = other.myInt_;
+      myFloat_ = other.myFloat_;
+      SingleNestedMessage = other.singleNestedMessage_ != null ? other.SingleNestedMessage.Clone() : null;
+    }
+
+    public TestFieldOrderings Clone() {
+      return new TestFieldOrderings(this);
+    }
+
+    public const int MyStringFieldNumber = 11;
+    private string myString_ = "";
+    public string MyString {
+      get { return myString_; }
+      set {
+        myString_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public const int MyIntFieldNumber = 1;
+    private long myInt_;
+    public long MyInt {
+      get { return myInt_; }
+      set {
+        myInt_ = value;
+      }
+    }
+
+    public const int MyFloatFieldNumber = 101;
+    private float myFloat_;
+    public float MyFloat {
+      get { return myFloat_; }
+      set {
+        myFloat_ = value;
+      }
+    }
+
+    public const int SingleNestedMessageFieldNumber = 200;
+    private global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage singleNestedMessage_;
+    public global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage SingleNestedMessage {
+      get { return singleNestedMessage_; }
+      set {
+        singleNestedMessage_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestFieldOrderings);
+    }
+
+    public bool Equals(TestFieldOrderings other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (MyString != other.MyString) return false;
+      if (MyInt != other.MyInt) return false;
+      if (MyFloat != other.MyFloat) return false;
+      if (!object.Equals(SingleNestedMessage, other.SingleNestedMessage)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (MyString.Length != 0) hash ^= MyString.GetHashCode();
+      if (MyInt != 0L) hash ^= MyInt.GetHashCode();
+      if (MyFloat != 0F) hash ^= MyFloat.GetHashCode();
+      if (singleNestedMessage_ != null) hash ^= SingleNestedMessage.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (MyInt != 0L) {
+        output.WriteRawTag(8);
+        output.WriteInt64(MyInt);
+      }
+      if (MyString.Length != 0) {
+        output.WriteRawTag(90);
+        output.WriteString(MyString);
+      }
+      if (MyFloat != 0F) {
+        output.WriteRawTag(173, 6);
+        output.WriteFloat(MyFloat);
+      }
+      if (singleNestedMessage_ != null) {
+        output.WriteRawTag(194, 12);
+        output.WriteMessage(SingleNestedMessage);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (MyString.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(MyString);
+      }
+      if (MyInt != 0L) {
+        size += 1 + pb::CodedOutputStream.ComputeInt64Size(MyInt);
+      }
+      if (MyFloat != 0F) {
+        size += 2 + 4;
+      }
+      if (singleNestedMessage_ != null) {
+        size += 2 + pb::CodedOutputStream.ComputeMessageSize(SingleNestedMessage);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestFieldOrderings other) {
+      if (other == null) {
+        return;
+      }
+      if (other.MyString.Length != 0) {
+        MyString = other.MyString;
+      }
+      if (other.MyInt != 0L) {
+        MyInt = other.MyInt;
+      }
+      if (other.MyFloat != 0F) {
+        MyFloat = other.MyFloat;
+      }
+      if (other.singleNestedMessage_ != null) {
+        if (singleNestedMessage_ == null) {
+          singleNestedMessage_ = new global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage();
+        }
+        SingleNestedMessage.MergeFrom(other.SingleNestedMessage);
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            MyInt = input.ReadInt64();
+            break;
+          }
+          case 90: {
+            MyString = input.ReadString();
+            break;
+          }
+          case 813: {
+            MyFloat = input.ReadFloat();
+            break;
+          }
+          case 1602: {
+            if (singleNestedMessage_ == null) {
+              singleNestedMessage_ = new global::Google.Protobuf.TestProtos.TestFieldOrderings.Types.NestedMessage();
+            }
+            input.ReadMessage(singleNestedMessage_);
+            break;
+          }
+        }
+      }
+    }
+
+    #region Nested types
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    public static partial class Types {
+      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+      public sealed partial class NestedMessage : pb::IMessage<NestedMessage> {
+        private static readonly pb::MessageParser<NestedMessage> _parser = new pb::MessageParser<NestedMessage>(() => new NestedMessage());
+        public static pb::MessageParser<NestedMessage> Parser { get { return _parser; } }
+
+        public static pbr::MessageDescriptor Descriptor {
+          get { return global::Google.Protobuf.TestProtos.TestFieldOrderings.Descriptor.NestedTypes[0]; }
+        }
+
+        pbr::MessageDescriptor pb::IMessage.Descriptor {
+          get { return Descriptor; }
+        }
+
+        public NestedMessage() {
+          OnConstruction();
+        }
+
+        partial void OnConstruction();
+
+        public NestedMessage(NestedMessage other) : this() {
+          oo_ = other.oo_;
+          bb_ = other.bb_;
+        }
+
+        public NestedMessage Clone() {
+          return new NestedMessage(this);
+        }
+
+        public const int OoFieldNumber = 2;
+        private long oo_;
+        public long Oo {
+          get { return oo_; }
+          set {
+            oo_ = value;
+          }
+        }
+
+        public const int BbFieldNumber = 1;
+        private int bb_;
+        public int Bb {
+          get { return bb_; }
+          set {
+            bb_ = value;
+          }
+        }
+
+        public override bool Equals(object other) {
+          return Equals(other as NestedMessage);
+        }
+
+        public bool Equals(NestedMessage other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Oo != other.Oo) return false;
+          if (Bb != other.Bb) return false;
+          return true;
+        }
+
+        public override int GetHashCode() {
+          int hash = 1;
+          if (Oo != 0L) hash ^= Oo.GetHashCode();
+          if (Bb != 0) hash ^= Bb.GetHashCode();
+          return hash;
+        }
+
+        public override string ToString() {
+          return pb::JsonFormatter.Default.Format(this);
+        }
+
+        public void WriteTo(pb::CodedOutputStream output) {
+          if (Bb != 0) {
+            output.WriteRawTag(8);
+            output.WriteInt32(Bb);
+          }
+          if (Oo != 0L) {
+            output.WriteRawTag(16);
+            output.WriteInt64(Oo);
+          }
+        }
+
+        public int CalculateSize() {
+          int size = 0;
+          if (Oo != 0L) {
+            size += 1 + pb::CodedOutputStream.ComputeInt64Size(Oo);
+          }
+          if (Bb != 0) {
+            size += 1 + pb::CodedOutputStream.ComputeInt32Size(Bb);
+          }
+          return size;
+        }
+
+        public void MergeFrom(NestedMessage other) {
+          if (other == null) {
+            return;
+          }
+          if (other.Oo != 0L) {
+            Oo = other.Oo;
+          }
+          if (other.Bb != 0) {
+            Bb = other.Bb;
+          }
+        }
+
+        public void MergeFrom(pb::CodedInputStream input) {
+          uint tag;
+          while ((tag = input.ReadTag()) != 0) {
+            switch(tag) {
+              default:
+                input.SkipLastField();
+                break;
+              case 8: {
+                Bb = input.ReadInt32();
+                break;
+              }
+              case 16: {
+                Oo = input.ReadInt64();
+                break;
+              }
+            }
+          }
+        }
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class SparseEnumMessage : pb::IMessage<SparseEnumMessage> {
+    private static readonly pb::MessageParser<SparseEnumMessage> _parser = new pb::MessageParser<SparseEnumMessage>(() => new SparseEnumMessage());
+    public static pb::MessageParser<SparseEnumMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[12]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public SparseEnumMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public SparseEnumMessage(SparseEnumMessage other) : this() {
+      sparseEnum_ = other.sparseEnum_;
+    }
+
+    public SparseEnumMessage Clone() {
+      return new SparseEnumMessage(this);
+    }
+
+    public const int SparseEnumFieldNumber = 1;
+    private global::Google.Protobuf.TestProtos.TestSparseEnum sparseEnum_ = global::Google.Protobuf.TestProtos.TestSparseEnum.TEST_SPARSE_ENUM_UNSPECIFIED;
+    public global::Google.Protobuf.TestProtos.TestSparseEnum SparseEnum {
+      get { return sparseEnum_; }
+      set {
+        sparseEnum_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as SparseEnumMessage);
+    }
+
+    public bool Equals(SparseEnumMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (SparseEnum != other.SparseEnum) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.TEST_SPARSE_ENUM_UNSPECIFIED) hash ^= SparseEnum.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.TEST_SPARSE_ENUM_UNSPECIFIED) {
+        output.WriteRawTag(8);
+        output.WriteEnum((int) SparseEnum);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.TEST_SPARSE_ENUM_UNSPECIFIED) {
+        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) SparseEnum);
+      }
+      return size;
+    }
+
+    public void MergeFrom(SparseEnumMessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.TEST_SPARSE_ENUM_UNSPECIFIED) {
+        SparseEnum = other.SparseEnum;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            sparseEnum_ = (global::Google.Protobuf.TestProtos.TestSparseEnum) input.ReadEnum();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class OneString : pb::IMessage<OneString> {
+    private static readonly pb::MessageParser<OneString> _parser = new pb::MessageParser<OneString>(() => new OneString());
+    public static pb::MessageParser<OneString> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[13]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public OneString() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public OneString(OneString other) : this() {
+      data_ = other.data_;
+    }
+
+    public OneString Clone() {
+      return new OneString(this);
+    }
+
+    public const int DataFieldNumber = 1;
+    private string data_ = "";
+    public string Data {
+      get { return data_; }
+      set {
+        data_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as OneString);
+    }
+
+    public bool Equals(OneString other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Data != other.Data) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Data.Length != 0) hash ^= Data.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Data.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(Data);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Data.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Data);
+      }
+      return size;
+    }
+
+    public void MergeFrom(OneString other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Data.Length != 0) {
+        Data = other.Data;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Data = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class MoreString : pb::IMessage<MoreString> {
+    private static readonly pb::MessageParser<MoreString> _parser = new pb::MessageParser<MoreString>(() => new MoreString());
+    public static pb::MessageParser<MoreString> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[14]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public MoreString() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public MoreString(MoreString other) : this() {
+      data_ = other.data_.Clone();
+    }
+
+    public MoreString Clone() {
+      return new MoreString(this);
+    }
+
+    public const int DataFieldNumber = 1;
+    private static readonly pb::FieldCodec<string> _repeated_data_codec
+        = pb::FieldCodec.ForString(10);
+    private readonly pbc::RepeatedField<string> data_ = new pbc::RepeatedField<string>();
+    public pbc::RepeatedField<string> Data {
+      get { return data_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as MoreString);
+    }
+
+    public bool Equals(MoreString other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!data_.Equals(other.data_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= data_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      data_.WriteTo(output, _repeated_data_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += data_.CalculateSize(_repeated_data_codec);
+      return size;
+    }
+
+    public void MergeFrom(MoreString other) {
+      if (other == null) {
+        return;
+      }
+      data_.Add(other.data_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            data_.AddEntriesFrom(input, _repeated_data_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class OneBytes : pb::IMessage<OneBytes> {
+    private static readonly pb::MessageParser<OneBytes> _parser = new pb::MessageParser<OneBytes>(() => new OneBytes());
+    public static pb::MessageParser<OneBytes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[15]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public OneBytes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public OneBytes(OneBytes other) : this() {
+      data_ = other.data_;
+    }
+
+    public OneBytes Clone() {
+      return new OneBytes(this);
+    }
+
+    public const int DataFieldNumber = 1;
+    private pb::ByteString data_ = pb::ByteString.Empty;
+    public pb::ByteString Data {
+      get { return data_; }
+      set {
+        data_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as OneBytes);
+    }
+
+    public bool Equals(OneBytes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Data != other.Data) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Data.Length != 0) hash ^= Data.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Data.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteBytes(Data);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Data.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeBytesSize(Data);
+      }
+      return size;
+    }
+
+    public void MergeFrom(OneBytes other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Data.Length != 0) {
+        Data = other.Data;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Data = input.ReadBytes();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class MoreBytes : pb::IMessage<MoreBytes> {
+    private static readonly pb::MessageParser<MoreBytes> _parser = new pb::MessageParser<MoreBytes>(() => new MoreBytes());
+    public static pb::MessageParser<MoreBytes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[16]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public MoreBytes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public MoreBytes(MoreBytes other) : this() {
+      data_ = other.data_;
+    }
+
+    public MoreBytes Clone() {
+      return new MoreBytes(this);
+    }
+
+    public const int DataFieldNumber = 1;
+    private pb::ByteString data_ = pb::ByteString.Empty;
+    public pb::ByteString Data {
+      get { return data_; }
+      set {
+        data_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as MoreBytes);
+    }
+
+    public bool Equals(MoreBytes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Data != other.Data) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Data.Length != 0) hash ^= Data.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Data.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteBytes(Data);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Data.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeBytesSize(Data);
+      }
+      return size;
+    }
+
+    public void MergeFrom(MoreBytes other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Data.Length != 0) {
+        Data = other.Data;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            Data = input.ReadBytes();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Int32Message : pb::IMessage<Int32Message> {
+    private static readonly pb::MessageParser<Int32Message> _parser = new pb::MessageParser<Int32Message>(() => new Int32Message());
+    public static pb::MessageParser<Int32Message> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[17]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Int32Message() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Int32Message(Int32Message other) : this() {
+      data_ = other.data_;
+    }
+
+    public Int32Message Clone() {
+      return new Int32Message(this);
+    }
+
+    public const int DataFieldNumber = 1;
+    private int data_;
+    public int Data {
+      get { return data_; }
+      set {
+        data_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Int32Message);
+    }
+
+    public bool Equals(Int32Message other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Data != other.Data) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Data != 0) hash ^= Data.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Data != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Data);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Data != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Data);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Int32Message other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Data != 0) {
+        Data = other.Data;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Data = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Uint32Message : pb::IMessage<Uint32Message> {
+    private static readonly pb::MessageParser<Uint32Message> _parser = new pb::MessageParser<Uint32Message>(() => new Uint32Message());
+    public static pb::MessageParser<Uint32Message> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[18]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Uint32Message() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Uint32Message(Uint32Message other) : this() {
+      data_ = other.data_;
+    }
+
+    public Uint32Message Clone() {
+      return new Uint32Message(this);
+    }
+
+    public const int DataFieldNumber = 1;
+    private uint data_;
+    public uint Data {
+      get { return data_; }
+      set {
+        data_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Uint32Message);
+    }
+
+    public bool Equals(Uint32Message other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Data != other.Data) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Data != 0) hash ^= Data.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Data != 0) {
+        output.WriteRawTag(8);
+        output.WriteUInt32(Data);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Data != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Data);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Uint32Message other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Data != 0) {
+        Data = other.Data;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Data = input.ReadUInt32();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Int64Message : pb::IMessage<Int64Message> {
+    private static readonly pb::MessageParser<Int64Message> _parser = new pb::MessageParser<Int64Message>(() => new Int64Message());
+    public static pb::MessageParser<Int64Message> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[19]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Int64Message() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Int64Message(Int64Message other) : this() {
+      data_ = other.data_;
+    }
+
+    public Int64Message Clone() {
+      return new Int64Message(this);
+    }
+
+    public const int DataFieldNumber = 1;
+    private long data_;
+    public long Data {
+      get { return data_; }
+      set {
+        data_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Int64Message);
+    }
+
+    public bool Equals(Int64Message other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Data != other.Data) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Data != 0L) hash ^= Data.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Data != 0L) {
+        output.WriteRawTag(8);
+        output.WriteInt64(Data);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Data != 0L) {
+        size += 1 + pb::CodedOutputStream.ComputeInt64Size(Data);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Int64Message other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Data != 0L) {
+        Data = other.Data;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Data = input.ReadInt64();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class Uint64Message : pb::IMessage<Uint64Message> {
+    private static readonly pb::MessageParser<Uint64Message> _parser = new pb::MessageParser<Uint64Message>(() => new Uint64Message());
+    public static pb::MessageParser<Uint64Message> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[20]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public Uint64Message() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public Uint64Message(Uint64Message other) : this() {
+      data_ = other.data_;
+    }
+
+    public Uint64Message Clone() {
+      return new Uint64Message(this);
+    }
+
+    public const int DataFieldNumber = 1;
+    private ulong data_;
+    public ulong Data {
+      get { return data_; }
+      set {
+        data_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as Uint64Message);
+    }
+
+    public bool Equals(Uint64Message other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Data != other.Data) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Data != 0UL) hash ^= Data.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Data != 0UL) {
+        output.WriteRawTag(8);
+        output.WriteUInt64(Data);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Data != 0UL) {
+        size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Data);
+      }
+      return size;
+    }
+
+    public void MergeFrom(Uint64Message other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Data != 0UL) {
+        Data = other.Data;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Data = input.ReadUInt64();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class BoolMessage : pb::IMessage<BoolMessage> {
+    private static readonly pb::MessageParser<BoolMessage> _parser = new pb::MessageParser<BoolMessage>(() => new BoolMessage());
+    public static pb::MessageParser<BoolMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[21]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public BoolMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public BoolMessage(BoolMessage other) : this() {
+      data_ = other.data_;
+    }
+
+    public BoolMessage Clone() {
+      return new BoolMessage(this);
+    }
+
+    public const int DataFieldNumber = 1;
+    private bool data_;
+    public bool Data {
+      get { return data_; }
+      set {
+        data_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as BoolMessage);
+    }
+
+    public bool Equals(BoolMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Data != other.Data) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (Data != false) hash ^= Data.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (Data != false) {
+        output.WriteRawTag(8);
+        output.WriteBool(Data);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (Data != false) {
+        size += 1 + 1;
+      }
+      return size;
+    }
+
+    public void MergeFrom(BoolMessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.Data != false) {
+        Data = other.Data;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            Data = input.ReadBool();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestOneof : pb::IMessage<TestOneof> {
+    private static readonly pb::MessageParser<TestOneof> _parser = new pb::MessageParser<TestOneof>(() => new TestOneof());
+    public static pb::MessageParser<TestOneof> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[22]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestOneof() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestOneof(TestOneof other) : this() {
+      switch (other.FooCase) {
+        case FooOneofCase.FooInt:
+          FooInt = other.FooInt;
+          break;
+        case FooOneofCase.FooString:
+          FooString = other.FooString;
+          break;
+        case FooOneofCase.FooMessage:
+          FooMessage = other.FooMessage.Clone();
+          break;
+      }
+
+    }
+
+    public TestOneof Clone() {
+      return new TestOneof(this);
+    }
+
+    public const int FooIntFieldNumber = 1;
+    public int FooInt {
+      get { return fooCase_ == FooOneofCase.FooInt ? (int) foo_ : 0; }
+      set {
+        foo_ = value;
+        fooCase_ = FooOneofCase.FooInt;
+      }
+    }
+
+    public const int FooStringFieldNumber = 2;
+    public string FooString {
+      get { return fooCase_ == FooOneofCase.FooString ? (string) foo_ : ""; }
+      set {
+        foo_ = pb::Preconditions.CheckNotNull(value, "value");
+        fooCase_ = FooOneofCase.FooString;
+      }
+    }
+
+    public const int FooMessageFieldNumber = 3;
+    public global::Google.Protobuf.TestProtos.TestAllTypes FooMessage {
+      get { return fooCase_ == FooOneofCase.FooMessage ? (global::Google.Protobuf.TestProtos.TestAllTypes) foo_ : null; }
+      set {
+        foo_ = value;
+        fooCase_ = value == null ? FooOneofCase.None : FooOneofCase.FooMessage;
+      }
+    }
+
+    private object foo_;
+    public enum FooOneofCase {
+      None = 0,
+      FooInt = 1,
+      FooString = 2,
+      FooMessage = 3,
+    }
+    private FooOneofCase fooCase_ = FooOneofCase.None;
+    public FooOneofCase FooCase {
+      get { return fooCase_; }
+    }
+
+    public void ClearFoo() {
+      fooCase_ = FooOneofCase.None;
+      foo_ = null;
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestOneof);
+    }
+
+    public bool Equals(TestOneof other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (FooInt != other.FooInt) return false;
+      if (FooString != other.FooString) return false;
+      if (!object.Equals(FooMessage, other.FooMessage)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (fooCase_ == FooOneofCase.FooInt) hash ^= FooInt.GetHashCode();
+      if (fooCase_ == FooOneofCase.FooString) hash ^= FooString.GetHashCode();
+      if (fooCase_ == FooOneofCase.FooMessage) hash ^= FooMessage.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (fooCase_ == FooOneofCase.FooInt) {
+        output.WriteRawTag(8);
+        output.WriteInt32(FooInt);
+      }
+      if (fooCase_ == FooOneofCase.FooString) {
+        output.WriteRawTag(18);
+        output.WriteString(FooString);
+      }
+      if (fooCase_ == FooOneofCase.FooMessage) {
+        output.WriteRawTag(26);
+        output.WriteMessage(FooMessage);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (fooCase_ == FooOneofCase.FooInt) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(FooInt);
+      }
+      if (fooCase_ == FooOneofCase.FooString) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(FooString);
+      }
+      if (fooCase_ == FooOneofCase.FooMessage) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(FooMessage);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestOneof other) {
+      if (other == null) {
+        return;
+      }
+      switch (other.FooCase) {
+        case FooOneofCase.FooInt:
+          FooInt = other.FooInt;
+          break;
+        case FooOneofCase.FooString:
+          FooString = other.FooString;
+          break;
+        case FooOneofCase.FooMessage:
+          FooMessage = other.FooMessage;
+          break;
+      }
+
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 8: {
+            FooInt = input.ReadInt32();
+            break;
+          }
+          case 18: {
+            FooString = input.ReadString();
+            break;
+          }
+          case 26: {
+            global::Google.Protobuf.TestProtos.TestAllTypes subBuilder = new global::Google.Protobuf.TestProtos.TestAllTypes();
+            if (fooCase_ == FooOneofCase.FooMessage) {
+              subBuilder.MergeFrom(FooMessage);
+            }
+            input.ReadMessage(subBuilder);
+            FooMessage = subBuilder;
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestPackedTypes : pb::IMessage<TestPackedTypes> {
+    private static readonly pb::MessageParser<TestPackedTypes> _parser = new pb::MessageParser<TestPackedTypes>(() => new TestPackedTypes());
+    public static pb::MessageParser<TestPackedTypes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[23]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestPackedTypes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestPackedTypes(TestPackedTypes other) : this() {
+      packedInt32_ = other.packedInt32_.Clone();
+      packedInt64_ = other.packedInt64_.Clone();
+      packedUint32_ = other.packedUint32_.Clone();
+      packedUint64_ = other.packedUint64_.Clone();
+      packedSint32_ = other.packedSint32_.Clone();
+      packedSint64_ = other.packedSint64_.Clone();
+      packedFixed32_ = other.packedFixed32_.Clone();
+      packedFixed64_ = other.packedFixed64_.Clone();
+      packedSfixed32_ = other.packedSfixed32_.Clone();
+      packedSfixed64_ = other.packedSfixed64_.Clone();
+      packedFloat_ = other.packedFloat_.Clone();
+      packedDouble_ = other.packedDouble_.Clone();
+      packedBool_ = other.packedBool_.Clone();
+      packedEnum_ = other.packedEnum_.Clone();
+    }
+
+    public TestPackedTypes Clone() {
+      return new TestPackedTypes(this);
+    }
+
+    public const int PackedInt32FieldNumber = 90;
+    private static readonly pb::FieldCodec<int> _repeated_packedInt32_codec
+        = pb::FieldCodec.ForInt32(722);
+    private readonly pbc::RepeatedField<int> packedInt32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> PackedInt32 {
+      get { return packedInt32_; }
+    }
+
+    public const int PackedInt64FieldNumber = 91;
+    private static readonly pb::FieldCodec<long> _repeated_packedInt64_codec
+        = pb::FieldCodec.ForInt64(730);
+    private readonly pbc::RepeatedField<long> packedInt64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> PackedInt64 {
+      get { return packedInt64_; }
+    }
+
+    public const int PackedUint32FieldNumber = 92;
+    private static readonly pb::FieldCodec<uint> _repeated_packedUint32_codec
+        = pb::FieldCodec.ForUInt32(738);
+    private readonly pbc::RepeatedField<uint> packedUint32_ = new pbc::RepeatedField<uint>();
+    public pbc::RepeatedField<uint> PackedUint32 {
+      get { return packedUint32_; }
+    }
+
+    public const int PackedUint64FieldNumber = 93;
+    private static readonly pb::FieldCodec<ulong> _repeated_packedUint64_codec
+        = pb::FieldCodec.ForUInt64(746);
+    private readonly pbc::RepeatedField<ulong> packedUint64_ = new pbc::RepeatedField<ulong>();
+    public pbc::RepeatedField<ulong> PackedUint64 {
+      get { return packedUint64_; }
+    }
+
+    public const int PackedSint32FieldNumber = 94;
+    private static readonly pb::FieldCodec<int> _repeated_packedSint32_codec
+        = pb::FieldCodec.ForSInt32(754);
+    private readonly pbc::RepeatedField<int> packedSint32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> PackedSint32 {
+      get { return packedSint32_; }
+    }
+
+    public const int PackedSint64FieldNumber = 95;
+    private static readonly pb::FieldCodec<long> _repeated_packedSint64_codec
+        = pb::FieldCodec.ForSInt64(762);
+    private readonly pbc::RepeatedField<long> packedSint64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> PackedSint64 {
+      get { return packedSint64_; }
+    }
+
+    public const int PackedFixed32FieldNumber = 96;
+    private static readonly pb::FieldCodec<uint> _repeated_packedFixed32_codec
+        = pb::FieldCodec.ForFixed32(770);
+    private readonly pbc::RepeatedField<uint> packedFixed32_ = new pbc::RepeatedField<uint>();
+    public pbc::RepeatedField<uint> PackedFixed32 {
+      get { return packedFixed32_; }
+    }
+
+    public const int PackedFixed64FieldNumber = 97;
+    private static readonly pb::FieldCodec<ulong> _repeated_packedFixed64_codec
+        = pb::FieldCodec.ForFixed64(778);
+    private readonly pbc::RepeatedField<ulong> packedFixed64_ = new pbc::RepeatedField<ulong>();
+    public pbc::RepeatedField<ulong> PackedFixed64 {
+      get { return packedFixed64_; }
+    }
+
+    public const int PackedSfixed32FieldNumber = 98;
+    private static readonly pb::FieldCodec<int> _repeated_packedSfixed32_codec
+        = pb::FieldCodec.ForSFixed32(786);
+    private readonly pbc::RepeatedField<int> packedSfixed32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> PackedSfixed32 {
+      get { return packedSfixed32_; }
+    }
+
+    public const int PackedSfixed64FieldNumber = 99;
+    private static readonly pb::FieldCodec<long> _repeated_packedSfixed64_codec
+        = pb::FieldCodec.ForSFixed64(794);
+    private readonly pbc::RepeatedField<long> packedSfixed64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> PackedSfixed64 {
+      get { return packedSfixed64_; }
+    }
+
+    public const int PackedFloatFieldNumber = 100;
+    private static readonly pb::FieldCodec<float> _repeated_packedFloat_codec
+        = pb::FieldCodec.ForFloat(802);
+    private readonly pbc::RepeatedField<float> packedFloat_ = new pbc::RepeatedField<float>();
+    public pbc::RepeatedField<float> PackedFloat {
+      get { return packedFloat_; }
+    }
+
+    public const int PackedDoubleFieldNumber = 101;
+    private static readonly pb::FieldCodec<double> _repeated_packedDouble_codec
+        = pb::FieldCodec.ForDouble(810);
+    private readonly pbc::RepeatedField<double> packedDouble_ = new pbc::RepeatedField<double>();
+    public pbc::RepeatedField<double> PackedDouble {
+      get { return packedDouble_; }
+    }
+
+    public const int PackedBoolFieldNumber = 102;
+    private static readonly pb::FieldCodec<bool> _repeated_packedBool_codec
+        = pb::FieldCodec.ForBool(818);
+    private readonly pbc::RepeatedField<bool> packedBool_ = new pbc::RepeatedField<bool>();
+    public pbc::RepeatedField<bool> PackedBool {
+      get { return packedBool_; }
+    }
+
+    public const int PackedEnumFieldNumber = 103;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.ForeignEnum> _repeated_packedEnum_codec
+        = pb::FieldCodec.ForEnum(826, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> packedEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> PackedEnum {
+      get { return packedEnum_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestPackedTypes);
+    }
+
+    public bool Equals(TestPackedTypes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!packedInt32_.Equals(other.packedInt32_)) return false;
+      if(!packedInt64_.Equals(other.packedInt64_)) return false;
+      if(!packedUint32_.Equals(other.packedUint32_)) return false;
+      if(!packedUint64_.Equals(other.packedUint64_)) return false;
+      if(!packedSint32_.Equals(other.packedSint32_)) return false;
+      if(!packedSint64_.Equals(other.packedSint64_)) return false;
+      if(!packedFixed32_.Equals(other.packedFixed32_)) return false;
+      if(!packedFixed64_.Equals(other.packedFixed64_)) return false;
+      if(!packedSfixed32_.Equals(other.packedSfixed32_)) return false;
+      if(!packedSfixed64_.Equals(other.packedSfixed64_)) return false;
+      if(!packedFloat_.Equals(other.packedFloat_)) return false;
+      if(!packedDouble_.Equals(other.packedDouble_)) return false;
+      if(!packedBool_.Equals(other.packedBool_)) return false;
+      if(!packedEnum_.Equals(other.packedEnum_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= packedInt32_.GetHashCode();
+      hash ^= packedInt64_.GetHashCode();
+      hash ^= packedUint32_.GetHashCode();
+      hash ^= packedUint64_.GetHashCode();
+      hash ^= packedSint32_.GetHashCode();
+      hash ^= packedSint64_.GetHashCode();
+      hash ^= packedFixed32_.GetHashCode();
+      hash ^= packedFixed64_.GetHashCode();
+      hash ^= packedSfixed32_.GetHashCode();
+      hash ^= packedSfixed64_.GetHashCode();
+      hash ^= packedFloat_.GetHashCode();
+      hash ^= packedDouble_.GetHashCode();
+      hash ^= packedBool_.GetHashCode();
+      hash ^= packedEnum_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      packedInt32_.WriteTo(output, _repeated_packedInt32_codec);
+      packedInt64_.WriteTo(output, _repeated_packedInt64_codec);
+      packedUint32_.WriteTo(output, _repeated_packedUint32_codec);
+      packedUint64_.WriteTo(output, _repeated_packedUint64_codec);
+      packedSint32_.WriteTo(output, _repeated_packedSint32_codec);
+      packedSint64_.WriteTo(output, _repeated_packedSint64_codec);
+      packedFixed32_.WriteTo(output, _repeated_packedFixed32_codec);
+      packedFixed64_.WriteTo(output, _repeated_packedFixed64_codec);
+      packedSfixed32_.WriteTo(output, _repeated_packedSfixed32_codec);
+      packedSfixed64_.WriteTo(output, _repeated_packedSfixed64_codec);
+      packedFloat_.WriteTo(output, _repeated_packedFloat_codec);
+      packedDouble_.WriteTo(output, _repeated_packedDouble_codec);
+      packedBool_.WriteTo(output, _repeated_packedBool_codec);
+      packedEnum_.WriteTo(output, _repeated_packedEnum_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += packedInt32_.CalculateSize(_repeated_packedInt32_codec);
+      size += packedInt64_.CalculateSize(_repeated_packedInt64_codec);
+      size += packedUint32_.CalculateSize(_repeated_packedUint32_codec);
+      size += packedUint64_.CalculateSize(_repeated_packedUint64_codec);
+      size += packedSint32_.CalculateSize(_repeated_packedSint32_codec);
+      size += packedSint64_.CalculateSize(_repeated_packedSint64_codec);
+      size += packedFixed32_.CalculateSize(_repeated_packedFixed32_codec);
+      size += packedFixed64_.CalculateSize(_repeated_packedFixed64_codec);
+      size += packedSfixed32_.CalculateSize(_repeated_packedSfixed32_codec);
+      size += packedSfixed64_.CalculateSize(_repeated_packedSfixed64_codec);
+      size += packedFloat_.CalculateSize(_repeated_packedFloat_codec);
+      size += packedDouble_.CalculateSize(_repeated_packedDouble_codec);
+      size += packedBool_.CalculateSize(_repeated_packedBool_codec);
+      size += packedEnum_.CalculateSize(_repeated_packedEnum_codec);
+      return size;
+    }
+
+    public void MergeFrom(TestPackedTypes other) {
+      if (other == null) {
+        return;
+      }
+      packedInt32_.Add(other.packedInt32_);
+      packedInt64_.Add(other.packedInt64_);
+      packedUint32_.Add(other.packedUint32_);
+      packedUint64_.Add(other.packedUint64_);
+      packedSint32_.Add(other.packedSint32_);
+      packedSint64_.Add(other.packedSint64_);
+      packedFixed32_.Add(other.packedFixed32_);
+      packedFixed64_.Add(other.packedFixed64_);
+      packedSfixed32_.Add(other.packedSfixed32_);
+      packedSfixed64_.Add(other.packedSfixed64_);
+      packedFloat_.Add(other.packedFloat_);
+      packedDouble_.Add(other.packedDouble_);
+      packedBool_.Add(other.packedBool_);
+      packedEnum_.Add(other.packedEnum_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 722:
+          case 720: {
+            packedInt32_.AddEntriesFrom(input, _repeated_packedInt32_codec);
+            break;
+          }
+          case 730:
+          case 728: {
+            packedInt64_.AddEntriesFrom(input, _repeated_packedInt64_codec);
+            break;
+          }
+          case 738:
+          case 736: {
+            packedUint32_.AddEntriesFrom(input, _repeated_packedUint32_codec);
+            break;
+          }
+          case 746:
+          case 744: {
+            packedUint64_.AddEntriesFrom(input, _repeated_packedUint64_codec);
+            break;
+          }
+          case 754:
+          case 752: {
+            packedSint32_.AddEntriesFrom(input, _repeated_packedSint32_codec);
+            break;
+          }
+          case 762:
+          case 760: {
+            packedSint64_.AddEntriesFrom(input, _repeated_packedSint64_codec);
+            break;
+          }
+          case 770:
+          case 773: {
+            packedFixed32_.AddEntriesFrom(input, _repeated_packedFixed32_codec);
+            break;
+          }
+          case 778:
+          case 777: {
+            packedFixed64_.AddEntriesFrom(input, _repeated_packedFixed64_codec);
+            break;
+          }
+          case 786:
+          case 789: {
+            packedSfixed32_.AddEntriesFrom(input, _repeated_packedSfixed32_codec);
+            break;
+          }
+          case 794:
+          case 793: {
+            packedSfixed64_.AddEntriesFrom(input, _repeated_packedSfixed64_codec);
+            break;
+          }
+          case 802:
+          case 805: {
+            packedFloat_.AddEntriesFrom(input, _repeated_packedFloat_codec);
+            break;
+          }
+          case 810:
+          case 809: {
+            packedDouble_.AddEntriesFrom(input, _repeated_packedDouble_codec);
+            break;
+          }
+          case 818:
+          case 816: {
+            packedBool_.AddEntriesFrom(input, _repeated_packedBool_codec);
+            break;
+          }
+          case 826:
+          case 824: {
+            packedEnum_.AddEntriesFrom(input, _repeated_packedEnum_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestUnpackedTypes : pb::IMessage<TestUnpackedTypes> {
+    private static readonly pb::MessageParser<TestUnpackedTypes> _parser = new pb::MessageParser<TestUnpackedTypes>(() => new TestUnpackedTypes());
+    public static pb::MessageParser<TestUnpackedTypes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[24]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestUnpackedTypes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestUnpackedTypes(TestUnpackedTypes other) : this() {
+      unpackedInt32_ = other.unpackedInt32_.Clone();
+      unpackedInt64_ = other.unpackedInt64_.Clone();
+      unpackedUint32_ = other.unpackedUint32_.Clone();
+      unpackedUint64_ = other.unpackedUint64_.Clone();
+      unpackedSint32_ = other.unpackedSint32_.Clone();
+      unpackedSint64_ = other.unpackedSint64_.Clone();
+      unpackedFixed32_ = other.unpackedFixed32_.Clone();
+      unpackedFixed64_ = other.unpackedFixed64_.Clone();
+      unpackedSfixed32_ = other.unpackedSfixed32_.Clone();
+      unpackedSfixed64_ = other.unpackedSfixed64_.Clone();
+      unpackedFloat_ = other.unpackedFloat_.Clone();
+      unpackedDouble_ = other.unpackedDouble_.Clone();
+      unpackedBool_ = other.unpackedBool_.Clone();
+      unpackedEnum_ = other.unpackedEnum_.Clone();
+    }
+
+    public TestUnpackedTypes Clone() {
+      return new TestUnpackedTypes(this);
+    }
+
+    public const int UnpackedInt32FieldNumber = 90;
+    private static readonly pb::FieldCodec<int> _repeated_unpackedInt32_codec
+        = pb::FieldCodec.ForInt32(720);
+    private readonly pbc::RepeatedField<int> unpackedInt32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> UnpackedInt32 {
+      get { return unpackedInt32_; }
+    }
+
+    public const int UnpackedInt64FieldNumber = 91;
+    private static readonly pb::FieldCodec<long> _repeated_unpackedInt64_codec
+        = pb::FieldCodec.ForInt64(728);
+    private readonly pbc::RepeatedField<long> unpackedInt64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> UnpackedInt64 {
+      get { return unpackedInt64_; }
+    }
+
+    public const int UnpackedUint32FieldNumber = 92;
+    private static readonly pb::FieldCodec<uint> _repeated_unpackedUint32_codec
+        = pb::FieldCodec.ForUInt32(736);
+    private readonly pbc::RepeatedField<uint> unpackedUint32_ = new pbc::RepeatedField<uint>();
+    public pbc::RepeatedField<uint> UnpackedUint32 {
+      get { return unpackedUint32_; }
+    }
+
+    public const int UnpackedUint64FieldNumber = 93;
+    private static readonly pb::FieldCodec<ulong> _repeated_unpackedUint64_codec
+        = pb::FieldCodec.ForUInt64(744);
+    private readonly pbc::RepeatedField<ulong> unpackedUint64_ = new pbc::RepeatedField<ulong>();
+    public pbc::RepeatedField<ulong> UnpackedUint64 {
+      get { return unpackedUint64_; }
+    }
+
+    public const int UnpackedSint32FieldNumber = 94;
+    private static readonly pb::FieldCodec<int> _repeated_unpackedSint32_codec
+        = pb::FieldCodec.ForSInt32(752);
+    private readonly pbc::RepeatedField<int> unpackedSint32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> UnpackedSint32 {
+      get { return unpackedSint32_; }
+    }
+
+    public const int UnpackedSint64FieldNumber = 95;
+    private static readonly pb::FieldCodec<long> _repeated_unpackedSint64_codec
+        = pb::FieldCodec.ForSInt64(760);
+    private readonly pbc::RepeatedField<long> unpackedSint64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> UnpackedSint64 {
+      get { return unpackedSint64_; }
+    }
+
+    public const int UnpackedFixed32FieldNumber = 96;
+    private static readonly pb::FieldCodec<uint> _repeated_unpackedFixed32_codec
+        = pb::FieldCodec.ForFixed32(773);
+    private readonly pbc::RepeatedField<uint> unpackedFixed32_ = new pbc::RepeatedField<uint>();
+    public pbc::RepeatedField<uint> UnpackedFixed32 {
+      get { return unpackedFixed32_; }
+    }
+
+    public const int UnpackedFixed64FieldNumber = 97;
+    private static readonly pb::FieldCodec<ulong> _repeated_unpackedFixed64_codec
+        = pb::FieldCodec.ForFixed64(777);
+    private readonly pbc::RepeatedField<ulong> unpackedFixed64_ = new pbc::RepeatedField<ulong>();
+    public pbc::RepeatedField<ulong> UnpackedFixed64 {
+      get { return unpackedFixed64_; }
+    }
+
+    public const int UnpackedSfixed32FieldNumber = 98;
+    private static readonly pb::FieldCodec<int> _repeated_unpackedSfixed32_codec
+        = pb::FieldCodec.ForSFixed32(789);
+    private readonly pbc::RepeatedField<int> unpackedSfixed32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> UnpackedSfixed32 {
+      get { return unpackedSfixed32_; }
+    }
+
+    public const int UnpackedSfixed64FieldNumber = 99;
+    private static readonly pb::FieldCodec<long> _repeated_unpackedSfixed64_codec
+        = pb::FieldCodec.ForSFixed64(793);
+    private readonly pbc::RepeatedField<long> unpackedSfixed64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> UnpackedSfixed64 {
+      get { return unpackedSfixed64_; }
+    }
+
+    public const int UnpackedFloatFieldNumber = 100;
+    private static readonly pb::FieldCodec<float> _repeated_unpackedFloat_codec
+        = pb::FieldCodec.ForFloat(805);
+    private readonly pbc::RepeatedField<float> unpackedFloat_ = new pbc::RepeatedField<float>();
+    public pbc::RepeatedField<float> UnpackedFloat {
+      get { return unpackedFloat_; }
+    }
+
+    public const int UnpackedDoubleFieldNumber = 101;
+    private static readonly pb::FieldCodec<double> _repeated_unpackedDouble_codec
+        = pb::FieldCodec.ForDouble(809);
+    private readonly pbc::RepeatedField<double> unpackedDouble_ = new pbc::RepeatedField<double>();
+    public pbc::RepeatedField<double> UnpackedDouble {
+      get { return unpackedDouble_; }
+    }
+
+    public const int UnpackedBoolFieldNumber = 102;
+    private static readonly pb::FieldCodec<bool> _repeated_unpackedBool_codec
+        = pb::FieldCodec.ForBool(816);
+    private readonly pbc::RepeatedField<bool> unpackedBool_ = new pbc::RepeatedField<bool>();
+    public pbc::RepeatedField<bool> UnpackedBool {
+      get { return unpackedBool_; }
+    }
+
+    public const int UnpackedEnumFieldNumber = 103;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.TestProtos.ForeignEnum> _repeated_unpackedEnum_codec
+        = pb::FieldCodec.ForEnum(824, x => (int) x, x => (global::Google.Protobuf.TestProtos.ForeignEnum) x);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> unpackedEnum_ = new pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum>();
+    public pbc::RepeatedField<global::Google.Protobuf.TestProtos.ForeignEnum> UnpackedEnum {
+      get { return unpackedEnum_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestUnpackedTypes);
+    }
+
+    public bool Equals(TestUnpackedTypes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!unpackedInt32_.Equals(other.unpackedInt32_)) return false;
+      if(!unpackedInt64_.Equals(other.unpackedInt64_)) return false;
+      if(!unpackedUint32_.Equals(other.unpackedUint32_)) return false;
+      if(!unpackedUint64_.Equals(other.unpackedUint64_)) return false;
+      if(!unpackedSint32_.Equals(other.unpackedSint32_)) return false;
+      if(!unpackedSint64_.Equals(other.unpackedSint64_)) return false;
+      if(!unpackedFixed32_.Equals(other.unpackedFixed32_)) return false;
+      if(!unpackedFixed64_.Equals(other.unpackedFixed64_)) return false;
+      if(!unpackedSfixed32_.Equals(other.unpackedSfixed32_)) return false;
+      if(!unpackedSfixed64_.Equals(other.unpackedSfixed64_)) return false;
+      if(!unpackedFloat_.Equals(other.unpackedFloat_)) return false;
+      if(!unpackedDouble_.Equals(other.unpackedDouble_)) return false;
+      if(!unpackedBool_.Equals(other.unpackedBool_)) return false;
+      if(!unpackedEnum_.Equals(other.unpackedEnum_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= unpackedInt32_.GetHashCode();
+      hash ^= unpackedInt64_.GetHashCode();
+      hash ^= unpackedUint32_.GetHashCode();
+      hash ^= unpackedUint64_.GetHashCode();
+      hash ^= unpackedSint32_.GetHashCode();
+      hash ^= unpackedSint64_.GetHashCode();
+      hash ^= unpackedFixed32_.GetHashCode();
+      hash ^= unpackedFixed64_.GetHashCode();
+      hash ^= unpackedSfixed32_.GetHashCode();
+      hash ^= unpackedSfixed64_.GetHashCode();
+      hash ^= unpackedFloat_.GetHashCode();
+      hash ^= unpackedDouble_.GetHashCode();
+      hash ^= unpackedBool_.GetHashCode();
+      hash ^= unpackedEnum_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      unpackedInt32_.WriteTo(output, _repeated_unpackedInt32_codec);
+      unpackedInt64_.WriteTo(output, _repeated_unpackedInt64_codec);
+      unpackedUint32_.WriteTo(output, _repeated_unpackedUint32_codec);
+      unpackedUint64_.WriteTo(output, _repeated_unpackedUint64_codec);
+      unpackedSint32_.WriteTo(output, _repeated_unpackedSint32_codec);
+      unpackedSint64_.WriteTo(output, _repeated_unpackedSint64_codec);
+      unpackedFixed32_.WriteTo(output, _repeated_unpackedFixed32_codec);
+      unpackedFixed64_.WriteTo(output, _repeated_unpackedFixed64_codec);
+      unpackedSfixed32_.WriteTo(output, _repeated_unpackedSfixed32_codec);
+      unpackedSfixed64_.WriteTo(output, _repeated_unpackedSfixed64_codec);
+      unpackedFloat_.WriteTo(output, _repeated_unpackedFloat_codec);
+      unpackedDouble_.WriteTo(output, _repeated_unpackedDouble_codec);
+      unpackedBool_.WriteTo(output, _repeated_unpackedBool_codec);
+      unpackedEnum_.WriteTo(output, _repeated_unpackedEnum_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += unpackedInt32_.CalculateSize(_repeated_unpackedInt32_codec);
+      size += unpackedInt64_.CalculateSize(_repeated_unpackedInt64_codec);
+      size += unpackedUint32_.CalculateSize(_repeated_unpackedUint32_codec);
+      size += unpackedUint64_.CalculateSize(_repeated_unpackedUint64_codec);
+      size += unpackedSint32_.CalculateSize(_repeated_unpackedSint32_codec);
+      size += unpackedSint64_.CalculateSize(_repeated_unpackedSint64_codec);
+      size += unpackedFixed32_.CalculateSize(_repeated_unpackedFixed32_codec);
+      size += unpackedFixed64_.CalculateSize(_repeated_unpackedFixed64_codec);
+      size += unpackedSfixed32_.CalculateSize(_repeated_unpackedSfixed32_codec);
+      size += unpackedSfixed64_.CalculateSize(_repeated_unpackedSfixed64_codec);
+      size += unpackedFloat_.CalculateSize(_repeated_unpackedFloat_codec);
+      size += unpackedDouble_.CalculateSize(_repeated_unpackedDouble_codec);
+      size += unpackedBool_.CalculateSize(_repeated_unpackedBool_codec);
+      size += unpackedEnum_.CalculateSize(_repeated_unpackedEnum_codec);
+      return size;
+    }
+
+    public void MergeFrom(TestUnpackedTypes other) {
+      if (other == null) {
+        return;
+      }
+      unpackedInt32_.Add(other.unpackedInt32_);
+      unpackedInt64_.Add(other.unpackedInt64_);
+      unpackedUint32_.Add(other.unpackedUint32_);
+      unpackedUint64_.Add(other.unpackedUint64_);
+      unpackedSint32_.Add(other.unpackedSint32_);
+      unpackedSint64_.Add(other.unpackedSint64_);
+      unpackedFixed32_.Add(other.unpackedFixed32_);
+      unpackedFixed64_.Add(other.unpackedFixed64_);
+      unpackedSfixed32_.Add(other.unpackedSfixed32_);
+      unpackedSfixed64_.Add(other.unpackedSfixed64_);
+      unpackedFloat_.Add(other.unpackedFloat_);
+      unpackedDouble_.Add(other.unpackedDouble_);
+      unpackedBool_.Add(other.unpackedBool_);
+      unpackedEnum_.Add(other.unpackedEnum_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 722:
+          case 720: {
+            unpackedInt32_.AddEntriesFrom(input, _repeated_unpackedInt32_codec);
+            break;
+          }
+          case 730:
+          case 728: {
+            unpackedInt64_.AddEntriesFrom(input, _repeated_unpackedInt64_codec);
+            break;
+          }
+          case 738:
+          case 736: {
+            unpackedUint32_.AddEntriesFrom(input, _repeated_unpackedUint32_codec);
+            break;
+          }
+          case 746:
+          case 744: {
+            unpackedUint64_.AddEntriesFrom(input, _repeated_unpackedUint64_codec);
+            break;
+          }
+          case 754:
+          case 752: {
+            unpackedSint32_.AddEntriesFrom(input, _repeated_unpackedSint32_codec);
+            break;
+          }
+          case 762:
+          case 760: {
+            unpackedSint64_.AddEntriesFrom(input, _repeated_unpackedSint64_codec);
+            break;
+          }
+          case 770:
+          case 773: {
+            unpackedFixed32_.AddEntriesFrom(input, _repeated_unpackedFixed32_codec);
+            break;
+          }
+          case 778:
+          case 777: {
+            unpackedFixed64_.AddEntriesFrom(input, _repeated_unpackedFixed64_codec);
+            break;
+          }
+          case 786:
+          case 789: {
+            unpackedSfixed32_.AddEntriesFrom(input, _repeated_unpackedSfixed32_codec);
+            break;
+          }
+          case 794:
+          case 793: {
+            unpackedSfixed64_.AddEntriesFrom(input, _repeated_unpackedSfixed64_codec);
+            break;
+          }
+          case 802:
+          case 805: {
+            unpackedFloat_.AddEntriesFrom(input, _repeated_unpackedFloat_codec);
+            break;
+          }
+          case 810:
+          case 809: {
+            unpackedDouble_.AddEntriesFrom(input, _repeated_unpackedDouble_codec);
+            break;
+          }
+          case 818:
+          case 816: {
+            unpackedBool_.AddEntriesFrom(input, _repeated_unpackedBool_codec);
+            break;
+          }
+          case 826:
+          case 824: {
+            unpackedEnum_.AddEntriesFrom(input, _repeated_unpackedEnum_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestRepeatedScalarDifferentTagSizes : pb::IMessage<TestRepeatedScalarDifferentTagSizes> {
+    private static readonly pb::MessageParser<TestRepeatedScalarDifferentTagSizes> _parser = new pb::MessageParser<TestRepeatedScalarDifferentTagSizes>(() => new TestRepeatedScalarDifferentTagSizes());
+    public static pb::MessageParser<TestRepeatedScalarDifferentTagSizes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[25]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestRepeatedScalarDifferentTagSizes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestRepeatedScalarDifferentTagSizes(TestRepeatedScalarDifferentTagSizes other) : this() {
+      repeatedFixed32_ = other.repeatedFixed32_.Clone();
+      repeatedInt32_ = other.repeatedInt32_.Clone();
+      repeatedFixed64_ = other.repeatedFixed64_.Clone();
+      repeatedInt64_ = other.repeatedInt64_.Clone();
+      repeatedFloat_ = other.repeatedFloat_.Clone();
+      repeatedUint64_ = other.repeatedUint64_.Clone();
+    }
+
+    public TestRepeatedScalarDifferentTagSizes Clone() {
+      return new TestRepeatedScalarDifferentTagSizes(this);
+    }
+
+    public const int RepeatedFixed32FieldNumber = 12;
+    private static readonly pb::FieldCodec<uint> _repeated_repeatedFixed32_codec
+        = pb::FieldCodec.ForFixed32(98);
+    private readonly pbc::RepeatedField<uint> repeatedFixed32_ = new pbc::RepeatedField<uint>();
+    public pbc::RepeatedField<uint> RepeatedFixed32 {
+      get { return repeatedFixed32_; }
+    }
+
+    public const int RepeatedInt32FieldNumber = 13;
+    private static readonly pb::FieldCodec<int> _repeated_repeatedInt32_codec
+        = pb::FieldCodec.ForInt32(106);
+    private readonly pbc::RepeatedField<int> repeatedInt32_ = new pbc::RepeatedField<int>();
+    public pbc::RepeatedField<int> RepeatedInt32 {
+      get { return repeatedInt32_; }
+    }
+
+    public const int RepeatedFixed64FieldNumber = 2046;
+    private static readonly pb::FieldCodec<ulong> _repeated_repeatedFixed64_codec
+        = pb::FieldCodec.ForFixed64(16370);
+    private readonly pbc::RepeatedField<ulong> repeatedFixed64_ = new pbc::RepeatedField<ulong>();
+    public pbc::RepeatedField<ulong> RepeatedFixed64 {
+      get { return repeatedFixed64_; }
+    }
+
+    public const int RepeatedInt64FieldNumber = 2047;
+    private static readonly pb::FieldCodec<long> _repeated_repeatedInt64_codec
+        = pb::FieldCodec.ForInt64(16378);
+    private readonly pbc::RepeatedField<long> repeatedInt64_ = new pbc::RepeatedField<long>();
+    public pbc::RepeatedField<long> RepeatedInt64 {
+      get { return repeatedInt64_; }
+    }
+
+    public const int RepeatedFloatFieldNumber = 262142;
+    private static readonly pb::FieldCodec<float> _repeated_repeatedFloat_codec
+        = pb::FieldCodec.ForFloat(2097138);
+    private readonly pbc::RepeatedField<float> repeatedFloat_ = new pbc::RepeatedField<float>();
+    public pbc::RepeatedField<float> RepeatedFloat {
+      get { return repeatedFloat_; }
+    }
+
+    public const int RepeatedUint64FieldNumber = 262143;
+    private static readonly pb::FieldCodec<ulong> _repeated_repeatedUint64_codec
+        = pb::FieldCodec.ForUInt64(2097146);
+    private readonly pbc::RepeatedField<ulong> repeatedUint64_ = new pbc::RepeatedField<ulong>();
+    public pbc::RepeatedField<ulong> RepeatedUint64 {
+      get { return repeatedUint64_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestRepeatedScalarDifferentTagSizes);
+    }
+
+    public bool Equals(TestRepeatedScalarDifferentTagSizes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!repeatedFixed32_.Equals(other.repeatedFixed32_)) return false;
+      if(!repeatedInt32_.Equals(other.repeatedInt32_)) return false;
+      if(!repeatedFixed64_.Equals(other.repeatedFixed64_)) return false;
+      if(!repeatedInt64_.Equals(other.repeatedInt64_)) return false;
+      if(!repeatedFloat_.Equals(other.repeatedFloat_)) return false;
+      if(!repeatedUint64_.Equals(other.repeatedUint64_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= repeatedFixed32_.GetHashCode();
+      hash ^= repeatedInt32_.GetHashCode();
+      hash ^= repeatedFixed64_.GetHashCode();
+      hash ^= repeatedInt64_.GetHashCode();
+      hash ^= repeatedFloat_.GetHashCode();
+      hash ^= repeatedUint64_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      repeatedFixed32_.WriteTo(output, _repeated_repeatedFixed32_codec);
+      repeatedInt32_.WriteTo(output, _repeated_repeatedInt32_codec);
+      repeatedFixed64_.WriteTo(output, _repeated_repeatedFixed64_codec);
+      repeatedInt64_.WriteTo(output, _repeated_repeatedInt64_codec);
+      repeatedFloat_.WriteTo(output, _repeated_repeatedFloat_codec);
+      repeatedUint64_.WriteTo(output, _repeated_repeatedUint64_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += repeatedFixed32_.CalculateSize(_repeated_repeatedFixed32_codec);
+      size += repeatedInt32_.CalculateSize(_repeated_repeatedInt32_codec);
+      size += repeatedFixed64_.CalculateSize(_repeated_repeatedFixed64_codec);
+      size += repeatedInt64_.CalculateSize(_repeated_repeatedInt64_codec);
+      size += repeatedFloat_.CalculateSize(_repeated_repeatedFloat_codec);
+      size += repeatedUint64_.CalculateSize(_repeated_repeatedUint64_codec);
+      return size;
+    }
+
+    public void MergeFrom(TestRepeatedScalarDifferentTagSizes other) {
+      if (other == null) {
+        return;
+      }
+      repeatedFixed32_.Add(other.repeatedFixed32_);
+      repeatedInt32_.Add(other.repeatedInt32_);
+      repeatedFixed64_.Add(other.repeatedFixed64_);
+      repeatedInt64_.Add(other.repeatedInt64_);
+      repeatedFloat_.Add(other.repeatedFloat_);
+      repeatedUint64_.Add(other.repeatedUint64_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 98:
+          case 101: {
+            repeatedFixed32_.AddEntriesFrom(input, _repeated_repeatedFixed32_codec);
+            break;
+          }
+          case 106:
+          case 104: {
+            repeatedInt32_.AddEntriesFrom(input, _repeated_repeatedInt32_codec);
+            break;
+          }
+          case 16370:
+          case 16369: {
+            repeatedFixed64_.AddEntriesFrom(input, _repeated_repeatedFixed64_codec);
+            break;
+          }
+          case 16378:
+          case 16376: {
+            repeatedInt64_.AddEntriesFrom(input, _repeated_repeatedInt64_codec);
+            break;
+          }
+          case 2097138:
+          case 2097141: {
+            repeatedFloat_.AddEntriesFrom(input, _repeated_repeatedFloat_codec);
+            break;
+          }
+          case 2097146:
+          case 2097144: {
+            repeatedUint64_.AddEntriesFrom(input, _repeated_repeatedUint64_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestCommentInjectionMessage : pb::IMessage<TestCommentInjectionMessage> {
+    private static readonly pb::MessageParser<TestCommentInjectionMessage> _parser = new pb::MessageParser<TestCommentInjectionMessage>(() => new TestCommentInjectionMessage());
+    public static pb::MessageParser<TestCommentInjectionMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[26]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestCommentInjectionMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestCommentInjectionMessage(TestCommentInjectionMessage other) : this() {
+      a_ = other.a_;
+    }
+
+    public TestCommentInjectionMessage Clone() {
+      return new TestCommentInjectionMessage(this);
+    }
+
+    public const int AFieldNumber = 1;
+    private string a_ = "";
+    public string A {
+      get { return a_; }
+      set {
+        a_ = pb::Preconditions.CheckNotNull(value, "value");
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestCommentInjectionMessage);
+    }
+
+    public bool Equals(TestCommentInjectionMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (A != other.A) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (A.Length != 0) hash ^= A.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (A.Length != 0) {
+        output.WriteRawTag(10);
+        output.WriteString(A);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (A.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(A);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestCommentInjectionMessage other) {
+      if (other == null) {
+        return;
+      }
+      if (other.A.Length != 0) {
+        A = other.A;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            A = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class FooRequest : pb::IMessage<FooRequest> {
+    private static readonly pb::MessageParser<FooRequest> _parser = new pb::MessageParser<FooRequest>(() => new FooRequest());
+    public static pb::MessageParser<FooRequest> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[27]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public FooRequest() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public FooRequest(FooRequest other) : this() {
+    }
+
+    public FooRequest Clone() {
+      return new FooRequest(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as FooRequest);
+    }
+
+    public bool Equals(FooRequest other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(FooRequest other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class FooResponse : pb::IMessage<FooResponse> {
+    private static readonly pb::MessageParser<FooResponse> _parser = new pb::MessageParser<FooResponse>(() => new FooResponse());
+    public static pb::MessageParser<FooResponse> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[28]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public FooResponse() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public FooResponse(FooResponse other) : this() {
+    }
+
+    public FooResponse Clone() {
+      return new FooResponse(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as FooResponse);
+    }
+
+    public bool Equals(FooResponse other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(FooResponse other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class FooClientMessage : pb::IMessage<FooClientMessage> {
+    private static readonly pb::MessageParser<FooClientMessage> _parser = new pb::MessageParser<FooClientMessage>(() => new FooClientMessage());
+    public static pb::MessageParser<FooClientMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[29]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public FooClientMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public FooClientMessage(FooClientMessage other) : this() {
+    }
+
+    public FooClientMessage Clone() {
+      return new FooClientMessage(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as FooClientMessage);
+    }
+
+    public bool Equals(FooClientMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(FooClientMessage other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class FooServerMessage : pb::IMessage<FooServerMessage> {
+    private static readonly pb::MessageParser<FooServerMessage> _parser = new pb::MessageParser<FooServerMessage>(() => new FooServerMessage());
+    public static pb::MessageParser<FooServerMessage> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[30]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public FooServerMessage() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public FooServerMessage(FooServerMessage other) : this() {
+    }
+
+    public FooServerMessage Clone() {
+      return new FooServerMessage(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as FooServerMessage);
+    }
+
+    public bool Equals(FooServerMessage other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(FooServerMessage other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class BarRequest : pb::IMessage<BarRequest> {
+    private static readonly pb::MessageParser<BarRequest> _parser = new pb::MessageParser<BarRequest>(() => new BarRequest());
+    public static pb::MessageParser<BarRequest> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[31]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public BarRequest() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public BarRequest(BarRequest other) : this() {
+    }
+
+    public BarRequest Clone() {
+      return new BarRequest(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as BarRequest);
+    }
+
+    public bool Equals(BarRequest other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(BarRequest other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class BarResponse : pb::IMessage<BarResponse> {
+    private static readonly pb::MessageParser<BarResponse> _parser = new pb::MessageParser<BarResponse>(() => new BarResponse());
+    public static pb::MessageParser<BarResponse> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestProto3.Descriptor.MessageTypes[32]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public BarResponse() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public BarResponse(BarResponse other) : this() {
+    }
+
+    public BarResponse Clone() {
+      return new BarResponse(this);
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as BarResponse);
+    }
+
+    public bool Equals(BarResponse other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      return size;
+    }
+
+    public void MergeFrom(BarResponse other) {
+      if (other == null) {
+        return;
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code

+ 2283 - 0
csharp/src/Google.Protobuf.Test/TestProtos/UnittestWellKnownTypes.cs

@@ -0,0 +1,2283 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/unittest_well_known_types.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Google.Protobuf.TestProtos {
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public static partial class UnittestWellKnownTypes {
+
+    #region Descriptor
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static UnittestWellKnownTypes() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "Ci9nb29nbGUvcHJvdG9idWYvdW5pdHRlc3Rfd2VsbF9rbm93bl90eXBlcy5w", 
+            "cm90bxIRcHJvdG9idWZfdW5pdHRlc3QaGWdvb2dsZS9wcm90b2J1Zi9hbnku", 
+            "cHJvdG8aGWdvb2dsZS9wcm90b2J1Zi9hcGkucHJvdG8aHmdvb2dsZS9wcm90", 
+            "b2J1Zi9kdXJhdGlvbi5wcm90bxobZ29vZ2xlL3Byb3RvYnVmL2VtcHR5LnBy", 
+            "b3RvGiBnb29nbGUvcHJvdG9idWYvZmllbGRfbWFzay5wcm90bxokZ29vZ2xl", 
+            "L3Byb3RvYnVmL3NvdXJjZV9jb250ZXh0LnByb3RvGhxnb29nbGUvcHJvdG9i", 
+            "dWYvc3RydWN0LnByb3RvGh9nb29nbGUvcHJvdG9idWYvdGltZXN0YW1wLnBy", 
+            "b3RvGhpnb29nbGUvcHJvdG9idWYvdHlwZS5wcm90bxoeZ29vZ2xlL3Byb3Rv", 
+            "YnVmL3dyYXBwZXJzLnByb3RvIpEHChJUZXN0V2VsbEtub3duVHlwZXMSJwoJ", 
+            "YW55X2ZpZWxkGAEgASgLMhQuZ29vZ2xlLnByb3RvYnVmLkFueRInCglhcGlf", 
+            "ZmllbGQYAiABKAsyFC5nb29nbGUucHJvdG9idWYuQXBpEjEKDmR1cmF0aW9u", 
+            "X2ZpZWxkGAMgASgLMhkuZ29vZ2xlLnByb3RvYnVmLkR1cmF0aW9uEisKC2Vt", 
+            "cHR5X2ZpZWxkGAQgASgLMhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5EjQKEGZp", 
+            "ZWxkX21hc2tfZmllbGQYBSABKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRN", 
+            "YXNrEjwKFHNvdXJjZV9jb250ZXh0X2ZpZWxkGAYgASgLMh4uZ29vZ2xlLnBy", 
+            "b3RvYnVmLlNvdXJjZUNvbnRleHQSLQoMc3RydWN0X2ZpZWxkGAcgASgLMhcu", 
+            "Z29vZ2xlLnByb3RvYnVmLlN0cnVjdBIzCg90aW1lc3RhbXBfZmllbGQYCCAB", 
+            "KAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEikKCnR5cGVfZmllbGQY", 
+            "CSABKAsyFS5nb29nbGUucHJvdG9idWYuVHlwZRIyCgxkb3VibGVfZmllbGQY", 
+            "CiABKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSMAoLZmxvYXRf", 
+            "ZmllbGQYCyABKAsyGy5nb29nbGUucHJvdG9idWYuRmxvYXRWYWx1ZRIwCgtp", 
+            "bnQ2NF9maWVsZBgMIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVl", 
+            "EjIKDHVpbnQ2NF9maWVsZBgNIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5VSW50", 
+            "NjRWYWx1ZRIwCgtpbnQzMl9maWVsZBgOIAEoCzIbLmdvb2dsZS5wcm90b2J1", 
+            "Zi5JbnQzMlZhbHVlEjIKDHVpbnQzMl9maWVsZBgPIAEoCzIcLmdvb2dsZS5w", 
+            "cm90b2J1Zi5VSW50MzJWYWx1ZRIuCgpib29sX2ZpZWxkGBAgASgLMhouZ29v", 
+            "Z2xlLnByb3RvYnVmLkJvb2xWYWx1ZRIyCgxzdHJpbmdfZmllbGQYESABKAsy", 
+            "HC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWUSMAoLYnl0ZXNfZmllbGQY", 
+            "EiABKAsyGy5nb29nbGUucHJvdG9idWYuQnl0ZXNWYWx1ZSKVBwoWUmVwZWF0", 
+            "ZWRXZWxsS25vd25UeXBlcxInCglhbnlfZmllbGQYASADKAsyFC5nb29nbGUu", 
+            "cHJvdG9idWYuQW55EicKCWFwaV9maWVsZBgCIAMoCzIULmdvb2dsZS5wcm90", 
+            "b2J1Zi5BcGkSMQoOZHVyYXRpb25fZmllbGQYAyADKAsyGS5nb29nbGUucHJv", 
+            "dG9idWYuRHVyYXRpb24SKwoLZW1wdHlfZmllbGQYBCADKAsyFi5nb29nbGUu", 
+            "cHJvdG9idWYuRW1wdHkSNAoQZmllbGRfbWFza19maWVsZBgFIAMoCzIaLmdv", 
+            "b2dsZS5wcm90b2J1Zi5GaWVsZE1hc2sSPAoUc291cmNlX2NvbnRleHRfZmll", 
+            "bGQYBiADKAsyHi5nb29nbGUucHJvdG9idWYuU291cmNlQ29udGV4dBItCgxz", 
+            "dHJ1Y3RfZmllbGQYByADKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0EjMK", 
+            "D3RpbWVzdGFtcF9maWVsZBgIIAMoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1l", 
+            "c3RhbXASKQoKdHlwZV9maWVsZBgJIAMoCzIVLmdvb2dsZS5wcm90b2J1Zi5U", 
+            "eXBlEjIKDGRvdWJsZV9maWVsZBgKIAMoCzIcLmdvb2dsZS5wcm90b2J1Zi5E", 
+            "b3VibGVWYWx1ZRIwCgtmbG9hdF9maWVsZBgLIAMoCzIbLmdvb2dsZS5wcm90", 
+            "b2J1Zi5GbG9hdFZhbHVlEjAKC2ludDY0X2ZpZWxkGAwgAygLMhsuZ29vZ2xl", 
+            "LnByb3RvYnVmLkludDY0VmFsdWUSMgoMdWludDY0X2ZpZWxkGA0gAygLMhwu", 
+            "Z29vZ2xlLnByb3RvYnVmLlVJbnQ2NFZhbHVlEjAKC2ludDMyX2ZpZWxkGA4g", 
+            "AygLMhsuZ29vZ2xlLnByb3RvYnVmLkludDMyVmFsdWUSMgoMdWludDMyX2Zp", 
+            "ZWxkGA8gAygLMhwuZ29vZ2xlLnByb3RvYnVmLlVJbnQzMlZhbHVlEi4KCmJv", 
+            "b2xfZmllbGQYECADKAsyGi5nb29nbGUucHJvdG9idWYuQm9vbFZhbHVlEjIK", 
+            "DHN0cmluZ19maWVsZBgRIAMoCzIcLmdvb2dsZS5wcm90b2J1Zi5TdHJpbmdW", 
+            "YWx1ZRIwCgtieXRlc19maWVsZBgSIAMoCzIbLmdvb2dsZS5wcm90b2J1Zi5C", 
+            "eXRlc1ZhbHVlIsUHChNPbmVvZldlbGxLbm93blR5cGVzEikKCWFueV9maWVs", 
+            "ZBgBIAEoCzIULmdvb2dsZS5wcm90b2J1Zi5BbnlIABIpCglhcGlfZmllbGQY", 
+            "AiABKAsyFC5nb29nbGUucHJvdG9idWYuQXBpSAASMwoOZHVyYXRpb25fZmll", 
+            "bGQYAyABKAsyGS5nb29nbGUucHJvdG9idWYuRHVyYXRpb25IABItCgtlbXB0", 
+            "eV9maWVsZBgEIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eUgAEjYKEGZp", 
+            "ZWxkX21hc2tfZmllbGQYBSABKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRN", 
+            "YXNrSAASPgoUc291cmNlX2NvbnRleHRfZmllbGQYBiABKAsyHi5nb29nbGUu", 
+            "cHJvdG9idWYuU291cmNlQ29udGV4dEgAEi8KDHN0cnVjdF9maWVsZBgHIAEo", 
+            "CzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RIABI1Cg90aW1lc3RhbXBfZmll", 
+            "bGQYCCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wSAASKwoKdHlw", 
+            "ZV9maWVsZBgJIAEoCzIVLmdvb2dsZS5wcm90b2J1Zi5UeXBlSAASNAoMZG91", 
+            "YmxlX2ZpZWxkGAogASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVl", 
+            "SAASMgoLZmxvYXRfZmllbGQYCyABKAsyGy5nb29nbGUucHJvdG9idWYuRmxv", 
+            "YXRWYWx1ZUgAEjIKC2ludDY0X2ZpZWxkGAwgASgLMhsuZ29vZ2xlLnByb3Rv", 
+            "YnVmLkludDY0VmFsdWVIABI0Cgx1aW50NjRfZmllbGQYDSABKAsyHC5nb29n", 
+            "bGUucHJvdG9idWYuVUludDY0VmFsdWVIABIyCgtpbnQzMl9maWVsZBgOIAEo", 
+            "CzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQzMlZhbHVlSAASNAoMdWludDMyX2Zp", 
+            "ZWxkGA8gASgLMhwuZ29vZ2xlLnByb3RvYnVmLlVJbnQzMlZhbHVlSAASMAoK", 
+            "Ym9vbF9maWVsZBgQIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5Cb29sVmFsdWVI", 
+            "ABI0CgxzdHJpbmdfZmllbGQYESABKAsyHC5nb29nbGUucHJvdG9idWYuU3Ry", 
+            "aW5nVmFsdWVIABIyCgtieXRlc19maWVsZBgSIAEoCzIbLmdvb2dsZS5wcm90", 
+            "b2J1Zi5CeXRlc1ZhbHVlSABCDQoLb25lb2ZfZmllbGQilhYKEU1hcFdlbGxL", 
+            "bm93blR5cGVzEkUKCWFueV9maWVsZBgBIAMoCzIyLnByb3RvYnVmX3VuaXR0", 
+            "ZXN0Lk1hcFdlbGxLbm93blR5cGVzLkFueUZpZWxkRW50cnkSRQoJYXBpX2Zp", 
+            "ZWxkGAIgAygLMjIucHJvdG9idWZfdW5pdHRlc3QuTWFwV2VsbEtub3duVHlw", 
+            "ZXMuQXBpRmllbGRFbnRyeRJPCg5kdXJhdGlvbl9maWVsZBgDIAMoCzI3LnBy", 
+            "b3RvYnVmX3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5cGVzLkR1cmF0aW9uRmll", 
+            "bGRFbnRyeRJJCgtlbXB0eV9maWVsZBgEIAMoCzI0LnByb3RvYnVmX3VuaXR0", 
+            "ZXN0Lk1hcFdlbGxLbm93blR5cGVzLkVtcHR5RmllbGRFbnRyeRJSChBmaWVs", 
+            "ZF9tYXNrX2ZpZWxkGAUgAygLMjgucHJvdG9idWZfdW5pdHRlc3QuTWFwV2Vs", 
+            "bEtub3duVHlwZXMuRmllbGRNYXNrRmllbGRFbnRyeRJaChRzb3VyY2VfY29u", 
+            "dGV4dF9maWVsZBgGIAMoCzI8LnByb3RvYnVmX3VuaXR0ZXN0Lk1hcFdlbGxL", 
+            "bm93blR5cGVzLlNvdXJjZUNvbnRleHRGaWVsZEVudHJ5EksKDHN0cnVjdF9m", 
+            "aWVsZBgHIAMoCzI1LnByb3RvYnVmX3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5", 
+            "cGVzLlN0cnVjdEZpZWxkRW50cnkSUQoPdGltZXN0YW1wX2ZpZWxkGAggAygL", 
+            "MjgucHJvdG9idWZfdW5pdHRlc3QuTWFwV2VsbEtub3duVHlwZXMuVGltZXN0", 
+            "YW1wRmllbGRFbnRyeRJHCgp0eXBlX2ZpZWxkGAkgAygLMjMucHJvdG9idWZf", 
+            "dW5pdHRlc3QuTWFwV2VsbEtub3duVHlwZXMuVHlwZUZpZWxkRW50cnkSSwoM", 
+            "ZG91YmxlX2ZpZWxkGAogAygLMjUucHJvdG9idWZfdW5pdHRlc3QuTWFwV2Vs", 
+            "bEtub3duVHlwZXMuRG91YmxlRmllbGRFbnRyeRJJCgtmbG9hdF9maWVsZBgL", 
+            "IAMoCzI0LnByb3RvYnVmX3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5cGVzLkZs", 
+            "b2F0RmllbGRFbnRyeRJJCgtpbnQ2NF9maWVsZBgMIAMoCzI0LnByb3RvYnVm", 
+            "X3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5cGVzLkludDY0RmllbGRFbnRyeRJL", 
+            "Cgx1aW50NjRfZmllbGQYDSADKAsyNS5wcm90b2J1Zl91bml0dGVzdC5NYXBX", 
+            "ZWxsS25vd25UeXBlcy5VaW50NjRGaWVsZEVudHJ5EkkKC2ludDMyX2ZpZWxk", 
+            "GA4gAygLMjQucHJvdG9idWZfdW5pdHRlc3QuTWFwV2VsbEtub3duVHlwZXMu", 
+            "SW50MzJGaWVsZEVudHJ5EksKDHVpbnQzMl9maWVsZBgPIAMoCzI1LnByb3Rv", 
+            "YnVmX3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5cGVzLlVpbnQzMkZpZWxkRW50", 
+            "cnkSRwoKYm9vbF9maWVsZBgQIAMoCzIzLnByb3RvYnVmX3VuaXR0ZXN0Lk1h", 
+            "cFdlbGxLbm93blR5cGVzLkJvb2xGaWVsZEVudHJ5EksKDHN0cmluZ19maWVs", 
+            "ZBgRIAMoCzI1LnByb3RvYnVmX3VuaXR0ZXN0Lk1hcFdlbGxLbm93blR5cGVz", 
+            "LlN0cmluZ0ZpZWxkRW50cnkSSQoLYnl0ZXNfZmllbGQYEiADKAsyNC5wcm90", 
+            "b2J1Zl91bml0dGVzdC5NYXBXZWxsS25vd25UeXBlcy5CeXRlc0ZpZWxkRW50", 
+            "cnkaRQoNQW55RmllbGRFbnRyeRILCgNrZXkYASABKAUSIwoFdmFsdWUYAiAB", 
+            "KAsyFC5nb29nbGUucHJvdG9idWYuQW55OgI4ARpFCg1BcGlGaWVsZEVudHJ5", 
+            "EgsKA2tleRgBIAEoBRIjCgV2YWx1ZRgCIAEoCzIULmdvb2dsZS5wcm90b2J1", 
+            "Zi5BcGk6AjgBGk8KEkR1cmF0aW9uRmllbGRFbnRyeRILCgNrZXkYASABKAUS", 
+            "KAoFdmFsdWUYAiABKAsyGS5nb29nbGUucHJvdG9idWYuRHVyYXRpb246AjgB", 
+            "GkkKD0VtcHR5RmllbGRFbnRyeRILCgNrZXkYASABKAUSJQoFdmFsdWUYAiAB", 
+            "KAsyFi5nb29nbGUucHJvdG9idWYuRW1wdHk6AjgBGlEKE0ZpZWxkTWFza0Zp", 
+            "ZWxkRW50cnkSCwoDa2V5GAEgASgFEikKBXZhbHVlGAIgASgLMhouZ29vZ2xl", 
+            "LnByb3RvYnVmLkZpZWxkTWFzazoCOAEaWQoXU291cmNlQ29udGV4dEZpZWxk", 
+            "RW50cnkSCwoDa2V5GAEgASgFEi0KBXZhbHVlGAIgASgLMh4uZ29vZ2xlLnBy", 
+            "b3RvYnVmLlNvdXJjZUNvbnRleHQ6AjgBGksKEFN0cnVjdEZpZWxkRW50cnkS", 
+            "CwoDa2V5GAEgASgFEiYKBXZhbHVlGAIgASgLMhcuZ29vZ2xlLnByb3RvYnVm", 
+            "LlN0cnVjdDoCOAEaUQoTVGltZXN0YW1wRmllbGRFbnRyeRILCgNrZXkYASAB", 
+            "KAUSKQoFdmFsdWUYAiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1w", 
+            "OgI4ARpHCg5UeXBlRmllbGRFbnRyeRILCgNrZXkYASABKAUSJAoFdmFsdWUY", 
+            "AiABKAsyFS5nb29nbGUucHJvdG9idWYuVHlwZToCOAEaUAoQRG91YmxlRmll", 
+            "bGRFbnRyeRILCgNrZXkYASABKAUSKwoFdmFsdWUYAiABKAsyHC5nb29nbGUu", 
+            "cHJvdG9idWYuRG91YmxlVmFsdWU6AjgBGk4KD0Zsb2F0RmllbGRFbnRyeRIL", 
+            "CgNrZXkYASABKAUSKgoFdmFsdWUYAiABKAsyGy5nb29nbGUucHJvdG9idWYu", 
+            "RmxvYXRWYWx1ZToCOAEaTgoPSW50NjRGaWVsZEVudHJ5EgsKA2tleRgBIAEo", 
+            "BRIqCgV2YWx1ZRgCIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVl", 
+            "OgI4ARpQChBVaW50NjRGaWVsZEVudHJ5EgsKA2tleRgBIAEoBRIrCgV2YWx1", 
+            "ZRgCIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5VSW50NjRWYWx1ZToCOAEaTgoP", 
+            "SW50MzJGaWVsZEVudHJ5EgsKA2tleRgBIAEoBRIqCgV2YWx1ZRgCIAEoCzIb", 
+            "Lmdvb2dsZS5wcm90b2J1Zi5JbnQzMlZhbHVlOgI4ARpQChBVaW50MzJGaWVs", 
+            "ZEVudHJ5EgsKA2tleRgBIAEoBRIrCgV2YWx1ZRgCIAEoCzIcLmdvb2dsZS5w", 
+            "cm90b2J1Zi5VSW50MzJWYWx1ZToCOAEaTAoOQm9vbEZpZWxkRW50cnkSCwoD", 
+            "a2V5GAEgASgFEikKBXZhbHVlGAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLkJv", 
+            "b2xWYWx1ZToCOAEaUAoQU3RyaW5nRmllbGRFbnRyeRILCgNrZXkYASABKAUS", 
+            "KwoFdmFsdWUYAiABKAsyHC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWU6", 
+            "AjgBGk4KD0J5dGVzRmllbGRFbnRyeRILCgNrZXkYASABKAUSKgoFdmFsdWUY", 
+            "AiABKAsyGy5nb29nbGUucHJvdG9idWYuQnl0ZXNWYWx1ZToCOAFCOQoYY29t", 
+            "Lmdvb2dsZS5wcm90b2J1Zi50ZXN0UAGqAhpHb29nbGUuUHJvdG9idWYuVGVz", 
+            "dFByb3Rvc2IGcHJvdG8z"));
+      descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
+          new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.Proto.Any.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.Api.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.Duration.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.Empty.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.FieldMask.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.SourceContext.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.Struct.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.Timestamp.Descriptor, global::Google.Protobuf.WellKnownTypes.Proto.Type.Descriptor, global::Google.Protobuf.WellKnownTypes.Wrappers.Descriptor, },
+          new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.TestWellKnownTypes), new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.RepeatedWellKnownTypes), new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, null, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.OneofWellKnownTypes), new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, new[]{ "OneofField" }, null, null),
+            new pbr::GeneratedCodeInfo(typeof(global::Google.Protobuf.TestProtos.MapWellKnownTypes), new[]{ "AnyField", "ApiField", "DurationField", "EmptyField", "FieldMaskField", "SourceContextField", "StructField", "TimestampField", "TypeField", "DoubleField", "FloatField", "Int64Field", "Uint64Field", "Int32Field", "Uint32Field", "BoolField", "StringField", "BytesField" }, null, null, new pbr::GeneratedCodeInfo[] { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, })
+          }));
+    }
+    #endregion
+
+  }
+  #region Messages
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class TestWellKnownTypes : pb::IMessage<TestWellKnownTypes> {
+    private static readonly pb::MessageParser<TestWellKnownTypes> _parser = new pb::MessageParser<TestWellKnownTypes>(() => new TestWellKnownTypes());
+    public static pb::MessageParser<TestWellKnownTypes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypes.Descriptor.MessageTypes[0]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public TestWellKnownTypes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public TestWellKnownTypes(TestWellKnownTypes other) : this() {
+      AnyField = other.anyField_ != null ? other.AnyField.Clone() : null;
+      ApiField = other.apiField_ != null ? other.ApiField.Clone() : null;
+      DurationField = other.durationField_ != null ? other.DurationField.Clone() : null;
+      EmptyField = other.emptyField_ != null ? other.EmptyField.Clone() : null;
+      FieldMaskField = other.fieldMaskField_ != null ? other.FieldMaskField.Clone() : null;
+      SourceContextField = other.sourceContextField_ != null ? other.SourceContextField.Clone() : null;
+      StructField = other.structField_ != null ? other.StructField.Clone() : null;
+      TimestampField = other.timestampField_ != null ? other.TimestampField.Clone() : null;
+      TypeField = other.typeField_ != null ? other.TypeField.Clone() : null;
+      DoubleField = other.DoubleField;
+      FloatField = other.FloatField;
+      Int64Field = other.Int64Field;
+      Uint64Field = other.Uint64Field;
+      Int32Field = other.Int32Field;
+      Uint32Field = other.Uint32Field;
+      BoolField = other.BoolField;
+      StringField = other.StringField;
+      BytesField = other.BytesField;
+    }
+
+    public TestWellKnownTypes Clone() {
+      return new TestWellKnownTypes(this);
+    }
+
+    public const int AnyFieldFieldNumber = 1;
+    private global::Google.Protobuf.WellKnownTypes.Any anyField_;
+    public global::Google.Protobuf.WellKnownTypes.Any AnyField {
+      get { return anyField_; }
+      set {
+        anyField_ = value;
+      }
+    }
+
+    public const int ApiFieldFieldNumber = 2;
+    private global::Google.Protobuf.WellKnownTypes.Api apiField_;
+    public global::Google.Protobuf.WellKnownTypes.Api ApiField {
+      get { return apiField_; }
+      set {
+        apiField_ = value;
+      }
+    }
+
+    public const int DurationFieldFieldNumber = 3;
+    private global::Google.Protobuf.WellKnownTypes.Duration durationField_;
+    public global::Google.Protobuf.WellKnownTypes.Duration DurationField {
+      get { return durationField_; }
+      set {
+        durationField_ = value;
+      }
+    }
+
+    public const int EmptyFieldFieldNumber = 4;
+    private global::Google.Protobuf.WellKnownTypes.Empty emptyField_;
+    public global::Google.Protobuf.WellKnownTypes.Empty EmptyField {
+      get { return emptyField_; }
+      set {
+        emptyField_ = value;
+      }
+    }
+
+    public const int FieldMaskFieldFieldNumber = 5;
+    private global::Google.Protobuf.WellKnownTypes.FieldMask fieldMaskField_;
+    public global::Google.Protobuf.WellKnownTypes.FieldMask FieldMaskField {
+      get { return fieldMaskField_; }
+      set {
+        fieldMaskField_ = value;
+      }
+    }
+
+    public const int SourceContextFieldFieldNumber = 6;
+    private global::Google.Protobuf.WellKnownTypes.SourceContext sourceContextField_;
+    public global::Google.Protobuf.WellKnownTypes.SourceContext SourceContextField {
+      get { return sourceContextField_; }
+      set {
+        sourceContextField_ = value;
+      }
+    }
+
+    public const int StructFieldFieldNumber = 7;
+    private global::Google.Protobuf.WellKnownTypes.Struct structField_;
+    public global::Google.Protobuf.WellKnownTypes.Struct StructField {
+      get { return structField_; }
+      set {
+        structField_ = value;
+      }
+    }
+
+    public const int TimestampFieldFieldNumber = 8;
+    private global::Google.Protobuf.WellKnownTypes.Timestamp timestampField_;
+    public global::Google.Protobuf.WellKnownTypes.Timestamp TimestampField {
+      get { return timestampField_; }
+      set {
+        timestampField_ = value;
+      }
+    }
+
+    public const int TypeFieldFieldNumber = 9;
+    private global::Google.Protobuf.WellKnownTypes.Type typeField_;
+    public global::Google.Protobuf.WellKnownTypes.Type TypeField {
+      get { return typeField_; }
+      set {
+        typeField_ = value;
+      }
+    }
+
+    public const int DoubleFieldFieldNumber = 10;
+    private static readonly pb::FieldCodec<double?> _single_doubleField_codec = pb::FieldCodec.ForStructWrapper<double>(82);
+    private double? doubleField_;
+    public double? DoubleField {
+      get { return doubleField_; }
+      set {
+        doubleField_ = value;
+      }
+    }
+
+    public const int FloatFieldFieldNumber = 11;
+    private static readonly pb::FieldCodec<float?> _single_floatField_codec = pb::FieldCodec.ForStructWrapper<float>(90);
+    private float? floatField_;
+    public float? FloatField {
+      get { return floatField_; }
+      set {
+        floatField_ = value;
+      }
+    }
+
+    public const int Int64FieldFieldNumber = 12;
+    private static readonly pb::FieldCodec<long?> _single_int64Field_codec = pb::FieldCodec.ForStructWrapper<long>(98);
+    private long? int64Field_;
+    public long? Int64Field {
+      get { return int64Field_; }
+      set {
+        int64Field_ = value;
+      }
+    }
+
+    public const int Uint64FieldFieldNumber = 13;
+    private static readonly pb::FieldCodec<ulong?> _single_uint64Field_codec = pb::FieldCodec.ForStructWrapper<ulong>(106);
+    private ulong? uint64Field_;
+    public ulong? Uint64Field {
+      get { return uint64Field_; }
+      set {
+        uint64Field_ = value;
+      }
+    }
+
+    public const int Int32FieldFieldNumber = 14;
+    private static readonly pb::FieldCodec<int?> _single_int32Field_codec = pb::FieldCodec.ForStructWrapper<int>(114);
+    private int? int32Field_;
+    public int? Int32Field {
+      get { return int32Field_; }
+      set {
+        int32Field_ = value;
+      }
+    }
+
+    public const int Uint32FieldFieldNumber = 15;
+    private static readonly pb::FieldCodec<uint?> _single_uint32Field_codec = pb::FieldCodec.ForStructWrapper<uint>(122);
+    private uint? uint32Field_;
+    public uint? Uint32Field {
+      get { return uint32Field_; }
+      set {
+        uint32Field_ = value;
+      }
+    }
+
+    public const int BoolFieldFieldNumber = 16;
+    private static readonly pb::FieldCodec<bool?> _single_boolField_codec = pb::FieldCodec.ForStructWrapper<bool>(130);
+    private bool? boolField_;
+    public bool? BoolField {
+      get { return boolField_; }
+      set {
+        boolField_ = value;
+      }
+    }
+
+    public const int StringFieldFieldNumber = 17;
+    private static readonly pb::FieldCodec<string> _single_stringField_codec = pb::FieldCodec.ForClassWrapper<string>(138);
+    private string stringField_;
+    public string StringField {
+      get { return stringField_; }
+      set {
+        stringField_ = value;
+      }
+    }
+
+    public const int BytesFieldFieldNumber = 18;
+    private static readonly pb::FieldCodec<pb::ByteString> _single_bytesField_codec = pb::FieldCodec.ForClassWrapper<pb::ByteString>(146);
+    private pb::ByteString bytesField_;
+    public pb::ByteString BytesField {
+      get { return bytesField_; }
+      set {
+        bytesField_ = value;
+      }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as TestWellKnownTypes);
+    }
+
+    public bool Equals(TestWellKnownTypes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(AnyField, other.AnyField)) return false;
+      if (!object.Equals(ApiField, other.ApiField)) return false;
+      if (!object.Equals(DurationField, other.DurationField)) return false;
+      if (!object.Equals(EmptyField, other.EmptyField)) return false;
+      if (!object.Equals(FieldMaskField, other.FieldMaskField)) return false;
+      if (!object.Equals(SourceContextField, other.SourceContextField)) return false;
+      if (!object.Equals(StructField, other.StructField)) return false;
+      if (!object.Equals(TimestampField, other.TimestampField)) return false;
+      if (!object.Equals(TypeField, other.TypeField)) return false;
+      if (DoubleField != other.DoubleField) return false;
+      if (FloatField != other.FloatField) return false;
+      if (Int64Field != other.Int64Field) return false;
+      if (Uint64Field != other.Uint64Field) return false;
+      if (Int32Field != other.Int32Field) return false;
+      if (Uint32Field != other.Uint32Field) return false;
+      if (BoolField != other.BoolField) return false;
+      if (StringField != other.StringField) return false;
+      if (BytesField != other.BytesField) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (anyField_ != null) hash ^= AnyField.GetHashCode();
+      if (apiField_ != null) hash ^= ApiField.GetHashCode();
+      if (durationField_ != null) hash ^= DurationField.GetHashCode();
+      if (emptyField_ != null) hash ^= EmptyField.GetHashCode();
+      if (fieldMaskField_ != null) hash ^= FieldMaskField.GetHashCode();
+      if (sourceContextField_ != null) hash ^= SourceContextField.GetHashCode();
+      if (structField_ != null) hash ^= StructField.GetHashCode();
+      if (timestampField_ != null) hash ^= TimestampField.GetHashCode();
+      if (typeField_ != null) hash ^= TypeField.GetHashCode();
+      if (doubleField_ != null) hash ^= DoubleField.GetHashCode();
+      if (floatField_ != null) hash ^= FloatField.GetHashCode();
+      if (int64Field_ != null) hash ^= Int64Field.GetHashCode();
+      if (uint64Field_ != null) hash ^= Uint64Field.GetHashCode();
+      if (int32Field_ != null) hash ^= Int32Field.GetHashCode();
+      if (uint32Field_ != null) hash ^= Uint32Field.GetHashCode();
+      if (boolField_ != null) hash ^= BoolField.GetHashCode();
+      if (stringField_ != null) hash ^= StringField.GetHashCode();
+      if (bytesField_ != null) hash ^= BytesField.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (anyField_ != null) {
+        output.WriteRawTag(10);
+        output.WriteMessage(AnyField);
+      }
+      if (apiField_ != null) {
+        output.WriteRawTag(18);
+        output.WriteMessage(ApiField);
+      }
+      if (durationField_ != null) {
+        output.WriteRawTag(26);
+        output.WriteMessage(DurationField);
+      }
+      if (emptyField_ != null) {
+        output.WriteRawTag(34);
+        output.WriteMessage(EmptyField);
+      }
+      if (fieldMaskField_ != null) {
+        output.WriteRawTag(42);
+        output.WriteMessage(FieldMaskField);
+      }
+      if (sourceContextField_ != null) {
+        output.WriteRawTag(50);
+        output.WriteMessage(SourceContextField);
+      }
+      if (structField_ != null) {
+        output.WriteRawTag(58);
+        output.WriteMessage(StructField);
+      }
+      if (timestampField_ != null) {
+        output.WriteRawTag(66);
+        output.WriteMessage(TimestampField);
+      }
+      if (typeField_ != null) {
+        output.WriteRawTag(74);
+        output.WriteMessage(TypeField);
+      }
+      if (doubleField_ != null) {
+        _single_doubleField_codec.WriteTagAndValue(output, DoubleField);
+      }
+      if (floatField_ != null) {
+        _single_floatField_codec.WriteTagAndValue(output, FloatField);
+      }
+      if (int64Field_ != null) {
+        _single_int64Field_codec.WriteTagAndValue(output, Int64Field);
+      }
+      if (uint64Field_ != null) {
+        _single_uint64Field_codec.WriteTagAndValue(output, Uint64Field);
+      }
+      if (int32Field_ != null) {
+        _single_int32Field_codec.WriteTagAndValue(output, Int32Field);
+      }
+      if (uint32Field_ != null) {
+        _single_uint32Field_codec.WriteTagAndValue(output, Uint32Field);
+      }
+      if (boolField_ != null) {
+        _single_boolField_codec.WriteTagAndValue(output, BoolField);
+      }
+      if (stringField_ != null) {
+        _single_stringField_codec.WriteTagAndValue(output, StringField);
+      }
+      if (bytesField_ != null) {
+        _single_bytesField_codec.WriteTagAndValue(output, BytesField);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (anyField_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(AnyField);
+      }
+      if (apiField_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ApiField);
+      }
+      if (durationField_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(DurationField);
+      }
+      if (emptyField_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(EmptyField);
+      }
+      if (fieldMaskField_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(FieldMaskField);
+      }
+      if (sourceContextField_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceContextField);
+      }
+      if (structField_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(StructField);
+      }
+      if (timestampField_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(TimestampField);
+      }
+      if (typeField_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(TypeField);
+      }
+      if (doubleField_ != null) {
+        size += _single_doubleField_codec.CalculateSizeWithTag(DoubleField);
+      }
+      if (floatField_ != null) {
+        size += _single_floatField_codec.CalculateSizeWithTag(FloatField);
+      }
+      if (int64Field_ != null) {
+        size += _single_int64Field_codec.CalculateSizeWithTag(Int64Field);
+      }
+      if (uint64Field_ != null) {
+        size += _single_uint64Field_codec.CalculateSizeWithTag(Uint64Field);
+      }
+      if (int32Field_ != null) {
+        size += _single_int32Field_codec.CalculateSizeWithTag(Int32Field);
+      }
+      if (uint32Field_ != null) {
+        size += _single_uint32Field_codec.CalculateSizeWithTag(Uint32Field);
+      }
+      if (boolField_ != null) {
+        size += _single_boolField_codec.CalculateSizeWithTag(BoolField);
+      }
+      if (stringField_ != null) {
+        size += _single_stringField_codec.CalculateSizeWithTag(StringField);
+      }
+      if (bytesField_ != null) {
+        size += _single_bytesField_codec.CalculateSizeWithTag(BytesField);
+      }
+      return size;
+    }
+
+    public void MergeFrom(TestWellKnownTypes other) {
+      if (other == null) {
+        return;
+      }
+      if (other.anyField_ != null) {
+        if (anyField_ == null) {
+          anyField_ = new global::Google.Protobuf.WellKnownTypes.Any();
+        }
+        AnyField.MergeFrom(other.AnyField);
+      }
+      if (other.apiField_ != null) {
+        if (apiField_ == null) {
+          apiField_ = new global::Google.Protobuf.WellKnownTypes.Api();
+        }
+        ApiField.MergeFrom(other.ApiField);
+      }
+      if (other.durationField_ != null) {
+        if (durationField_ == null) {
+          durationField_ = new global::Google.Protobuf.WellKnownTypes.Duration();
+        }
+        DurationField.MergeFrom(other.DurationField);
+      }
+      if (other.emptyField_ != null) {
+        if (emptyField_ == null) {
+          emptyField_ = new global::Google.Protobuf.WellKnownTypes.Empty();
+        }
+        EmptyField.MergeFrom(other.EmptyField);
+      }
+      if (other.fieldMaskField_ != null) {
+        if (fieldMaskField_ == null) {
+          fieldMaskField_ = new global::Google.Protobuf.WellKnownTypes.FieldMask();
+        }
+        FieldMaskField.MergeFrom(other.FieldMaskField);
+      }
+      if (other.sourceContextField_ != null) {
+        if (sourceContextField_ == null) {
+          sourceContextField_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+        }
+        SourceContextField.MergeFrom(other.SourceContextField);
+      }
+      if (other.structField_ != null) {
+        if (structField_ == null) {
+          structField_ = new global::Google.Protobuf.WellKnownTypes.Struct();
+        }
+        StructField.MergeFrom(other.StructField);
+      }
+      if (other.timestampField_ != null) {
+        if (timestampField_ == null) {
+          timestampField_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+        }
+        TimestampField.MergeFrom(other.TimestampField);
+      }
+      if (other.typeField_ != null) {
+        if (typeField_ == null) {
+          typeField_ = new global::Google.Protobuf.WellKnownTypes.Type();
+        }
+        TypeField.MergeFrom(other.TypeField);
+      }
+      if (other.doubleField_ != null) {
+        if (doubleField_ == null || other.DoubleField != 0D) {
+          DoubleField = other.DoubleField;
+        }
+      }
+      if (other.floatField_ != null) {
+        if (floatField_ == null || other.FloatField != 0F) {
+          FloatField = other.FloatField;
+        }
+      }
+      if (other.int64Field_ != null) {
+        if (int64Field_ == null || other.Int64Field != 0L) {
+          Int64Field = other.Int64Field;
+        }
+      }
+      if (other.uint64Field_ != null) {
+        if (uint64Field_ == null || other.Uint64Field != 0UL) {
+          Uint64Field = other.Uint64Field;
+        }
+      }
+      if (other.int32Field_ != null) {
+        if (int32Field_ == null || other.Int32Field != 0) {
+          Int32Field = other.Int32Field;
+        }
+      }
+      if (other.uint32Field_ != null) {
+        if (uint32Field_ == null || other.Uint32Field != 0) {
+          Uint32Field = other.Uint32Field;
+        }
+      }
+      if (other.boolField_ != null) {
+        if (boolField_ == null || other.BoolField != false) {
+          BoolField = other.BoolField;
+        }
+      }
+      if (other.stringField_ != null) {
+        if (stringField_ == null || other.StringField != "") {
+          StringField = other.StringField;
+        }
+      }
+      if (other.bytesField_ != null) {
+        if (bytesField_ == null || other.BytesField != pb::ByteString.Empty) {
+          BytesField = other.BytesField;
+        }
+      }
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            if (anyField_ == null) {
+              anyField_ = new global::Google.Protobuf.WellKnownTypes.Any();
+            }
+            input.ReadMessage(anyField_);
+            break;
+          }
+          case 18: {
+            if (apiField_ == null) {
+              apiField_ = new global::Google.Protobuf.WellKnownTypes.Api();
+            }
+            input.ReadMessage(apiField_);
+            break;
+          }
+          case 26: {
+            if (durationField_ == null) {
+              durationField_ = new global::Google.Protobuf.WellKnownTypes.Duration();
+            }
+            input.ReadMessage(durationField_);
+            break;
+          }
+          case 34: {
+            if (emptyField_ == null) {
+              emptyField_ = new global::Google.Protobuf.WellKnownTypes.Empty();
+            }
+            input.ReadMessage(emptyField_);
+            break;
+          }
+          case 42: {
+            if (fieldMaskField_ == null) {
+              fieldMaskField_ = new global::Google.Protobuf.WellKnownTypes.FieldMask();
+            }
+            input.ReadMessage(fieldMaskField_);
+            break;
+          }
+          case 50: {
+            if (sourceContextField_ == null) {
+              sourceContextField_ = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+            }
+            input.ReadMessage(sourceContextField_);
+            break;
+          }
+          case 58: {
+            if (structField_ == null) {
+              structField_ = new global::Google.Protobuf.WellKnownTypes.Struct();
+            }
+            input.ReadMessage(structField_);
+            break;
+          }
+          case 66: {
+            if (timestampField_ == null) {
+              timestampField_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+            }
+            input.ReadMessage(timestampField_);
+            break;
+          }
+          case 74: {
+            if (typeField_ == null) {
+              typeField_ = new global::Google.Protobuf.WellKnownTypes.Type();
+            }
+            input.ReadMessage(typeField_);
+            break;
+          }
+          case 82: {
+            double? value = _single_doubleField_codec.Read(input);
+            if (doubleField_ == null || value != 0D) {
+              DoubleField = value;
+            }
+            break;
+          }
+          case 90: {
+            float? value = _single_floatField_codec.Read(input);
+            if (floatField_ == null || value != 0F) {
+              FloatField = value;
+            }
+            break;
+          }
+          case 98: {
+            long? value = _single_int64Field_codec.Read(input);
+            if (int64Field_ == null || value != 0L) {
+              Int64Field = value;
+            }
+            break;
+          }
+          case 106: {
+            ulong? value = _single_uint64Field_codec.Read(input);
+            if (uint64Field_ == null || value != 0UL) {
+              Uint64Field = value;
+            }
+            break;
+          }
+          case 114: {
+            int? value = _single_int32Field_codec.Read(input);
+            if (int32Field_ == null || value != 0) {
+              Int32Field = value;
+            }
+            break;
+          }
+          case 122: {
+            uint? value = _single_uint32Field_codec.Read(input);
+            if (uint32Field_ == null || value != 0) {
+              Uint32Field = value;
+            }
+            break;
+          }
+          case 130: {
+            bool? value = _single_boolField_codec.Read(input);
+            if (boolField_ == null || value != false) {
+              BoolField = value;
+            }
+            break;
+          }
+          case 138: {
+            string value = _single_stringField_codec.Read(input);
+            if (stringField_ == null || value != "") {
+              StringField = value;
+            }
+            break;
+          }
+          case 146: {
+            pb::ByteString value = _single_bytesField_codec.Read(input);
+            if (bytesField_ == null || value != pb::ByteString.Empty) {
+              BytesField = value;
+            }
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class RepeatedWellKnownTypes : pb::IMessage<RepeatedWellKnownTypes> {
+    private static readonly pb::MessageParser<RepeatedWellKnownTypes> _parser = new pb::MessageParser<RepeatedWellKnownTypes>(() => new RepeatedWellKnownTypes());
+    public static pb::MessageParser<RepeatedWellKnownTypes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypes.Descriptor.MessageTypes[1]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public RepeatedWellKnownTypes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public RepeatedWellKnownTypes(RepeatedWellKnownTypes other) : this() {
+      anyField_ = other.anyField_.Clone();
+      apiField_ = other.apiField_.Clone();
+      durationField_ = other.durationField_.Clone();
+      emptyField_ = other.emptyField_.Clone();
+      fieldMaskField_ = other.fieldMaskField_.Clone();
+      sourceContextField_ = other.sourceContextField_.Clone();
+      structField_ = other.structField_.Clone();
+      timestampField_ = other.timestampField_.Clone();
+      typeField_ = other.typeField_.Clone();
+      doubleField_ = other.doubleField_.Clone();
+      floatField_ = other.floatField_.Clone();
+      int64Field_ = other.int64Field_.Clone();
+      uint64Field_ = other.uint64Field_.Clone();
+      int32Field_ = other.int32Field_.Clone();
+      uint32Field_ = other.uint32Field_.Clone();
+      boolField_ = other.boolField_.Clone();
+      stringField_ = other.stringField_.Clone();
+      bytesField_ = other.bytesField_.Clone();
+    }
+
+    public RepeatedWellKnownTypes Clone() {
+      return new RepeatedWellKnownTypes(this);
+    }
+
+    public const int AnyFieldFieldNumber = 1;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Any> _repeated_anyField_codec
+        = pb::FieldCodec.ForMessage(10, global::Google.Protobuf.WellKnownTypes.Any.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Any> anyField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Any>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Any> AnyField {
+      get { return anyField_; }
+    }
+
+    public const int ApiFieldFieldNumber = 2;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Api> _repeated_apiField_codec
+        = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Api.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Api> apiField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Api>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Api> ApiField {
+      get { return apiField_; }
+    }
+
+    public const int DurationFieldFieldNumber = 3;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Duration> _repeated_durationField_codec
+        = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.WellKnownTypes.Duration.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Duration> durationField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Duration>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Duration> DurationField {
+      get { return durationField_; }
+    }
+
+    public const int EmptyFieldFieldNumber = 4;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Empty> _repeated_emptyField_codec
+        = pb::FieldCodec.ForMessage(34, global::Google.Protobuf.WellKnownTypes.Empty.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Empty> emptyField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Empty>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Empty> EmptyField {
+      get { return emptyField_; }
+    }
+
+    public const int FieldMaskFieldFieldNumber = 5;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.FieldMask> _repeated_fieldMaskField_codec
+        = pb::FieldCodec.ForMessage(42, global::Google.Protobuf.WellKnownTypes.FieldMask.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.FieldMask> fieldMaskField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.FieldMask>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.FieldMask> FieldMaskField {
+      get { return fieldMaskField_; }
+    }
+
+    public const int SourceContextFieldFieldNumber = 6;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.SourceContext> _repeated_sourceContextField_codec
+        = pb::FieldCodec.ForMessage(50, global::Google.Protobuf.WellKnownTypes.SourceContext.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.SourceContext> sourceContextField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.SourceContext>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.SourceContext> SourceContextField {
+      get { return sourceContextField_; }
+    }
+
+    public const int StructFieldFieldNumber = 7;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Struct> _repeated_structField_codec
+        = pb::FieldCodec.ForMessage(58, global::Google.Protobuf.WellKnownTypes.Struct.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Struct> structField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Struct>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Struct> StructField {
+      get { return structField_; }
+    }
+
+    public const int TimestampFieldFieldNumber = 8;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Timestamp> _repeated_timestampField_codec
+        = pb::FieldCodec.ForMessage(66, global::Google.Protobuf.WellKnownTypes.Timestamp.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Timestamp> timestampField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Timestamp>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Timestamp> TimestampField {
+      get { return timestampField_; }
+    }
+
+    public const int TypeFieldFieldNumber = 9;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.WellKnownTypes.Type> _repeated_typeField_codec
+        = pb::FieldCodec.ForMessage(74, global::Google.Protobuf.WellKnownTypes.Type.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Type> typeField_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Type>();
+    public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Type> TypeField {
+      get { return typeField_; }
+    }
+
+    public const int DoubleFieldFieldNumber = 10;
+    private static readonly pb::FieldCodec<double?> _repeated_doubleField_codec
+        = pb::FieldCodec.ForStructWrapper<double>(82);
+    private readonly pbc::RepeatedField<double?> doubleField_ = new pbc::RepeatedField<double?>();
+    public pbc::RepeatedField<double?> DoubleField {
+      get { return doubleField_; }
+    }
+
+    public const int FloatFieldFieldNumber = 11;
+    private static readonly pb::FieldCodec<float?> _repeated_floatField_codec
+        = pb::FieldCodec.ForStructWrapper<float>(90);
+    private readonly pbc::RepeatedField<float?> floatField_ = new pbc::RepeatedField<float?>();
+    public pbc::RepeatedField<float?> FloatField {
+      get { return floatField_; }
+    }
+
+    public const int Int64FieldFieldNumber = 12;
+    private static readonly pb::FieldCodec<long?> _repeated_int64Field_codec
+        = pb::FieldCodec.ForStructWrapper<long>(98);
+    private readonly pbc::RepeatedField<long?> int64Field_ = new pbc::RepeatedField<long?>();
+    public pbc::RepeatedField<long?> Int64Field {
+      get { return int64Field_; }
+    }
+
+    public const int Uint64FieldFieldNumber = 13;
+    private static readonly pb::FieldCodec<ulong?> _repeated_uint64Field_codec
+        = pb::FieldCodec.ForStructWrapper<ulong>(106);
+    private readonly pbc::RepeatedField<ulong?> uint64Field_ = new pbc::RepeatedField<ulong?>();
+    public pbc::RepeatedField<ulong?> Uint64Field {
+      get { return uint64Field_; }
+    }
+
+    public const int Int32FieldFieldNumber = 14;
+    private static readonly pb::FieldCodec<int?> _repeated_int32Field_codec
+        = pb::FieldCodec.ForStructWrapper<int>(114);
+    private readonly pbc::RepeatedField<int?> int32Field_ = new pbc::RepeatedField<int?>();
+    public pbc::RepeatedField<int?> Int32Field {
+      get { return int32Field_; }
+    }
+
+    public const int Uint32FieldFieldNumber = 15;
+    private static readonly pb::FieldCodec<uint?> _repeated_uint32Field_codec
+        = pb::FieldCodec.ForStructWrapper<uint>(122);
+    private readonly pbc::RepeatedField<uint?> uint32Field_ = new pbc::RepeatedField<uint?>();
+    public pbc::RepeatedField<uint?> Uint32Field {
+      get { return uint32Field_; }
+    }
+
+    public const int BoolFieldFieldNumber = 16;
+    private static readonly pb::FieldCodec<bool?> _repeated_boolField_codec
+        = pb::FieldCodec.ForStructWrapper<bool>(130);
+    private readonly pbc::RepeatedField<bool?> boolField_ = new pbc::RepeatedField<bool?>();
+    public pbc::RepeatedField<bool?> BoolField {
+      get { return boolField_; }
+    }
+
+    public const int StringFieldFieldNumber = 17;
+    private static readonly pb::FieldCodec<string> _repeated_stringField_codec
+        = pb::FieldCodec.ForClassWrapper<string>(138);
+    private readonly pbc::RepeatedField<string> stringField_ = new pbc::RepeatedField<string>();
+    public pbc::RepeatedField<string> StringField {
+      get { return stringField_; }
+    }
+
+    public const int BytesFieldFieldNumber = 18;
+    private static readonly pb::FieldCodec<pb::ByteString> _repeated_bytesField_codec
+        = pb::FieldCodec.ForClassWrapper<pb::ByteString>(146);
+    private readonly pbc::RepeatedField<pb::ByteString> bytesField_ = new pbc::RepeatedField<pb::ByteString>();
+    public pbc::RepeatedField<pb::ByteString> BytesField {
+      get { return bytesField_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as RepeatedWellKnownTypes);
+    }
+
+    public bool Equals(RepeatedWellKnownTypes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!anyField_.Equals(other.anyField_)) return false;
+      if(!apiField_.Equals(other.apiField_)) return false;
+      if(!durationField_.Equals(other.durationField_)) return false;
+      if(!emptyField_.Equals(other.emptyField_)) return false;
+      if(!fieldMaskField_.Equals(other.fieldMaskField_)) return false;
+      if(!sourceContextField_.Equals(other.sourceContextField_)) return false;
+      if(!structField_.Equals(other.structField_)) return false;
+      if(!timestampField_.Equals(other.timestampField_)) return false;
+      if(!typeField_.Equals(other.typeField_)) return false;
+      if(!doubleField_.Equals(other.doubleField_)) return false;
+      if(!floatField_.Equals(other.floatField_)) return false;
+      if(!int64Field_.Equals(other.int64Field_)) return false;
+      if(!uint64Field_.Equals(other.uint64Field_)) return false;
+      if(!int32Field_.Equals(other.int32Field_)) return false;
+      if(!uint32Field_.Equals(other.uint32Field_)) return false;
+      if(!boolField_.Equals(other.boolField_)) return false;
+      if(!stringField_.Equals(other.stringField_)) return false;
+      if(!bytesField_.Equals(other.bytesField_)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= anyField_.GetHashCode();
+      hash ^= apiField_.GetHashCode();
+      hash ^= durationField_.GetHashCode();
+      hash ^= emptyField_.GetHashCode();
+      hash ^= fieldMaskField_.GetHashCode();
+      hash ^= sourceContextField_.GetHashCode();
+      hash ^= structField_.GetHashCode();
+      hash ^= timestampField_.GetHashCode();
+      hash ^= typeField_.GetHashCode();
+      hash ^= doubleField_.GetHashCode();
+      hash ^= floatField_.GetHashCode();
+      hash ^= int64Field_.GetHashCode();
+      hash ^= uint64Field_.GetHashCode();
+      hash ^= int32Field_.GetHashCode();
+      hash ^= uint32Field_.GetHashCode();
+      hash ^= boolField_.GetHashCode();
+      hash ^= stringField_.GetHashCode();
+      hash ^= bytesField_.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      anyField_.WriteTo(output, _repeated_anyField_codec);
+      apiField_.WriteTo(output, _repeated_apiField_codec);
+      durationField_.WriteTo(output, _repeated_durationField_codec);
+      emptyField_.WriteTo(output, _repeated_emptyField_codec);
+      fieldMaskField_.WriteTo(output, _repeated_fieldMaskField_codec);
+      sourceContextField_.WriteTo(output, _repeated_sourceContextField_codec);
+      structField_.WriteTo(output, _repeated_structField_codec);
+      timestampField_.WriteTo(output, _repeated_timestampField_codec);
+      typeField_.WriteTo(output, _repeated_typeField_codec);
+      doubleField_.WriteTo(output, _repeated_doubleField_codec);
+      floatField_.WriteTo(output, _repeated_floatField_codec);
+      int64Field_.WriteTo(output, _repeated_int64Field_codec);
+      uint64Field_.WriteTo(output, _repeated_uint64Field_codec);
+      int32Field_.WriteTo(output, _repeated_int32Field_codec);
+      uint32Field_.WriteTo(output, _repeated_uint32Field_codec);
+      boolField_.WriteTo(output, _repeated_boolField_codec);
+      stringField_.WriteTo(output, _repeated_stringField_codec);
+      bytesField_.WriteTo(output, _repeated_bytesField_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += anyField_.CalculateSize(_repeated_anyField_codec);
+      size += apiField_.CalculateSize(_repeated_apiField_codec);
+      size += durationField_.CalculateSize(_repeated_durationField_codec);
+      size += emptyField_.CalculateSize(_repeated_emptyField_codec);
+      size += fieldMaskField_.CalculateSize(_repeated_fieldMaskField_codec);
+      size += sourceContextField_.CalculateSize(_repeated_sourceContextField_codec);
+      size += structField_.CalculateSize(_repeated_structField_codec);
+      size += timestampField_.CalculateSize(_repeated_timestampField_codec);
+      size += typeField_.CalculateSize(_repeated_typeField_codec);
+      size += doubleField_.CalculateSize(_repeated_doubleField_codec);
+      size += floatField_.CalculateSize(_repeated_floatField_codec);
+      size += int64Field_.CalculateSize(_repeated_int64Field_codec);
+      size += uint64Field_.CalculateSize(_repeated_uint64Field_codec);
+      size += int32Field_.CalculateSize(_repeated_int32Field_codec);
+      size += uint32Field_.CalculateSize(_repeated_uint32Field_codec);
+      size += boolField_.CalculateSize(_repeated_boolField_codec);
+      size += stringField_.CalculateSize(_repeated_stringField_codec);
+      size += bytesField_.CalculateSize(_repeated_bytesField_codec);
+      return size;
+    }
+
+    public void MergeFrom(RepeatedWellKnownTypes other) {
+      if (other == null) {
+        return;
+      }
+      anyField_.Add(other.anyField_);
+      apiField_.Add(other.apiField_);
+      durationField_.Add(other.durationField_);
+      emptyField_.Add(other.emptyField_);
+      fieldMaskField_.Add(other.fieldMaskField_);
+      sourceContextField_.Add(other.sourceContextField_);
+      structField_.Add(other.structField_);
+      timestampField_.Add(other.timestampField_);
+      typeField_.Add(other.typeField_);
+      doubleField_.Add(other.doubleField_);
+      floatField_.Add(other.floatField_);
+      int64Field_.Add(other.int64Field_);
+      uint64Field_.Add(other.uint64Field_);
+      int32Field_.Add(other.int32Field_);
+      uint32Field_.Add(other.uint32Field_);
+      boolField_.Add(other.boolField_);
+      stringField_.Add(other.stringField_);
+      bytesField_.Add(other.bytesField_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            anyField_.AddEntriesFrom(input, _repeated_anyField_codec);
+            break;
+          }
+          case 18: {
+            apiField_.AddEntriesFrom(input, _repeated_apiField_codec);
+            break;
+          }
+          case 26: {
+            durationField_.AddEntriesFrom(input, _repeated_durationField_codec);
+            break;
+          }
+          case 34: {
+            emptyField_.AddEntriesFrom(input, _repeated_emptyField_codec);
+            break;
+          }
+          case 42: {
+            fieldMaskField_.AddEntriesFrom(input, _repeated_fieldMaskField_codec);
+            break;
+          }
+          case 50: {
+            sourceContextField_.AddEntriesFrom(input, _repeated_sourceContextField_codec);
+            break;
+          }
+          case 58: {
+            structField_.AddEntriesFrom(input, _repeated_structField_codec);
+            break;
+          }
+          case 66: {
+            timestampField_.AddEntriesFrom(input, _repeated_timestampField_codec);
+            break;
+          }
+          case 74: {
+            typeField_.AddEntriesFrom(input, _repeated_typeField_codec);
+            break;
+          }
+          case 82: {
+            doubleField_.AddEntriesFrom(input, _repeated_doubleField_codec);
+            break;
+          }
+          case 90: {
+            floatField_.AddEntriesFrom(input, _repeated_floatField_codec);
+            break;
+          }
+          case 98: {
+            int64Field_.AddEntriesFrom(input, _repeated_int64Field_codec);
+            break;
+          }
+          case 106: {
+            uint64Field_.AddEntriesFrom(input, _repeated_uint64Field_codec);
+            break;
+          }
+          case 114: {
+            int32Field_.AddEntriesFrom(input, _repeated_int32Field_codec);
+            break;
+          }
+          case 122: {
+            uint32Field_.AddEntriesFrom(input, _repeated_uint32Field_codec);
+            break;
+          }
+          case 130: {
+            boolField_.AddEntriesFrom(input, _repeated_boolField_codec);
+            break;
+          }
+          case 138: {
+            stringField_.AddEntriesFrom(input, _repeated_stringField_codec);
+            break;
+          }
+          case 146: {
+            bytesField_.AddEntriesFrom(input, _repeated_bytesField_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class OneofWellKnownTypes : pb::IMessage<OneofWellKnownTypes> {
+    private static readonly pb::MessageParser<OneofWellKnownTypes> _parser = new pb::MessageParser<OneofWellKnownTypes>(() => new OneofWellKnownTypes());
+    public static pb::MessageParser<OneofWellKnownTypes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypes.Descriptor.MessageTypes[2]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public OneofWellKnownTypes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public OneofWellKnownTypes(OneofWellKnownTypes other) : this() {
+      switch (other.OneofFieldCase) {
+        case OneofFieldOneofCase.AnyField:
+          AnyField = other.AnyField.Clone();
+          break;
+        case OneofFieldOneofCase.ApiField:
+          ApiField = other.ApiField.Clone();
+          break;
+        case OneofFieldOneofCase.DurationField:
+          DurationField = other.DurationField.Clone();
+          break;
+        case OneofFieldOneofCase.EmptyField:
+          EmptyField = other.EmptyField.Clone();
+          break;
+        case OneofFieldOneofCase.FieldMaskField:
+          FieldMaskField = other.FieldMaskField.Clone();
+          break;
+        case OneofFieldOneofCase.SourceContextField:
+          SourceContextField = other.SourceContextField.Clone();
+          break;
+        case OneofFieldOneofCase.StructField:
+          StructField = other.StructField.Clone();
+          break;
+        case OneofFieldOneofCase.TimestampField:
+          TimestampField = other.TimestampField.Clone();
+          break;
+        case OneofFieldOneofCase.TypeField:
+          TypeField = other.TypeField.Clone();
+          break;
+        case OneofFieldOneofCase.DoubleField:
+          DoubleField = other.DoubleField;
+          break;
+        case OneofFieldOneofCase.FloatField:
+          FloatField = other.FloatField;
+          break;
+        case OneofFieldOneofCase.Int64Field:
+          Int64Field = other.Int64Field;
+          break;
+        case OneofFieldOneofCase.Uint64Field:
+          Uint64Field = other.Uint64Field;
+          break;
+        case OneofFieldOneofCase.Int32Field:
+          Int32Field = other.Int32Field;
+          break;
+        case OneofFieldOneofCase.Uint32Field:
+          Uint32Field = other.Uint32Field;
+          break;
+        case OneofFieldOneofCase.BoolField:
+          BoolField = other.BoolField;
+          break;
+        case OneofFieldOneofCase.StringField:
+          StringField = other.StringField;
+          break;
+        case OneofFieldOneofCase.BytesField:
+          BytesField = other.BytesField;
+          break;
+      }
+
+    }
+
+    public OneofWellKnownTypes Clone() {
+      return new OneofWellKnownTypes(this);
+    }
+
+    public const int AnyFieldFieldNumber = 1;
+    public global::Google.Protobuf.WellKnownTypes.Any AnyField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.AnyField ? (global::Google.Protobuf.WellKnownTypes.Any) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.AnyField;
+      }
+    }
+
+    public const int ApiFieldFieldNumber = 2;
+    public global::Google.Protobuf.WellKnownTypes.Api ApiField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.ApiField ? (global::Google.Protobuf.WellKnownTypes.Api) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.ApiField;
+      }
+    }
+
+    public const int DurationFieldFieldNumber = 3;
+    public global::Google.Protobuf.WellKnownTypes.Duration DurationField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.DurationField ? (global::Google.Protobuf.WellKnownTypes.Duration) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.DurationField;
+      }
+    }
+
+    public const int EmptyFieldFieldNumber = 4;
+    public global::Google.Protobuf.WellKnownTypes.Empty EmptyField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.EmptyField ? (global::Google.Protobuf.WellKnownTypes.Empty) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.EmptyField;
+      }
+    }
+
+    public const int FieldMaskFieldFieldNumber = 5;
+    public global::Google.Protobuf.WellKnownTypes.FieldMask FieldMaskField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.FieldMaskField ? (global::Google.Protobuf.WellKnownTypes.FieldMask) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.FieldMaskField;
+      }
+    }
+
+    public const int SourceContextFieldFieldNumber = 6;
+    public global::Google.Protobuf.WellKnownTypes.SourceContext SourceContextField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.SourceContextField ? (global::Google.Protobuf.WellKnownTypes.SourceContext) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.SourceContextField;
+      }
+    }
+
+    public const int StructFieldFieldNumber = 7;
+    public global::Google.Protobuf.WellKnownTypes.Struct StructField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.StructField ? (global::Google.Protobuf.WellKnownTypes.Struct) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.StructField;
+      }
+    }
+
+    public const int TimestampFieldFieldNumber = 8;
+    public global::Google.Protobuf.WellKnownTypes.Timestamp TimestampField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.TimestampField ? (global::Google.Protobuf.WellKnownTypes.Timestamp) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.TimestampField;
+      }
+    }
+
+    public const int TypeFieldFieldNumber = 9;
+    public global::Google.Protobuf.WellKnownTypes.Type TypeField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.TypeField ? (global::Google.Protobuf.WellKnownTypes.Type) oneofField_ : null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.TypeField;
+      }
+    }
+
+    public const int DoubleFieldFieldNumber = 10;
+    private static readonly pb::FieldCodec<double?> _oneof_doubleField_codec = pb::FieldCodec.ForStructWrapper<double>(82);
+    public double? DoubleField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.DoubleField ? (double?) oneofField_ : (double?) null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.DoubleField;
+      }
+    }
+
+    public const int FloatFieldFieldNumber = 11;
+    private static readonly pb::FieldCodec<float?> _oneof_floatField_codec = pb::FieldCodec.ForStructWrapper<float>(90);
+    public float? FloatField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.FloatField ? (float?) oneofField_ : (float?) null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.FloatField;
+      }
+    }
+
+    public const int Int64FieldFieldNumber = 12;
+    private static readonly pb::FieldCodec<long?> _oneof_int64Field_codec = pb::FieldCodec.ForStructWrapper<long>(98);
+    public long? Int64Field {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.Int64Field ? (long?) oneofField_ : (long?) null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.Int64Field;
+      }
+    }
+
+    public const int Uint64FieldFieldNumber = 13;
+    private static readonly pb::FieldCodec<ulong?> _oneof_uint64Field_codec = pb::FieldCodec.ForStructWrapper<ulong>(106);
+    public ulong? Uint64Field {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.Uint64Field ? (ulong?) oneofField_ : (ulong?) null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.Uint64Field;
+      }
+    }
+
+    public const int Int32FieldFieldNumber = 14;
+    private static readonly pb::FieldCodec<int?> _oneof_int32Field_codec = pb::FieldCodec.ForStructWrapper<int>(114);
+    public int? Int32Field {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.Int32Field ? (int?) oneofField_ : (int?) null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.Int32Field;
+      }
+    }
+
+    public const int Uint32FieldFieldNumber = 15;
+    private static readonly pb::FieldCodec<uint?> _oneof_uint32Field_codec = pb::FieldCodec.ForStructWrapper<uint>(122);
+    public uint? Uint32Field {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.Uint32Field ? (uint?) oneofField_ : (uint?) null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.Uint32Field;
+      }
+    }
+
+    public const int BoolFieldFieldNumber = 16;
+    private static readonly pb::FieldCodec<bool?> _oneof_boolField_codec = pb::FieldCodec.ForStructWrapper<bool>(130);
+    public bool? BoolField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.BoolField ? (bool?) oneofField_ : (bool?) null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.BoolField;
+      }
+    }
+
+    public const int StringFieldFieldNumber = 17;
+    private static readonly pb::FieldCodec<string> _oneof_stringField_codec = pb::FieldCodec.ForClassWrapper<string>(138);
+    public string StringField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.StringField ? (string) oneofField_ : (string) null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.StringField;
+      }
+    }
+
+    public const int BytesFieldFieldNumber = 18;
+    private static readonly pb::FieldCodec<pb::ByteString> _oneof_bytesField_codec = pb::FieldCodec.ForClassWrapper<pb::ByteString>(146);
+    public pb::ByteString BytesField {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.BytesField ? (pb::ByteString) oneofField_ : (pb::ByteString) null; }
+      set {
+        oneofField_ = value;
+        oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.BytesField;
+      }
+    }
+
+    private object oneofField_;
+    public enum OneofFieldOneofCase {
+      None = 0,
+      AnyField = 1,
+      ApiField = 2,
+      DurationField = 3,
+      EmptyField = 4,
+      FieldMaskField = 5,
+      SourceContextField = 6,
+      StructField = 7,
+      TimestampField = 8,
+      TypeField = 9,
+      DoubleField = 10,
+      FloatField = 11,
+      Int64Field = 12,
+      Uint64Field = 13,
+      Int32Field = 14,
+      Uint32Field = 15,
+      BoolField = 16,
+      StringField = 17,
+      BytesField = 18,
+    }
+    private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None;
+    public OneofFieldOneofCase OneofFieldCase {
+      get { return oneofFieldCase_; }
+    }
+
+    public void ClearOneofField() {
+      oneofFieldCase_ = OneofFieldOneofCase.None;
+      oneofField_ = null;
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as OneofWellKnownTypes);
+    }
+
+    public bool Equals(OneofWellKnownTypes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!object.Equals(AnyField, other.AnyField)) return false;
+      if (!object.Equals(ApiField, other.ApiField)) return false;
+      if (!object.Equals(DurationField, other.DurationField)) return false;
+      if (!object.Equals(EmptyField, other.EmptyField)) return false;
+      if (!object.Equals(FieldMaskField, other.FieldMaskField)) return false;
+      if (!object.Equals(SourceContextField, other.SourceContextField)) return false;
+      if (!object.Equals(StructField, other.StructField)) return false;
+      if (!object.Equals(TimestampField, other.TimestampField)) return false;
+      if (!object.Equals(TypeField, other.TypeField)) return false;
+      if (DoubleField != other.DoubleField) return false;
+      if (FloatField != other.FloatField) return false;
+      if (Int64Field != other.Int64Field) return false;
+      if (Uint64Field != other.Uint64Field) return false;
+      if (Int32Field != other.Int32Field) return false;
+      if (Uint32Field != other.Uint32Field) return false;
+      if (BoolField != other.BoolField) return false;
+      if (StringField != other.StringField) return false;
+      if (BytesField != other.BytesField) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      if (oneofFieldCase_ == OneofFieldOneofCase.AnyField) hash ^= AnyField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.ApiField) hash ^= ApiField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.DurationField) hash ^= DurationField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.EmptyField) hash ^= EmptyField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.FieldMaskField) hash ^= FieldMaskField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.SourceContextField) hash ^= SourceContextField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.StructField) hash ^= StructField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.TimestampField) hash ^= TimestampField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.TypeField) hash ^= TypeField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.DoubleField) hash ^= DoubleField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.FloatField) hash ^= FloatField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.Int64Field) hash ^= Int64Field.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.Uint64Field) hash ^= Uint64Field.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.Int32Field) hash ^= Int32Field.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.Uint32Field) hash ^= Uint32Field.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.BoolField) hash ^= BoolField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.StringField) hash ^= StringField.GetHashCode();
+      if (oneofFieldCase_ == OneofFieldOneofCase.BytesField) hash ^= BytesField.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      if (oneofFieldCase_ == OneofFieldOneofCase.AnyField) {
+        output.WriteRawTag(10);
+        output.WriteMessage(AnyField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.ApiField) {
+        output.WriteRawTag(18);
+        output.WriteMessage(ApiField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.DurationField) {
+        output.WriteRawTag(26);
+        output.WriteMessage(DurationField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.EmptyField) {
+        output.WriteRawTag(34);
+        output.WriteMessage(EmptyField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.FieldMaskField) {
+        output.WriteRawTag(42);
+        output.WriteMessage(FieldMaskField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.SourceContextField) {
+        output.WriteRawTag(50);
+        output.WriteMessage(SourceContextField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.StructField) {
+        output.WriteRawTag(58);
+        output.WriteMessage(StructField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.TimestampField) {
+        output.WriteRawTag(66);
+        output.WriteMessage(TimestampField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.TypeField) {
+        output.WriteRawTag(74);
+        output.WriteMessage(TypeField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.DoubleField) {
+        _oneof_doubleField_codec.WriteTagAndValue(output, (double?) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.FloatField) {
+        _oneof_floatField_codec.WriteTagAndValue(output, (float?) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.Int64Field) {
+        _oneof_int64Field_codec.WriteTagAndValue(output, (long?) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.Uint64Field) {
+        _oneof_uint64Field_codec.WriteTagAndValue(output, (ulong?) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.Int32Field) {
+        _oneof_int32Field_codec.WriteTagAndValue(output, (int?) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.Uint32Field) {
+        _oneof_uint32Field_codec.WriteTagAndValue(output, (uint?) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.BoolField) {
+        _oneof_boolField_codec.WriteTagAndValue(output, (bool?) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.StringField) {
+        _oneof_stringField_codec.WriteTagAndValue(output, (string) oneofField_);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.BytesField) {
+        _oneof_bytesField_codec.WriteTagAndValue(output, (pb::ByteString) oneofField_);
+      }
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      if (oneofFieldCase_ == OneofFieldOneofCase.AnyField) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(AnyField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.ApiField) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(ApiField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.DurationField) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(DurationField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.EmptyField) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(EmptyField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.FieldMaskField) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(FieldMaskField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.SourceContextField) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceContextField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.StructField) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(StructField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.TimestampField) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(TimestampField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.TypeField) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(TypeField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.DoubleField) {
+        size += _oneof_doubleField_codec.CalculateSizeWithTag(DoubleField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.FloatField) {
+        size += _oneof_floatField_codec.CalculateSizeWithTag(FloatField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.Int64Field) {
+        size += _oneof_int64Field_codec.CalculateSizeWithTag(Int64Field);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.Uint64Field) {
+        size += _oneof_uint64Field_codec.CalculateSizeWithTag(Uint64Field);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.Int32Field) {
+        size += _oneof_int32Field_codec.CalculateSizeWithTag(Int32Field);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.Uint32Field) {
+        size += _oneof_uint32Field_codec.CalculateSizeWithTag(Uint32Field);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.BoolField) {
+        size += _oneof_boolField_codec.CalculateSizeWithTag(BoolField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.StringField) {
+        size += _oneof_stringField_codec.CalculateSizeWithTag(StringField);
+      }
+      if (oneofFieldCase_ == OneofFieldOneofCase.BytesField) {
+        size += _oneof_bytesField_codec.CalculateSizeWithTag(BytesField);
+      }
+      return size;
+    }
+
+    public void MergeFrom(OneofWellKnownTypes other) {
+      if (other == null) {
+        return;
+      }
+      switch (other.OneofFieldCase) {
+        case OneofFieldOneofCase.AnyField:
+          AnyField = other.AnyField;
+          break;
+        case OneofFieldOneofCase.ApiField:
+          ApiField = other.ApiField;
+          break;
+        case OneofFieldOneofCase.DurationField:
+          DurationField = other.DurationField;
+          break;
+        case OneofFieldOneofCase.EmptyField:
+          EmptyField = other.EmptyField;
+          break;
+        case OneofFieldOneofCase.FieldMaskField:
+          FieldMaskField = other.FieldMaskField;
+          break;
+        case OneofFieldOneofCase.SourceContextField:
+          SourceContextField = other.SourceContextField;
+          break;
+        case OneofFieldOneofCase.StructField:
+          StructField = other.StructField;
+          break;
+        case OneofFieldOneofCase.TimestampField:
+          TimestampField = other.TimestampField;
+          break;
+        case OneofFieldOneofCase.TypeField:
+          TypeField = other.TypeField;
+          break;
+        case OneofFieldOneofCase.DoubleField:
+          DoubleField = other.DoubleField;
+          break;
+        case OneofFieldOneofCase.FloatField:
+          FloatField = other.FloatField;
+          break;
+        case OneofFieldOneofCase.Int64Field:
+          Int64Field = other.Int64Field;
+          break;
+        case OneofFieldOneofCase.Uint64Field:
+          Uint64Field = other.Uint64Field;
+          break;
+        case OneofFieldOneofCase.Int32Field:
+          Int32Field = other.Int32Field;
+          break;
+        case OneofFieldOneofCase.Uint32Field:
+          Uint32Field = other.Uint32Field;
+          break;
+        case OneofFieldOneofCase.BoolField:
+          BoolField = other.BoolField;
+          break;
+        case OneofFieldOneofCase.StringField:
+          StringField = other.StringField;
+          break;
+        case OneofFieldOneofCase.BytesField:
+          BytesField = other.BytesField;
+          break;
+      }
+
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            global::Google.Protobuf.WellKnownTypes.Any subBuilder = new global::Google.Protobuf.WellKnownTypes.Any();
+            if (oneofFieldCase_ == OneofFieldOneofCase.AnyField) {
+              subBuilder.MergeFrom(AnyField);
+            }
+            input.ReadMessage(subBuilder);
+            AnyField = subBuilder;
+            break;
+          }
+          case 18: {
+            global::Google.Protobuf.WellKnownTypes.Api subBuilder = new global::Google.Protobuf.WellKnownTypes.Api();
+            if (oneofFieldCase_ == OneofFieldOneofCase.ApiField) {
+              subBuilder.MergeFrom(ApiField);
+            }
+            input.ReadMessage(subBuilder);
+            ApiField = subBuilder;
+            break;
+          }
+          case 26: {
+            global::Google.Protobuf.WellKnownTypes.Duration subBuilder = new global::Google.Protobuf.WellKnownTypes.Duration();
+            if (oneofFieldCase_ == OneofFieldOneofCase.DurationField) {
+              subBuilder.MergeFrom(DurationField);
+            }
+            input.ReadMessage(subBuilder);
+            DurationField = subBuilder;
+            break;
+          }
+          case 34: {
+            global::Google.Protobuf.WellKnownTypes.Empty subBuilder = new global::Google.Protobuf.WellKnownTypes.Empty();
+            if (oneofFieldCase_ == OneofFieldOneofCase.EmptyField) {
+              subBuilder.MergeFrom(EmptyField);
+            }
+            input.ReadMessage(subBuilder);
+            EmptyField = subBuilder;
+            break;
+          }
+          case 42: {
+            global::Google.Protobuf.WellKnownTypes.FieldMask subBuilder = new global::Google.Protobuf.WellKnownTypes.FieldMask();
+            if (oneofFieldCase_ == OneofFieldOneofCase.FieldMaskField) {
+              subBuilder.MergeFrom(FieldMaskField);
+            }
+            input.ReadMessage(subBuilder);
+            FieldMaskField = subBuilder;
+            break;
+          }
+          case 50: {
+            global::Google.Protobuf.WellKnownTypes.SourceContext subBuilder = new global::Google.Protobuf.WellKnownTypes.SourceContext();
+            if (oneofFieldCase_ == OneofFieldOneofCase.SourceContextField) {
+              subBuilder.MergeFrom(SourceContextField);
+            }
+            input.ReadMessage(subBuilder);
+            SourceContextField = subBuilder;
+            break;
+          }
+          case 58: {
+            global::Google.Protobuf.WellKnownTypes.Struct subBuilder = new global::Google.Protobuf.WellKnownTypes.Struct();
+            if (oneofFieldCase_ == OneofFieldOneofCase.StructField) {
+              subBuilder.MergeFrom(StructField);
+            }
+            input.ReadMessage(subBuilder);
+            StructField = subBuilder;
+            break;
+          }
+          case 66: {
+            global::Google.Protobuf.WellKnownTypes.Timestamp subBuilder = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+            if (oneofFieldCase_ == OneofFieldOneofCase.TimestampField) {
+              subBuilder.MergeFrom(TimestampField);
+            }
+            input.ReadMessage(subBuilder);
+            TimestampField = subBuilder;
+            break;
+          }
+          case 74: {
+            global::Google.Protobuf.WellKnownTypes.Type subBuilder = new global::Google.Protobuf.WellKnownTypes.Type();
+            if (oneofFieldCase_ == OneofFieldOneofCase.TypeField) {
+              subBuilder.MergeFrom(TypeField);
+            }
+            input.ReadMessage(subBuilder);
+            TypeField = subBuilder;
+            break;
+          }
+          case 82: {
+            DoubleField = _oneof_doubleField_codec.Read(input);
+            break;
+          }
+          case 90: {
+            FloatField = _oneof_floatField_codec.Read(input);
+            break;
+          }
+          case 98: {
+            Int64Field = _oneof_int64Field_codec.Read(input);
+            break;
+          }
+          case 106: {
+            Uint64Field = _oneof_uint64Field_codec.Read(input);
+            break;
+          }
+          case 114: {
+            Int32Field = _oneof_int32Field_codec.Read(input);
+            break;
+          }
+          case 122: {
+            Uint32Field = _oneof_uint32Field_codec.Read(input);
+            break;
+          }
+          case 130: {
+            BoolField = _oneof_boolField_codec.Read(input);
+            break;
+          }
+          case 138: {
+            StringField = _oneof_stringField_codec.Read(input);
+            break;
+          }
+          case 146: {
+            BytesField = _oneof_bytesField_codec.Read(input);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  public sealed partial class MapWellKnownTypes : pb::IMessage<MapWellKnownTypes> {
+    private static readonly pb::MessageParser<MapWellKnownTypes> _parser = new pb::MessageParser<MapWellKnownTypes>(() => new MapWellKnownTypes());
+    public static pb::MessageParser<MapWellKnownTypes> Parser { get { return _parser; } }
+
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.TestProtos.UnittestWellKnownTypes.Descriptor.MessageTypes[3]; }
+    }
+
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    public MapWellKnownTypes() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    public MapWellKnownTypes(MapWellKnownTypes other) : this() {
+      anyField_ = other.anyField_.Clone();
+      apiField_ = other.apiField_.Clone();
+      durationField_ = other.durationField_.Clone();
+      emptyField_ = other.emptyField_.Clone();
+      fieldMaskField_ = other.fieldMaskField_.Clone();
+      sourceContextField_ = other.sourceContextField_.Clone();
+      structField_ = other.structField_.Clone();
+      timestampField_ = other.timestampField_.Clone();
+      typeField_ = other.typeField_.Clone();
+      doubleField_ = other.doubleField_.Clone();
+      floatField_ = other.floatField_.Clone();
+      int64Field_ = other.int64Field_.Clone();
+      uint64Field_ = other.uint64Field_.Clone();
+      int32Field_ = other.int32Field_.Clone();
+      uint32Field_ = other.uint32Field_.Clone();
+      boolField_ = other.boolField_.Clone();
+      stringField_ = other.stringField_.Clone();
+      bytesField_ = other.bytesField_.Clone();
+    }
+
+    public MapWellKnownTypes Clone() {
+      return new MapWellKnownTypes(this);
+    }
+
+    public const int AnyFieldFieldNumber = 1;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Any>.Codec _map_anyField_codec
+        = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Any>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Any.Parser), 10);
+    private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Any> anyField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Any>();
+    public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Any> AnyField {
+      get { return anyField_; }
+    }
+
+    public const int ApiFieldFieldNumber = 2;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Api>.Codec _map_apiField_codec
+        = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Api>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Api.Parser), 18);
+    private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Api> apiField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Api>();
+    public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Api> ApiField {
+      get { return apiField_; }
+    }
+
+    public const int DurationFieldFieldNumber = 3;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Duration>.Codec _map_durationField_codec
+        = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Duration>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Duration.Parser), 26);
+    private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Duration> durationField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Duration>();
+    public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Duration> DurationField {
+      get { return durationField_; }
+    }
+
+    public const int EmptyFieldFieldNumber = 4;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Empty>.Codec _map_emptyField_codec
+        = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Empty>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Empty.Parser), 34);
+    private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Empty> emptyField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Empty>();
+    public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Empty> EmptyField {
+      get { return emptyField_; }
+    }
+
+    public const int FieldMaskFieldFieldNumber = 5;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.FieldMask>.Codec _map_fieldMaskField_codec
+        = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.FieldMask>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.FieldMask.Parser), 42);
+    private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.FieldMask> fieldMaskField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.FieldMask>();
+    public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.FieldMask> FieldMaskField {
+      get { return fieldMaskField_; }
+    }
+
+    public const int SourceContextFieldFieldNumber = 6;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.SourceContext>.Codec _map_sourceContextField_codec
+        = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.SourceContext>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.SourceContext.Parser), 50);
+    private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.SourceContext> sourceContextField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.SourceContext>();
+    public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.SourceContext> SourceContextField {
+      get { return sourceContextField_; }
+    }
+
+    public const int StructFieldFieldNumber = 7;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Struct>.Codec _map_structField_codec
+        = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Struct>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Struct.Parser), 58);
+    private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Struct> structField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Struct>();
+    public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Struct> StructField {
+      get { return structField_; }
+    }
+
+    public const int TimestampFieldFieldNumber = 8;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Timestamp>.Codec _map_timestampField_codec
+        = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Timestamp>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Timestamp.Parser), 66);
+    private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Timestamp> timestampField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Timestamp>();
+    public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Timestamp> TimestampField {
+      get { return timestampField_; }
+    }
+
+    public const int TypeFieldFieldNumber = 9;
+    private static readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Type>.Codec _map_typeField_codec
+        = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Type>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Type.Parser), 74);
+    private readonly pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Type> typeField_ = new pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Type>();
+    public pbc::MapField<int, global::Google.Protobuf.WellKnownTypes.Type> TypeField {
+      get { return typeField_; }
+    }
+
+    public const int DoubleFieldFieldNumber = 10;
+    private static readonly pbc::MapField<int, double?>.Codec _map_doubleField_codec
+        = new pbc::MapField<int, double?>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper<double>(18), 82);
+    private readonly pbc::MapField<int, double?> doubleField_ = new pbc::MapField<int, double?>(true);
+    public pbc::MapField<int, double?> DoubleField {
+      get { return doubleField_; }
+    }
+
+    public const int FloatFieldFieldNumber = 11;
+    private static readonly pbc::MapField<int, float?>.Codec _map_floatField_codec
+        = new pbc::MapField<int, float?>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper<float>(18), 90);
+    private readonly pbc::MapField<int, float?> floatField_ = new pbc::MapField<int, float?>(true);
+    public pbc::MapField<int, float?> FloatField {
+      get { return floatField_; }
+    }
+
+    public const int Int64FieldFieldNumber = 12;
+    private static readonly pbc::MapField<int, long?>.Codec _map_int64Field_codec
+        = new pbc::MapField<int, long?>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper<long>(18), 98);
+    private readonly pbc::MapField<int, long?> int64Field_ = new pbc::MapField<int, long?>(true);
+    public pbc::MapField<int, long?> Int64Field {
+      get { return int64Field_; }
+    }
+
+    public const int Uint64FieldFieldNumber = 13;
+    private static readonly pbc::MapField<int, ulong?>.Codec _map_uint64Field_codec
+        = new pbc::MapField<int, ulong?>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper<ulong>(18), 106);
+    private readonly pbc::MapField<int, ulong?> uint64Field_ = new pbc::MapField<int, ulong?>(true);
+    public pbc::MapField<int, ulong?> Uint64Field {
+      get { return uint64Field_; }
+    }
+
+    public const int Int32FieldFieldNumber = 14;
+    private static readonly pbc::MapField<int, int?>.Codec _map_int32Field_codec
+        = new pbc::MapField<int, int?>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper<int>(18), 114);
+    private readonly pbc::MapField<int, int?> int32Field_ = new pbc::MapField<int, int?>(true);
+    public pbc::MapField<int, int?> Int32Field {
+      get { return int32Field_; }
+    }
+
+    public const int Uint32FieldFieldNumber = 15;
+    private static readonly pbc::MapField<int, uint?>.Codec _map_uint32Field_codec
+        = new pbc::MapField<int, uint?>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper<uint>(18), 122);
+    private readonly pbc::MapField<int, uint?> uint32Field_ = new pbc::MapField<int, uint?>(true);
+    public pbc::MapField<int, uint?> Uint32Field {
+      get { return uint32Field_; }
+    }
+
+    public const int BoolFieldFieldNumber = 16;
+    private static readonly pbc::MapField<int, bool?>.Codec _map_boolField_codec
+        = new pbc::MapField<int, bool?>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForStructWrapper<bool>(18), 130);
+    private readonly pbc::MapField<int, bool?> boolField_ = new pbc::MapField<int, bool?>(true);
+    public pbc::MapField<int, bool?> BoolField {
+      get { return boolField_; }
+    }
+
+    public const int StringFieldFieldNumber = 17;
+    private static readonly pbc::MapField<int, string>.Codec _map_stringField_codec
+        = new pbc::MapField<int, string>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForClassWrapper<string>(18), 138);
+    private readonly pbc::MapField<int, string> stringField_ = new pbc::MapField<int, string>(true);
+    public pbc::MapField<int, string> StringField {
+      get { return stringField_; }
+    }
+
+    public const int BytesFieldFieldNumber = 18;
+    private static readonly pbc::MapField<int, pb::ByteString>.Codec _map_bytesField_codec
+        = new pbc::MapField<int, pb::ByteString>.Codec(pb::FieldCodec.ForInt32(8), pb::FieldCodec.ForClassWrapper<pb::ByteString>(18), 146);
+    private readonly pbc::MapField<int, pb::ByteString> bytesField_ = new pbc::MapField<int, pb::ByteString>(true);
+    public pbc::MapField<int, pb::ByteString> BytesField {
+      get { return bytesField_; }
+    }
+
+    public override bool Equals(object other) {
+      return Equals(other as MapWellKnownTypes);
+    }
+
+    public bool Equals(MapWellKnownTypes other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (!AnyField.Equals(other.AnyField)) return false;
+      if (!ApiField.Equals(other.ApiField)) return false;
+      if (!DurationField.Equals(other.DurationField)) return false;
+      if (!EmptyField.Equals(other.EmptyField)) return false;
+      if (!FieldMaskField.Equals(other.FieldMaskField)) return false;
+      if (!SourceContextField.Equals(other.SourceContextField)) return false;
+      if (!StructField.Equals(other.StructField)) return false;
+      if (!TimestampField.Equals(other.TimestampField)) return false;
+      if (!TypeField.Equals(other.TypeField)) return false;
+      if (!DoubleField.Equals(other.DoubleField)) return false;
+      if (!FloatField.Equals(other.FloatField)) return false;
+      if (!Int64Field.Equals(other.Int64Field)) return false;
+      if (!Uint64Field.Equals(other.Uint64Field)) return false;
+      if (!Int32Field.Equals(other.Int32Field)) return false;
+      if (!Uint32Field.Equals(other.Uint32Field)) return false;
+      if (!BoolField.Equals(other.BoolField)) return false;
+      if (!StringField.Equals(other.StringField)) return false;
+      if (!BytesField.Equals(other.BytesField)) return false;
+      return true;
+    }
+
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= AnyField.GetHashCode();
+      hash ^= ApiField.GetHashCode();
+      hash ^= DurationField.GetHashCode();
+      hash ^= EmptyField.GetHashCode();
+      hash ^= FieldMaskField.GetHashCode();
+      hash ^= SourceContextField.GetHashCode();
+      hash ^= StructField.GetHashCode();
+      hash ^= TimestampField.GetHashCode();
+      hash ^= TypeField.GetHashCode();
+      hash ^= DoubleField.GetHashCode();
+      hash ^= FloatField.GetHashCode();
+      hash ^= Int64Field.GetHashCode();
+      hash ^= Uint64Field.GetHashCode();
+      hash ^= Int32Field.GetHashCode();
+      hash ^= Uint32Field.GetHashCode();
+      hash ^= BoolField.GetHashCode();
+      hash ^= StringField.GetHashCode();
+      hash ^= BytesField.GetHashCode();
+      return hash;
+    }
+
+    public override string ToString() {
+      return pb::JsonFormatter.Default.Format(this);
+    }
+
+    public void WriteTo(pb::CodedOutputStream output) {
+      anyField_.WriteTo(output, _map_anyField_codec);
+      apiField_.WriteTo(output, _map_apiField_codec);
+      durationField_.WriteTo(output, _map_durationField_codec);
+      emptyField_.WriteTo(output, _map_emptyField_codec);
+      fieldMaskField_.WriteTo(output, _map_fieldMaskField_codec);
+      sourceContextField_.WriteTo(output, _map_sourceContextField_codec);
+      structField_.WriteTo(output, _map_structField_codec);
+      timestampField_.WriteTo(output, _map_timestampField_codec);
+      typeField_.WriteTo(output, _map_typeField_codec);
+      doubleField_.WriteTo(output, _map_doubleField_codec);
+      floatField_.WriteTo(output, _map_floatField_codec);
+      int64Field_.WriteTo(output, _map_int64Field_codec);
+      uint64Field_.WriteTo(output, _map_uint64Field_codec);
+      int32Field_.WriteTo(output, _map_int32Field_codec);
+      uint32Field_.WriteTo(output, _map_uint32Field_codec);
+      boolField_.WriteTo(output, _map_boolField_codec);
+      stringField_.WriteTo(output, _map_stringField_codec);
+      bytesField_.WriteTo(output, _map_bytesField_codec);
+    }
+
+    public int CalculateSize() {
+      int size = 0;
+      size += anyField_.CalculateSize(_map_anyField_codec);
+      size += apiField_.CalculateSize(_map_apiField_codec);
+      size += durationField_.CalculateSize(_map_durationField_codec);
+      size += emptyField_.CalculateSize(_map_emptyField_codec);
+      size += fieldMaskField_.CalculateSize(_map_fieldMaskField_codec);
+      size += sourceContextField_.CalculateSize(_map_sourceContextField_codec);
+      size += structField_.CalculateSize(_map_structField_codec);
+      size += timestampField_.CalculateSize(_map_timestampField_codec);
+      size += typeField_.CalculateSize(_map_typeField_codec);
+      size += doubleField_.CalculateSize(_map_doubleField_codec);
+      size += floatField_.CalculateSize(_map_floatField_codec);
+      size += int64Field_.CalculateSize(_map_int64Field_codec);
+      size += uint64Field_.CalculateSize(_map_uint64Field_codec);
+      size += int32Field_.CalculateSize(_map_int32Field_codec);
+      size += uint32Field_.CalculateSize(_map_uint32Field_codec);
+      size += boolField_.CalculateSize(_map_boolField_codec);
+      size += stringField_.CalculateSize(_map_stringField_codec);
+      size += bytesField_.CalculateSize(_map_bytesField_codec);
+      return size;
+    }
+
+    public void MergeFrom(MapWellKnownTypes other) {
+      if (other == null) {
+        return;
+      }
+      anyField_.Add(other.anyField_);
+      apiField_.Add(other.apiField_);
+      durationField_.Add(other.durationField_);
+      emptyField_.Add(other.emptyField_);
+      fieldMaskField_.Add(other.fieldMaskField_);
+      sourceContextField_.Add(other.sourceContextField_);
+      structField_.Add(other.structField_);
+      timestampField_.Add(other.timestampField_);
+      typeField_.Add(other.typeField_);
+      doubleField_.Add(other.doubleField_);
+      floatField_.Add(other.floatField_);
+      int64Field_.Add(other.int64Field_);
+      uint64Field_.Add(other.uint64Field_);
+      int32Field_.Add(other.int32Field_);
+      uint32Field_.Add(other.uint32Field_);
+      boolField_.Add(other.boolField_);
+      stringField_.Add(other.stringField_);
+      bytesField_.Add(other.bytesField_);
+    }
+
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 10: {
+            anyField_.AddEntriesFrom(input, _map_anyField_codec);
+            break;
+          }
+          case 18: {
+            apiField_.AddEntriesFrom(input, _map_apiField_codec);
+            break;
+          }
+          case 26: {
+            durationField_.AddEntriesFrom(input, _map_durationField_codec);
+            break;
+          }
+          case 34: {
+            emptyField_.AddEntriesFrom(input, _map_emptyField_codec);
+            break;
+          }
+          case 42: {
+            fieldMaskField_.AddEntriesFrom(input, _map_fieldMaskField_codec);
+            break;
+          }
+          case 50: {
+            sourceContextField_.AddEntriesFrom(input, _map_sourceContextField_codec);
+            break;
+          }
+          case 58: {
+            structField_.AddEntriesFrom(input, _map_structField_codec);
+            break;
+          }
+          case 66: {
+            timestampField_.AddEntriesFrom(input, _map_timestampField_codec);
+            break;
+          }
+          case 74: {
+            typeField_.AddEntriesFrom(input, _map_typeField_codec);
+            break;
+          }
+          case 82: {
+            doubleField_.AddEntriesFrom(input, _map_doubleField_codec);
+            break;
+          }
+          case 90: {
+            floatField_.AddEntriesFrom(input, _map_floatField_codec);
+            break;
+          }
+          case 98: {
+            int64Field_.AddEntriesFrom(input, _map_int64Field_codec);
+            break;
+          }
+          case 106: {
+            uint64Field_.AddEntriesFrom(input, _map_uint64Field_codec);
+            break;
+          }
+          case 114: {
+            int32Field_.AddEntriesFrom(input, _map_int32Field_codec);
+            break;
+          }
+          case 122: {
+            uint32Field_.AddEntriesFrom(input, _map_uint32Field_codec);
+            break;
+          }
+          case 130: {
+            boolField_.AddEntriesFrom(input, _map_boolField_codec);
+            break;
+          }
+          case 138: {
+            stringField_.AddEntriesFrom(input, _map_stringField_codec);
+            break;
+          }
+          case 146: {
+            bytesField_.AddEntriesFrom(input, _map_bytesField_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code

+ 104 - 0
csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs

@@ -0,0 +1,104 @@
+#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 NUnit.Framework;
+using System;
+
+namespace Google.Protobuf.WellKnownTypes
+{
+    public class DurationTest
+    {
+        [Test]
+        public void ToTimeSpan()
+        {
+            Assert.AreEqual(TimeSpan.FromSeconds(1), new Duration { Seconds = 1 }.ToTimeSpan());
+            Assert.AreEqual(TimeSpan.FromSeconds(-1), new Duration { Seconds = -1 }.ToTimeSpan());
+            Assert.AreEqual(TimeSpan.FromMilliseconds(1), new Duration { Nanos = 1000000 }.ToTimeSpan());
+            Assert.AreEqual(TimeSpan.FromMilliseconds(-1), new Duration { Nanos = -1000000 }.ToTimeSpan());
+            Assert.AreEqual(TimeSpan.FromTicks(1), new Duration { Nanos = 100 }.ToTimeSpan());
+            Assert.AreEqual(TimeSpan.FromTicks(-1), new Duration { Nanos = -100 }.ToTimeSpan());
+
+            // Rounding is towards 0
+            Assert.AreEqual(TimeSpan.FromTicks(2), new Duration { Nanos = 250 }.ToTimeSpan());
+            Assert.AreEqual(TimeSpan.FromTicks(-2), new Duration { Nanos = -250 }.ToTimeSpan());
+
+            // Non-normalized durations
+            Assert.AreEqual(TimeSpan.FromSeconds(3), new Duration { Seconds = 1, Nanos = 2 * Duration.NanosecondsPerSecond }.ToTimeSpan());
+            Assert.AreEqual(TimeSpan.FromSeconds(1), new Duration { Seconds = 3, Nanos = -2 * Duration.NanosecondsPerSecond }.ToTimeSpan());
+            Assert.AreEqual(TimeSpan.FromSeconds(-1), new Duration { Seconds = 1, Nanos = -2 * Duration.NanosecondsPerSecond }.ToTimeSpan());
+        }
+
+        [Test]
+        public void Addition()
+        {
+            Assert.AreEqual(new Duration { Seconds = 2, Nanos = 100000000 },
+                new Duration { Seconds = 1, Nanos = 600000000 } + new Duration { Nanos = 500000000 });
+            Assert.AreEqual(new Duration { Seconds = -2, Nanos = -100000000 },
+                new Duration { Seconds = -1, Nanos = -600000000 } + new Duration { Nanos = -500000000 });
+            Assert.AreEqual(new Duration { Seconds = 1, Nanos = 100000000 },
+                new Duration { Seconds = 1, Nanos = 600000000 } + new Duration { Nanos = -500000000 });
+
+            // Non-normalized durations, or non-normalized intermediate results
+            Assert.AreEqual(new Duration { Seconds = 1 },
+                new Duration { Seconds = 1, Nanos = -500000000 } + new Duration { Nanos = 500000000 });
+
+            Assert.AreEqual(new Duration { Nanos = -900000000 },
+                new Duration { Seconds = -1, Nanos = -100000000 } + new Duration { Nanos = 200000000 });
+            Assert.AreEqual(new Duration { Nanos = 900000000 },
+                new Duration { Seconds = 1, Nanos = 100000000 } + new Duration { Nanos = -200000000 });
+        }
+
+        [Test]
+        public void Subtraction()
+        {
+            Assert.AreEqual(new Duration { Seconds = 1, Nanos = 100000000 },
+                new Duration { Seconds = 1, Nanos = 600000000 } - new Duration { Nanos = 500000000 });
+            Assert.AreEqual(new Duration { Seconds = -1, Nanos = -100000000 },
+                new Duration { Seconds = -1, Nanos = -600000000 } - new Duration { Nanos = -500000000 });
+            Assert.AreEqual(new Duration { Seconds = 2, Nanos = 100000000 },
+                new Duration { Seconds = 1, Nanos = 600000000 } - new Duration { Nanos = -500000000 });
+
+            // Non-normalized durations
+            Assert.AreEqual(new Duration(),
+                new Duration { Seconds = 1, Nanos = -500000000 } - new Duration { Nanos = 500000000 });
+            Assert.AreEqual(new Duration { Seconds = 1 },
+                new Duration { Nanos = 2000000000 } - new Duration { Nanos = 1000000000 });
+        }
+
+        [Test]
+        public void FromTimeSpan()
+        {
+            Assert.AreEqual(new Duration { Seconds = 1 }, Duration.FromTimeSpan(TimeSpan.FromSeconds(1)));
+            Assert.AreEqual(new Duration { Nanos = Duration.NanosecondsPerTick }, Duration.FromTimeSpan(TimeSpan.FromTicks(1)));
+        }
+    }
+}

+ 84 - 0
csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs

@@ -0,0 +1,84 @@
+#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 NUnit.Framework;
+using System;
+
+namespace Google.Protobuf.WellKnownTypes
+{
+    public class TimestampTest
+    {
+        [Test]
+        public void FromAndToDateTime()
+        {
+            DateTime utcMin = DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
+            DateTime utcMax = DateTime.SpecifyKind(DateTime.MaxValue, DateTimeKind.Utc);
+            AssertRoundtrip(new Timestamp { Seconds = -62135596800 }, utcMin);
+            AssertRoundtrip(new Timestamp { Seconds = 253402300799, Nanos = 999999900 }, utcMax);
+            AssertRoundtrip(new Timestamp(), new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc));
+            AssertRoundtrip(new Timestamp { Nanos = 1000000}, new DateTime(1970, 1, 1, 0, 0, 0, 1, DateTimeKind.Utc));
+            AssertRoundtrip(new Timestamp { Seconds = -1, Nanos = 999000000 }, new DateTime(1969, 12, 31, 23, 59, 59, 999, DateTimeKind.Utc));
+            AssertRoundtrip(new Timestamp { Seconds = 3600 }, new DateTime(1970, 1, 1, 1, 0, 0, DateTimeKind.Utc));
+            AssertRoundtrip(new Timestamp { Seconds = -3600 }, new DateTime(1969, 12, 31, 23, 0, 0, DateTimeKind.Utc));
+        }
+
+        [Test]
+        public void ToDateTimeTruncation()
+        {
+            var t1 = new Timestamp { Seconds = 1, Nanos = 1000000 + Duration.NanosecondsPerTick - 1 };
+            Assert.AreEqual(new DateTime(1970, 1, 1, 0, 0, 1, DateTimeKind.Utc).AddMilliseconds(1), t1.ToDateTime());
+
+            var t2 = new Timestamp { Seconds = -1, Nanos = 1000000 + Duration.NanosecondsPerTick - 1 };
+            Assert.AreEqual(new DateTime(1969, 12, 31, 23, 59, 59).AddMilliseconds(1), t2.ToDateTime());
+        }
+
+        private static void AssertRoundtrip(Timestamp timestamp, DateTime dateTime)
+        {
+            Assert.AreEqual(timestamp, Timestamp.FromDateTime(dateTime));
+            Assert.AreEqual(dateTime, timestamp.ToDateTime());
+            Assert.AreEqual(DateTimeKind.Utc, timestamp.ToDateTime().Kind);
+        }
+
+        [Test]
+        public void Arithmetic()
+        {
+            Timestamp t1 = new Timestamp { Seconds = 10000, Nanos = 5000 };
+            Timestamp t2 = new Timestamp { Seconds = 8000, Nanos = 10000 };
+            Duration difference = new Duration { Seconds = 1999, Nanos = Duration.NanosecondsPerSecond - 5000 };
+            Assert.AreEqual(difference, t1 - t2);
+            Assert.AreEqual(-difference, t2 - t1);
+            
+            Assert.AreEqual(t1, t2 + difference);
+            Assert.AreEqual(t2, t1 - difference);
+        }
+    }
+}

+ 349 - 0
csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs

@@ -0,0 +1,349 @@
+#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 Google.Protobuf.TestProtos;
+using NUnit.Framework;
+using System.Collections;
+using System.IO;
+
+namespace Google.Protobuf.WellKnownTypes
+{
+    public class WrappersTest
+    {
+        [Test]
+        public void NullIsDefault()
+        {
+            var message = new TestWellKnownTypes();
+            Assert.IsNull(message.StringField);
+            Assert.IsNull(message.BytesField);
+            Assert.IsNull(message.BoolField);
+            Assert.IsNull(message.FloatField);
+            Assert.IsNull(message.DoubleField);
+            Assert.IsNull(message.Int32Field);
+            Assert.IsNull(message.Int64Field);
+            Assert.IsNull(message.Uint32Field);
+            Assert.IsNull(message.Uint64Field);
+        }
+
+        [Test]
+        public void NonDefaultSingleValues()
+        {
+            var message = new TestWellKnownTypes
+            {
+                StringField = "x",
+                BytesField = ByteString.CopyFrom(1, 2, 3),
+                BoolField = true,
+                FloatField = 12.5f,
+                DoubleField = 12.25d,
+                Int32Field = 1,
+                Int64Field = 2,
+                Uint32Field = 3,
+                Uint64Field = 4
+            };
+
+            var bytes = message.ToByteArray();
+            var parsed = TestWellKnownTypes.Parser.ParseFrom(bytes);
+
+            Assert.AreEqual("x", parsed.StringField);
+            Assert.AreEqual(ByteString.CopyFrom(1, 2, 3), parsed.BytesField);
+            Assert.AreEqual(true, parsed.BoolField);
+            Assert.AreEqual(12.5f, parsed.FloatField);
+            Assert.AreEqual(12.25d, parsed.DoubleField);
+            Assert.AreEqual(1, parsed.Int32Field);
+            Assert.AreEqual(2L, parsed.Int64Field);
+            Assert.AreEqual(3U, parsed.Uint32Field);
+            Assert.AreEqual(4UL, parsed.Uint64Field);
+        }
+
+        [Test]
+        public void NonNullDefaultIsPreservedThroughSerialization()
+        {
+            var message = new TestWellKnownTypes
+            {
+                StringField = "",
+                BytesField = ByteString.Empty,
+                BoolField = false,
+                FloatField = 0f,
+                DoubleField = 0d,
+                Int32Field = 0,
+                Int64Field = 0,
+                Uint32Field = 0,
+                Uint64Field = 0
+            };
+
+            var bytes = message.ToByteArray();
+            var parsed = TestWellKnownTypes.Parser.ParseFrom(bytes);
+
+            Assert.AreEqual("", parsed.StringField);
+            Assert.AreEqual(ByteString.Empty, parsed.BytesField);
+            Assert.AreEqual(false, parsed.BoolField);
+            Assert.AreEqual(0f, parsed.FloatField);
+            Assert.AreEqual(0d, parsed.DoubleField);
+            Assert.AreEqual(0, parsed.Int32Field);
+            Assert.AreEqual(0L, parsed.Int64Field);
+            Assert.AreEqual(0U, parsed.Uint32Field);
+            Assert.AreEqual(0UL, parsed.Uint64Field);
+        }
+
+        [Test]
+        public void RepeatedWrappersProhibitNullItems()
+        {
+            var message = new RepeatedWellKnownTypes();
+            Assert.Throws<ArgumentNullException>(() => message.BoolField.Add((bool?) null));
+            Assert.Throws<ArgumentNullException>(() => message.Int32Field.Add((int?) null));
+            Assert.Throws<ArgumentNullException>(() => message.StringField.Add((string) null));
+            Assert.Throws<ArgumentNullException>(() => message.BytesField.Add((ByteString) null));
+        }
+
+        [Test]
+        public void RepeatedWrappersSerializeDeserialize()
+        {
+            var message = new RepeatedWellKnownTypes
+            {
+                BoolField = { true, false },
+                BytesField = { ByteString.CopyFrom(1, 2, 3), ByteString.CopyFrom(4, 5, 6), ByteString.Empty },
+                DoubleField = { 12.5, -1.5, 0d },
+                FloatField = { 123.25f, -20f, 0f },
+                Int32Field = { int.MaxValue, int.MinValue, 0 },
+                Int64Field = { long.MaxValue, long.MinValue, 0L },                
+                StringField = { "First", "Second", "" },
+                Uint32Field = { uint.MaxValue, uint.MinValue, 0U },
+                Uint64Field = { ulong.MaxValue, ulong.MinValue, 0UL },
+            };
+            var bytes = message.ToByteArray();
+            var parsed = RepeatedWellKnownTypes.Parser.ParseFrom(bytes);
+
+            Assert.AreEqual(message, parsed);
+            // Just to test a single value for sanity...
+            Assert.AreEqual("Second", message.StringField[1]);
+        }
+
+        [Test]
+        public void MapWrappersSerializeDeserialize()
+        {
+            var message = new MapWellKnownTypes
+            {
+                BoolField = { { 10, false }, { 20, true } },
+                BytesField = {
+                    { -1, ByteString.CopyFrom(1, 2, 3) },
+                    { 10, ByteString.CopyFrom(4, 5, 6) },
+                    { 1000, ByteString.Empty },
+                    { 10000, null }
+                },
+                DoubleField = { { 1, 12.5 }, { 10, -1.5 }, { 20, 0d } },
+                FloatField = { { 2, 123.25f }, { 3, -20f }, { 4, 0f } },
+                Int32Field = { { 5, int.MaxValue }, { 6, int.MinValue }, { 7, 0 } },
+                Int64Field = { { 8, long.MaxValue }, { 9, long.MinValue }, { 10, 0L } },
+                StringField = { { 11, "First" }, { 12, "Second" }, { 13, "" }, { 14, null } },
+                Uint32Field = { { 15, uint.MaxValue }, { 16, uint.MinValue }, { 17, 0U } },
+                Uint64Field = { { 18, ulong.MaxValue }, { 19, ulong.MinValue }, { 20, 0UL } },
+            };
+
+            var bytes = message.ToByteArray();
+            var parsed = MapWellKnownTypes.Parser.ParseFrom(bytes);
+
+            Assert.AreEqual(message, parsed);
+            // Just to test a single value for sanity...
+            Assert.AreEqual("Second", message.StringField[12]);
+        }
+
+        [Test]
+        public void Reflection_SingleValues()
+        {
+            var message = new TestWellKnownTypes
+            {
+                StringField = "x",
+                BytesField = ByteString.CopyFrom(1, 2, 3),
+                BoolField = true,
+                FloatField = 12.5f,
+                DoubleField = 12.25d,
+                Int32Field = 1,
+                Int64Field = 2,
+                Uint32Field = 3,
+                Uint64Field = 4
+            };
+            var fields = TestWellKnownTypes.Descriptor.Fields;
+
+            Assert.AreEqual("x", fields[TestWellKnownTypes.StringFieldFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(ByteString.CopyFrom(1, 2, 3), fields[TestWellKnownTypes.BytesFieldFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(true, fields[TestWellKnownTypes.BoolFieldFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(12.5f, fields[TestWellKnownTypes.FloatFieldFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(12.25d, fields[TestWellKnownTypes.DoubleFieldFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(1, fields[TestWellKnownTypes.Int32FieldFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(2L, fields[TestWellKnownTypes.Int64FieldFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(3U, fields[TestWellKnownTypes.Uint32FieldFieldNumber].Accessor.GetValue(message));
+            Assert.AreEqual(4UL, fields[TestWellKnownTypes.Uint64FieldFieldNumber].Accessor.GetValue(message));
+
+            // And a couple of null fields...
+            message.StringField = null;
+            message.FloatField = null;
+            Assert.IsNull(fields[TestWellKnownTypes.StringFieldFieldNumber].Accessor.GetValue(message));
+            Assert.IsNull(fields[TestWellKnownTypes.FloatFieldFieldNumber].Accessor.GetValue(message));
+        }
+
+        [Test]
+        public void Reflection_RepeatedFields()
+        {
+            // Just a single example... note that we can't have a null value here
+            var message = new RepeatedWellKnownTypes { Int32Field = { 1, 2 } };
+            var fields = RepeatedWellKnownTypes.Descriptor.Fields;
+            var list = (IList) fields[RepeatedWellKnownTypes.Int32FieldFieldNumber].Accessor.GetValue(message);
+            CollectionAssert.AreEqual(new[] { 1, 2 }, list);
+        }
+
+        [Test]
+        public void Reflection_MapFields()
+        {
+            // Just a single example... note that we can't have a null value here
+            var message = new MapWellKnownTypes { Int32Field = { { 1, 2 }, { 3, null } } };
+            var fields = MapWellKnownTypes.Descriptor.Fields;
+            var dictionary = (IDictionary) fields[MapWellKnownTypes.Int32FieldFieldNumber].Accessor.GetValue(message);
+            Assert.AreEqual(2, dictionary[1]);
+            Assert.IsNull(dictionary[3]);
+            Assert.IsTrue(dictionary.Contains(3));
+        }
+
+        [Test]
+        public void Oneof()
+        {
+            var message = new OneofWellKnownTypes { EmptyField = new Empty() };
+            // Start off with a non-wrapper
+            Assert.AreEqual(OneofWellKnownTypes.OneofFieldOneofCase.EmptyField, message.OneofFieldCase);
+            AssertOneofRoundTrip(message);
+
+            message.StringField = "foo";
+            Assert.AreEqual(OneofWellKnownTypes.OneofFieldOneofCase.StringField, message.OneofFieldCase);
+            AssertOneofRoundTrip(message);
+
+            message.StringField = "foo";
+            Assert.AreEqual(OneofWellKnownTypes.OneofFieldOneofCase.StringField, message.OneofFieldCase);
+            AssertOneofRoundTrip(message);
+
+            message.DoubleField = 0.0f;
+            Assert.AreEqual(OneofWellKnownTypes.OneofFieldOneofCase.DoubleField, message.OneofFieldCase);
+            AssertOneofRoundTrip(message);
+
+            message.DoubleField = 1.0f;
+            Assert.AreEqual(OneofWellKnownTypes.OneofFieldOneofCase.DoubleField, message.OneofFieldCase);
+            AssertOneofRoundTrip(message);
+
+            message.ClearOneofField();
+            Assert.AreEqual(OneofWellKnownTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
+            AssertOneofRoundTrip(message);
+        }
+
+        private void AssertOneofRoundTrip(OneofWellKnownTypes message)
+        {
+            // Normal roundtrip, but explicitly checking the case...
+            var bytes = message.ToByteArray();
+            var parsed = OneofWellKnownTypes.Parser.ParseFrom(bytes);
+            Assert.AreEqual(message, parsed);
+            Assert.AreEqual(message.OneofFieldCase, parsed.OneofFieldCase);
+        }
+
+        [Test]
+        [TestCase("x", "y", "y")]
+        [TestCase("x", "", "x")]
+        [TestCase("x", null, "x")]
+        [TestCase("", "y", "y")]
+        [TestCase("", "", "")]
+        [TestCase("", null, "")]
+        [TestCase(null, "y", "y")]
+        [TestCase(null, "", "")]
+        [TestCase(null, null, null)]
+        public void Merging(string original, string merged, string expected)
+        {
+            var originalMessage = new TestWellKnownTypes { StringField = original };
+            var mergingMessage = new TestWellKnownTypes { StringField = merged };
+            originalMessage.MergeFrom(mergingMessage);
+            Assert.AreEqual(expected, originalMessage.StringField);
+
+            // Try it using MergeFrom(CodedInputStream) too...
+            originalMessage = new TestWellKnownTypes { StringField = original };
+            originalMessage.MergeFrom(mergingMessage.ToByteArray());
+            Assert.AreEqual(expected, originalMessage.StringField);
+        }
+
+        // Merging is odd with wrapper types, due to the way that default values aren't emitted in
+        // the binary stream. In fact we cheat a little bit - a message with an explicitly present default
+        // value will have that default value ignored.
+        [Test]
+        public void MergingCornerCase()
+        {
+            var message = new TestWellKnownTypes { Int32Field = 5 };
+
+            // Create a byte array which has the data of an Int32Value explicitly containing a value of 0.
+            // This wouldn't normally happen.
+            byte[] bytes;
+            var wrapperTag = WireFormat.MakeTag(TestWellKnownTypes.Int32FieldFieldNumber, WireFormat.WireType.LengthDelimited);
+            var valueTag = WireFormat.MakeTag(Int32Value.ValueFieldNumber, WireFormat.WireType.Varint);
+            using (var stream = new MemoryStream())
+            {
+                var coded = new CodedOutputStream(stream);
+                coded.WriteTag(wrapperTag);
+                coded.WriteLength(2); // valueTag + a value 0, each one byte
+                coded.WriteTag(valueTag);
+                coded.WriteInt32(0);
+                coded.Flush();
+                bytes = stream.ToArray();
+            }
+
+            message.MergeFrom(bytes);
+            // A normal implementation would have 0 now, as the explicit default would have been overwritten the 5.
+            Assert.AreEqual(5, message.Int32Field);
+        }
+
+        [Test]
+        public void UnknownFieldInWrapper()
+        {
+            var stream = new MemoryStream();
+            var output = new CodedOutputStream(stream);
+            var wrapperTag = WireFormat.MakeTag(TestWellKnownTypes.Int32FieldFieldNumber, WireFormat.WireType.LengthDelimited);
+            var unknownTag = WireFormat.MakeTag(15, WireFormat.WireType.Varint);
+            var valueTag = WireFormat.MakeTag(Int32Value.ValueFieldNumber, WireFormat.WireType.Varint);
+
+            output.WriteTag(wrapperTag);
+            output.WriteLength(4); // unknownTag + value 5 + valueType + value 6, each 1 byte
+            output.WriteTag(unknownTag);
+            output.WriteInt32((int) valueTag); // Sneakily "pretend" it's a tag when it's really a value
+            output.WriteTag(valueTag);
+            output.WriteInt32(6);
+
+            output.Flush();
+            stream.Position = 0;
+            
+            var message = TestWellKnownTypes.Parser.ParseFrom(stream);
+            Assert.AreEqual(6, message.Int32Field);
+        }
+    }
+}

+ 5 - 0
csharp/src/Google.Protobuf.Test/packages.config

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="NUnit" version="2.6.4" targetFramework="net45" userInstalled="true" />
+  <package id="NUnitTestAdapter" version="2.0.0" targetFramework="net45" userInstalled="true" />
+</packages>

+ 56 - 0
csharp/src/Google.Protobuf.sln

@@ -0,0 +1,56 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf", "Google.Protobuf\Google.Protobuf.csproj", "{6908BDCE-D925-43F3-94AC-A531E6DF2591}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf.Test", "Google.Protobuf.Test\Google.Protobuf.Test.csproj", "{DD01ED24-3750-4567-9A23-1DB676A15610}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddressBook", "AddressBook\AddressBook.csproj", "{A31F5FB2-4FF3-432A-B35B-5CD203606311}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf.JsonDump", "Google.Protobuf.JsonDump\Google.Protobuf.JsonDump.csproj", "{D7282E99-2DC3-405B-946F-177DB2FD2AE2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf.Conformance", "Google.Protobuf.Conformance\Google.Protobuf.Conformance.csproj", "{0607D1B8-80D6-4B35-9857-1263C1B32B94}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+		ReleaseSigned|Any CPU = ReleaseSigned|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{6908BDCE-D925-43F3-94AC-A531E6DF2591}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{6908BDCE-D925-43F3-94AC-A531E6DF2591}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{6908BDCE-D925-43F3-94AC-A531E6DF2591}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{6908BDCE-D925-43F3-94AC-A531E6DF2591}.Release|Any CPU.Build.0 = Release|Any CPU
+		{6908BDCE-D925-43F3-94AC-A531E6DF2591}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
+		{6908BDCE-D925-43F3-94AC-A531E6DF2591}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
+		{DD01ED24-3750-4567-9A23-1DB676A15610}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{DD01ED24-3750-4567-9A23-1DB676A15610}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{DD01ED24-3750-4567-9A23-1DB676A15610}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{DD01ED24-3750-4567-9A23-1DB676A15610}.Release|Any CPU.Build.0 = Release|Any CPU
+		{DD01ED24-3750-4567-9A23-1DB676A15610}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
+		{DD01ED24-3750-4567-9A23-1DB676A15610}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
+		{A31F5FB2-4FF3-432A-B35B-5CD203606311}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A31F5FB2-4FF3-432A-B35B-5CD203606311}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{A31F5FB2-4FF3-432A-B35B-5CD203606311}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{A31F5FB2-4FF3-432A-B35B-5CD203606311}.Release|Any CPU.Build.0 = Release|Any CPU
+		{A31F5FB2-4FF3-432A-B35B-5CD203606311}.ReleaseSigned|Any CPU.ActiveCfg = Release|Any CPU
+		{A31F5FB2-4FF3-432A-B35B-5CD203606311}.ReleaseSigned|Any CPU.Build.0 = Release|Any CPU
+		{D7282E99-2DC3-405B-946F-177DB2FD2AE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{D7282E99-2DC3-405B-946F-177DB2FD2AE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{D7282E99-2DC3-405B-946F-177DB2FD2AE2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{D7282E99-2DC3-405B-946F-177DB2FD2AE2}.Release|Any CPU.Build.0 = Release|Any CPU
+		{D7282E99-2DC3-405B-946F-177DB2FD2AE2}.ReleaseSigned|Any CPU.ActiveCfg = Release|Any CPU
+		{D7282E99-2DC3-405B-946F-177DB2FD2AE2}.ReleaseSigned|Any CPU.Build.0 = Release|Any CPU
+		{0607D1B8-80D6-4B35-9857-1263C1B32B94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{0607D1B8-80D6-4B35-9857-1263C1B32B94}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0607D1B8-80D6-4B35-9857-1263C1B32B94}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{0607D1B8-80D6-4B35-9857-1263C1B32B94}.Release|Any CPU.Build.0 = Release|Any CPU
+		{0607D1B8-80D6-4B35-9857-1263C1B32B94}.ReleaseSigned|Any CPU.ActiveCfg = Release|Any CPU
+		{0607D1B8-80D6-4B35-9857-1263C1B32B94}.ReleaseSigned|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 79 - 0
csharp/src/Google.Protobuf/ByteArray.cs

@@ -0,0 +1,79 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Provides a utility routine to copy small arrays much more quickly than Buffer.BlockCopy
+    /// </summary>
+    internal static class ByteArray
+    {
+        /// <summary>
+        /// The threshold above which you should use Buffer.BlockCopy rather than ByteArray.Copy
+        /// </summary>
+        private const int CopyThreshold = 12;
+
+        /// <summary>
+        /// Determines which copy routine to use based on the number of bytes to be copied.
+        /// </summary>
+        internal static void Copy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int count)
+        {
+            if (count > CopyThreshold)
+            {
+                Buffer.BlockCopy(src, srcOffset, dst, dstOffset, count);
+            }
+            else
+            {
+                int stop = srcOffset + count;
+                for (int i = srcOffset; i < stop; i++)
+                {
+                    dst[dstOffset++] = src[i];
+                }
+            }
+        }
+
+        /// <summary>
+        /// Reverses the order of bytes in the array
+        /// </summary>
+        internal static void Reverse(byte[] bytes)
+        {
+            for (int first = 0, last = bytes.Length - 1; first < last; first++, last--)
+            {
+                byte temp = bytes[first];
+                bytes[first] = bytes[last];
+                bytes[last] = temp;
+            }
+        }
+    }
+}

+ 345 - 0
csharp/src/Google.Protobuf/ByteString.cs

@@ -0,0 +1,345 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Immutable array of bytes.
+    /// </summary>
+    public sealed class ByteString : IEnumerable<byte>, IEquatable<ByteString>
+    {
+        private static readonly ByteString empty = new ByteString(new byte[0]);
+
+        private readonly byte[] bytes;
+
+        /// <summary>
+        /// Unsafe operations that can cause IO Failure and/or other catestrophic side-effects.
+        /// </summary>
+        public static class Unsafe
+        {
+            /// <summary>
+            /// Constructs a new ByteString from the given byte array. The array is
+            /// *not* copied, and must not be modified after this constructor is called.
+            /// </summary>
+            public static ByteString FromBytes(byte[] bytes)
+            {
+                return new ByteString(bytes);
+            }
+
+            /// <summary>
+            /// Provides direct, unrestricted access to the bytes contained in this instance.
+            /// You must not modify or resize the byte array returned by this method.
+            /// </summary>
+            public static byte[] GetBuffer(ByteString bytes)
+            {
+                return bytes.bytes;
+            }
+        }
+
+        /// <summary>
+        /// Internal use only.  Ensure that the provided array is not mutated and belongs to this instance.
+        /// </summary>
+        internal static ByteString AttachBytes(byte[] bytes)
+        {
+            return new ByteString(bytes);
+        }
+
+        /// <summary>
+        /// Constructs a new ByteString from the given byte array. The array is
+        /// *not* copied, and must not be modified after this constructor is called.
+        /// </summary>
+        private ByteString(byte[] bytes)
+        {
+            this.bytes = bytes;
+        }
+
+        /// <summary>
+        /// Returns an empty ByteString.
+        /// </summary>
+        public static ByteString Empty
+        {
+            get { return empty; }
+        }
+
+        /// <summary>
+        /// Returns the length of this ByteString in bytes.
+        /// </summary>
+        public int Length
+        {
+            get { return bytes.Length; }
+        }
+
+        /// <summary>
+        /// Returns <c>true</c> if this byte string is empty, <c>false</c> otherwise.
+        /// </summary>
+        public bool IsEmpty
+        {
+            get { return Length == 0; }
+        }
+
+        /// <summary>
+        /// Converts this <see cref="ByteString"/> into a byte array.
+        /// </summary>
+        /// <remarks>The data is copied - changes to the returned array will not be reflected in this <c>ByteString</c>.</remarks>
+        /// <returns>A byte array with the same data as this <c>ByteString</c>.</returns>
+        public byte[] ToByteArray()
+        {
+            return (byte[]) bytes.Clone();
+        }
+
+        /// <summary>
+        /// Converts this <see cref="ByteString"/> into a standard base64 representation.
+        /// </summary>
+        /// <returns>A base64 representation of this <c>ByteString</c>.</returns>
+        public string ToBase64()
+        {
+            return Convert.ToBase64String(bytes);
+        }
+
+        /// <summary>
+        /// Constructs a <see cref="ByteString" /> from the Base64 Encoded String.
+        /// </summary>
+        public static ByteString FromBase64(string bytes)
+        {
+            // By handling the empty string explicitly, we not only optimize but we fix a
+            // problem on CF 2.0. See issue 61 for details.
+            return bytes == "" ? Empty : new ByteString(Convert.FromBase64String(bytes));
+        }
+
+        /// <summary>
+        /// Constructs a <see cref="ByteString" /> from the given array. The contents
+        /// are copied, so further modifications to the array will not
+        /// be reflected in the returned ByteString.
+        /// This method can also be invoked in <c>ByteString.CopyFrom(0xaa, 0xbb, ...)</c> form
+        /// which is primarily useful for testing.
+        /// </summary>
+        public static ByteString CopyFrom(params byte[] bytes)
+        {
+            return new ByteString((byte[]) bytes.Clone());
+        }
+
+        /// <summary>
+        /// Constructs a <see cref="ByteString" /> from a portion of a byte array.
+        /// </summary>
+        public static ByteString CopyFrom(byte[] bytes, int offset, int count)
+        {
+            byte[] portion = new byte[count];
+            ByteArray.Copy(bytes, offset, portion, 0, count);
+            return new ByteString(portion);
+        }
+
+        /// <summary>
+        /// Creates a new <see cref="ByteString" /> by encoding the specified text with
+        /// the given encoding.
+        /// </summary>
+        public static ByteString CopyFrom(string text, Encoding encoding)
+        {
+            return new ByteString(encoding.GetBytes(text));
+        }
+
+        /// <summary>
+        /// Creates a new <see cref="ByteString" /> by encoding the specified text in UTF-8.
+        /// </summary>
+        public static ByteString CopyFromUtf8(string text)
+        {
+            return CopyFrom(text, Encoding.UTF8);
+        }
+
+        /// <summary>
+        /// Retuns the byte at the given index.
+        /// </summary>
+        public byte this[int index]
+        {
+            get { return bytes[index]; }
+        }
+
+        /// <summary>
+        /// Converts this <see cref="ByteString"/> into a string by applying the given encoding.
+        /// </summary>
+        /// <remarks>
+        /// This method should only be used to convert binary data which was the result of encoding
+        /// text with the given encoding.
+        /// </remarks>
+        /// <param name="encoding">The encoding to use to decode the binary data into text.</param>
+        /// <returns>The result of decoding the binary data with the given decoding.</returns>
+        public string ToString(Encoding encoding)
+        {
+            return encoding.GetString(bytes, 0, bytes.Length);
+        }
+
+        /// <summary>
+        /// Converts this <see cref="ByteString"/> into a string by applying the UTF-8 encoding.
+        /// </summary>
+        /// <remarks>
+        /// This method should only be used to convert binary data which was the result of encoding
+        /// text with UTF-8.
+        /// </remarks>
+        /// <returns>The result of decoding the binary data with the given decoding.</returns>
+        public string ToStringUtf8()
+        {
+            return ToString(Encoding.UTF8);
+        }
+
+        /// <summary>
+        /// Returns an iterator over the bytes in this <see cref="ByteString"/>.
+        /// </summary>
+        /// <returns>An iterator over the bytes in this object.</returns>
+        public IEnumerator<byte> GetEnumerator()
+        {
+            return ((IEnumerable<byte>) bytes).GetEnumerator();
+        }
+
+        /// <summary>
+        /// Returns an iterator over the bytes in this <see cref="ByteString"/>.
+        /// </summary>
+        /// <returns>An iterator over the bytes in this object.</returns>
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+
+        /// <summary>
+        /// Creates a CodedInputStream from this ByteString's data.
+        /// </summary>
+        public CodedInputStream CreateCodedInput()
+        {
+            // We trust CodedInputStream not to reveal the provided byte array or modify it
+            return new CodedInputStream(bytes);
+        }
+
+        /// <summary>
+        /// Compares two byte strings for equality.
+        /// </summary>
+        /// <param name="lhs">The first byte string to compare.</param>
+        /// <param name="rhs">The second byte string to compare.</param>
+        /// <returns><c>true</c> if the byte strings are equal; false otherwise.</returns>
+        public static bool operator ==(ByteString lhs, ByteString rhs)
+        {
+            if (ReferenceEquals(lhs, rhs))
+            {
+                return true;
+            }
+            if (ReferenceEquals(lhs, null) || ReferenceEquals(rhs, null))
+            {
+                return false;
+            }
+            if (lhs.bytes.Length != rhs.bytes.Length)
+            {
+                return false;
+            }
+            for (int i = 0; i < lhs.Length; i++)
+            {
+                if (rhs.bytes[i] != lhs.bytes[i])
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// Compares two byte strings for inequality.
+        /// </summary>
+        /// <param name="lhs">The first byte string to compare.</param>
+        /// <param name="rhs">The second byte string to compare.</param>
+        /// <returns><c>false</c> if the byte strings are equal; true otherwise.</returns>
+        public static bool operator !=(ByteString lhs, ByteString rhs)
+        {
+            return !(lhs == rhs);
+        }
+
+        /// <summary>
+        /// Compares this byte string with another object.
+        /// </summary>
+        /// <param name="obj">The object to compare this with.</param>
+        /// <returns><c>true</c> if <paramref name="obj"/> refers to an equal <see cref="ByteString"/>; <c>false</c> otherwise.</returns>
+        public override bool Equals(object obj)
+        {
+            return this == (obj as ByteString);
+        }
+
+        /// <summary>
+        /// Returns a hash code for this object. Two equal byte strings
+        /// will return the same hash code.
+        /// </summary>
+        /// <returns>A hash code for this object.</returns>
+        public override int GetHashCode()
+        {
+            int ret = 23;
+            foreach (byte b in bytes)
+            {
+                ret = (ret << 8) | b;
+            }
+            return ret;
+        }
+
+        /// <summary>
+        /// Compares this byte string with another.
+        /// </summary>
+        /// <param name="other">The <see cref="ByteString"/> to compare this with.</param>
+        /// <returns><c>true</c> if <paramref name="other"/> refers to an equal byte string; <c>false</c> otherwise.</returns>
+        public bool Equals(ByteString other)
+        {
+            return this == other;
+        }
+
+        /// <summary>
+        /// Used internally by CodedOutputStream to avoid creating a copy for the write
+        /// </summary>
+        internal void WriteRawBytesTo(CodedOutputStream outputStream)
+        {
+            outputStream.WriteRawBytes(bytes, 0, bytes.Length);
+        }
+
+        /// <summary>
+        /// Copies the entire byte array to the destination array provided at the offset specified.
+        /// </summary>
+        public void CopyTo(byte[] array, int position)
+        {
+            ByteArray.Copy(bytes, 0, array, position, bytes.Length);
+        }
+
+        /// <summary>
+        /// Writes the entire byte array to the provided stream
+        /// </summary>
+        public void WriteTo(Stream outputStream)
+        {
+            outputStream.Write(bytes, 0, bytes.Length);
+        }
+    }
+}

+ 1221 - 0
csharp/src/Google.Protobuf/CodedInputStream.cs

@@ -0,0 +1,1221 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using Google.Protobuf.Collections;
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Readings and decodes protocol message fields.
+    /// </summary>
+    /// <remarks>
+    /// <para>
+    /// This class is generally used by generated code to read appropriate
+    /// primitives from the stream. It effectively encapsulates the lowest
+    /// levels of protocol buffer format.
+    /// </para>
+    /// <para>
+    /// Repeated fields and map fields are not handled by this class; use <see cref="RepeatedField{T}"/>
+    /// and <see cref="MapField{TKey, TValue}"/> to serialize such fields.
+    /// </para>
+    /// </remarks>
+    public sealed class CodedInputStream
+    {
+        /// <summary>
+        /// Buffer of data read from the stream or provided at construction time.
+        /// </summary>
+        private readonly byte[] buffer;
+
+        /// <summary>
+        /// The index of the buffer at which we need to refill from the stream (if there is one).
+        /// </summary>
+        private int bufferSize;
+
+        private int bufferSizeAfterLimit = 0;
+        /// <summary>
+        /// The position within the current buffer (i.e. the next byte to read)
+        /// </summary>
+        private int bufferPos = 0;
+
+        /// <summary>
+        /// The stream to read further input from, or null if the byte array buffer was provided
+        /// directly on construction, with no further data available.
+        /// </summary>
+        private readonly Stream input;
+
+        /// <summary>
+        /// The last tag we read. 0 indicates we've read to the end of the stream
+        /// (or haven't read anything yet).
+        /// </summary>
+        private uint lastTag = 0;
+
+        /// <summary>
+        /// The next tag, used to store the value read by PeekTag.
+        /// </summary>
+        private uint nextTag = 0;
+        private bool hasNextTag = false;
+
+        internal const int DefaultRecursionLimit = 64;
+        internal const int DefaultSizeLimit = 64 << 20; // 64MB
+        internal const int BufferSize = 4096;
+
+        /// <summary>
+        /// The total number of bytes read before the current buffer. The
+        /// total bytes read up to the current position can be computed as
+        /// totalBytesRetired + bufferPos.
+        /// </summary>
+        private int totalBytesRetired = 0;
+
+        /// <summary>
+        /// The absolute position of the end of the current message.
+        /// </summary> 
+        private int currentLimit = int.MaxValue;
+
+        private int recursionDepth = 0;
+
+        private readonly int recursionLimit;
+        private readonly int sizeLimit;
+
+        #region Construction
+        // Note that the checks are performed such that we don't end up checking obviously-valid things
+        // like non-null references for arrays we've just created.
+
+        /// <summary>
+        /// Creates a new CodedInputStream reading data from the given byte array.
+        /// </summary>
+        public CodedInputStream(byte[] buffer) : this(null, Preconditions.CheckNotNull(buffer, "buffer"), 0, buffer.Length)
+        {            
+        }
+
+        /// <summary>
+        /// Creates a new CodedInputStream that reads from the given byte array slice.
+        /// </summary>
+        public CodedInputStream(byte[] buffer, int offset, int length)
+            : this(null, Preconditions.CheckNotNull(buffer, "buffer"), offset, offset + length)
+        {            
+            if (offset < 0 || offset > buffer.Length)
+            {
+                throw new ArgumentOutOfRangeException("offset", "Offset must be within the buffer");
+            }
+            if (length < 0 || offset + length > buffer.Length)
+            {
+                throw new ArgumentOutOfRangeException("length", "Length must be non-negative and within the buffer");
+            }
+        }
+
+        /// <summary>
+        /// Creates a new CodedInputStream reading data from the given stream.
+        /// </summary>
+        public CodedInputStream(Stream input) : this(input, new byte[BufferSize], 0, 0)
+        {
+            Preconditions.CheckNotNull(input, "input");
+        }
+
+        /// <summary>
+        /// Creates a new CodedInputStream reading data from the given
+        /// stream and buffer, using the default limits.
+        /// </summary>
+        internal CodedInputStream(Stream input, byte[] buffer, int bufferPos, int bufferSize)
+        {
+            this.input = input;
+            this.buffer = buffer;
+            this.bufferPos = bufferPos;
+            this.bufferSize = bufferSize;
+            this.sizeLimit = DefaultSizeLimit;
+            this.recursionLimit = DefaultRecursionLimit;
+        }
+
+        /// <summary>
+        /// Creates a new CodedInputStream reading data from the given
+        /// stream and buffer, using the specified limits.
+        /// </summary>
+        /// <remarks>
+        /// This chains to the version with the default limits instead of vice versa to avoid
+        /// having to check that the default values are valid every time.
+        /// </remarks>
+        internal CodedInputStream(Stream input, byte[] buffer, int bufferPos, int bufferSize, int sizeLimit, int recursionLimit)
+            : this(input, buffer, bufferPos, bufferSize)
+        {
+            if (sizeLimit <= 0)
+            {
+                throw new ArgumentOutOfRangeException("sizeLimit", "Size limit must be positive");
+            }
+            if (recursionLimit <= 0)
+            {
+                throw new ArgumentOutOfRangeException("recursionLimit!", "Recursion limit must be positive");
+            }
+            this.sizeLimit = sizeLimit;
+            this.recursionLimit = recursionLimit;
+        }
+        #endregion
+
+        /// <summary>
+        /// Creates a <see cref="CodedInputStream"/> with the specified size and recursion limits, reading
+        /// from an input stream.
+        /// </summary>
+        /// <remarks>
+        /// This method exists separately from the constructor to reduce the number of constructor overloads.
+        /// It is likely to be used considerably less frequently than the constructors, as the default limits
+        /// are suitable for most use cases.
+        /// </remarks>
+        /// <param name="input">The input stream to read from</param>
+        /// <param name="sizeLimit">The total limit of data to read from the stream.</param>
+        /// <param name="recursionLimit">The maximum recursion depth to allow while reading.</param>
+        /// <returns>A <c>CodedInputStream</c> reading from <paramref name="input"/> with the specified size
+        /// and recursion limits.</returns>
+        public static CodedInputStream CreateWithLimits(Stream input, int sizeLimit, int recursionLimit)
+        {
+            return new CodedInputStream(input, new byte[BufferSize], 0, 0, sizeLimit, recursionLimit);
+        }
+
+        /// <summary>
+        /// Returns the current position in the input stream, or the position in the input buffer
+        /// </summary>
+        public long Position 
+        {
+            get
+            {
+                if (input != null)
+                {
+                    return input.Position - ((bufferSize + bufferSizeAfterLimit) - bufferPos);
+                }
+                return bufferPos;
+            }
+        }
+
+        /// <summary>
+        /// Returns the last tag read, or 0 if no tags have been read or we've read beyond
+        /// the end of the stream.
+        /// </summary>
+        internal uint LastTag { get { return lastTag; } }
+
+        /// <summary>
+        /// Returns the size limit for this stream.
+        /// </summary>
+        /// <remarks>
+        /// This limit is applied when reading from the underlying stream, as a sanity check. It is
+        /// not applied when reading from a byte array data source without an underlying stream.
+        /// The default value is 64MB.
+        /// </remarks>
+        /// <value>
+        /// The size limit.
+        /// </value>
+        public int SizeLimit { get { return sizeLimit; } }
+
+        /// <summary>
+        /// Returns the recursion limit for this stream. This limit is applied whilst reading messages,
+        /// to avoid maliciously-recursive data.
+        /// </summary>
+        /// <remarks>
+        /// The default limit is 64.
+        /// </remarks>
+        /// <value>
+        /// The recursion limit for this stream.
+        /// </value>
+        public int RecursionLimit { get { return recursionLimit; } }
+
+        #region Validation
+        /// <summary>
+        /// Verifies that the last call to ReadTag() returned tag 0 - in other words,
+        /// we've reached the end of the stream when we expected to.
+        /// </summary>
+        /// <exception cref="InvalidProtocolBufferException">The 
+        /// tag read was not the one specified</exception>
+        internal void CheckReadEndOfStreamTag()
+        {
+            if (lastTag != 0)
+            {
+                throw InvalidProtocolBufferException.MoreDataAvailable();
+            }
+        }
+        #endregion
+
+        #region Reading of tags etc
+
+        /// <summary>
+        /// Peeks at the next field tag. This is like calling <see cref="ReadTag"/>, but the
+        /// tag is not consumed. (So a subsequent call to <see cref="ReadTag"/> will return the
+        /// same value.)
+        /// </summary>
+        public uint PeekTag()
+        {
+            if (hasNextTag)
+            {
+                return nextTag;
+            }
+
+            uint savedLast = lastTag;
+            nextTag = ReadTag();
+            hasNextTag = true;
+            lastTag = savedLast; // Undo the side effect of ReadTag
+            return nextTag;
+        }
+
+        /// <summary>
+        /// Reads a field tag, returning the tag of 0 for "end of stream".
+        /// </summary>
+        /// <remarks>
+        /// If this method returns 0, it doesn't necessarily mean the end of all
+        /// the data in this CodedInputStream; it may be the end of the logical stream
+        /// for an embedded message, for example.
+        /// </remarks>
+        /// <returns>The next field tag, or 0 for end of stream. (0 is never a valid tag.)</returns>
+        public uint ReadTag()
+        {
+            if (hasNextTag)
+            {
+                lastTag = nextTag;
+                hasNextTag = false;
+                return lastTag;
+            }
+
+            // Optimize for the incredibly common case of having at least two bytes left in the buffer,
+            // and those two bytes being enough to get the tag. This will be true for fields up to 4095.
+            if (bufferPos + 2 <= bufferSize)
+            {
+                int tmp = buffer[bufferPos++];
+                if (tmp < 128)
+                {
+                    lastTag = (uint)tmp;
+                }
+                else
+                {
+                    int result = tmp & 0x7f;
+                    if ((tmp = buffer[bufferPos++]) < 128)
+                    {
+                        result |= tmp << 7;
+                        lastTag = (uint) result;
+                    }
+                    else
+                    {
+                        // Nope, rewind and go the potentially slow route.
+                        bufferPos -= 2;
+                        lastTag = ReadRawVarint32();
+                    }
+                }
+            }
+            else
+            {
+                if (IsAtEnd)
+                {
+                    lastTag = 0;
+                    return 0; // This is the only case in which we return 0.
+                }
+
+                lastTag = ReadRawVarint32();
+            }
+            if (lastTag == 0)
+            {
+                // If we actually read zero, that's not a valid tag.
+                throw InvalidProtocolBufferException.InvalidTag();
+            }
+            return lastTag;
+        }
+
+        /// <summary>
+        /// Skips the data for the field with the tag we've just read.
+        /// This should be called directly after <see cref="ReadTag"/>, when
+        /// the caller wishes to skip an unknown field.
+        /// </summary>
+        public void SkipLastField()
+        {
+            if (lastTag == 0)
+            {
+                throw new InvalidOperationException("SkipLastField cannot be called at the end of a stream");
+            }
+            switch (WireFormat.GetTagWireType(lastTag))
+            {
+                case WireFormat.WireType.StartGroup:
+                    SkipGroup();
+                    break;
+                case WireFormat.WireType.EndGroup:
+                    // Just ignore; there's no data following the tag.
+                    break;
+                case WireFormat.WireType.Fixed32:
+                    ReadFixed32();
+                    break;
+                case WireFormat.WireType.Fixed64:
+                    ReadFixed64();
+                    break;
+                case WireFormat.WireType.LengthDelimited:
+                    var length = ReadLength();
+                    SkipRawBytes(length);
+                    break;
+                case WireFormat.WireType.Varint:
+                    ReadRawVarint32();
+                    break;
+            }
+        }
+
+        private void SkipGroup()
+        {
+            // Note: Currently we expect this to be the way that groups are read. We could put the recursion
+            // depth changes into the ReadTag method instead, potentially...
+            recursionDepth++;
+            if (recursionDepth >= recursionLimit)
+            {
+                throw InvalidProtocolBufferException.RecursionLimitExceeded();
+            }
+            uint tag;
+            do
+            {
+                tag = ReadTag();
+                if (tag == 0)
+                {
+                    throw InvalidProtocolBufferException.TruncatedMessage();
+                }
+                // This recursion will allow us to handle nested groups.
+                SkipLastField();
+            } while (WireFormat.GetTagWireType(tag) != WireFormat.WireType.EndGroup);
+            recursionDepth--;
+        }
+
+        /// <summary>
+        /// Reads a double field from the stream.
+        /// </summary>
+        public double ReadDouble()
+        {
+            return BitConverter.Int64BitsToDouble((long) ReadRawLittleEndian64());
+        }
+
+        /// <summary>
+        /// Reads a float field from the stream.
+        /// </summary>
+        public float ReadFloat()
+        {
+            if (BitConverter.IsLittleEndian && 4 <= bufferSize - bufferPos)
+            {
+                float ret = BitConverter.ToSingle(buffer, bufferPos);
+                bufferPos += 4;
+                return ret;
+            }
+            else
+            {
+                byte[] rawBytes = ReadRawBytes(4);
+                if (!BitConverter.IsLittleEndian)
+                {
+                    ByteArray.Reverse(rawBytes);
+                }
+                return BitConverter.ToSingle(rawBytes, 0);
+            }
+        }
+
+        /// <summary>
+        /// Reads a uint64 field from the stream.
+        /// </summary>
+        public ulong ReadUInt64()
+        {
+            return ReadRawVarint64();
+        }
+
+        /// <summary>
+        /// Reads an int64 field from the stream.
+        /// </summary>
+        public long ReadInt64()
+        {
+            return (long) ReadRawVarint64();
+        }
+
+        /// <summary>
+        /// Reads an int32 field from the stream.
+        /// </summary>
+        public int ReadInt32()
+        {
+            return (int) ReadRawVarint32();
+        }
+
+        /// <summary>
+        /// Reads a fixed64 field from the stream.
+        /// </summary>
+        public ulong ReadFixed64()
+        {
+            return ReadRawLittleEndian64();
+        }
+
+        /// <summary>
+        /// Reads a fixed32 field from the stream.
+        /// </summary>
+        public uint ReadFixed32()
+        {
+            return ReadRawLittleEndian32();
+        }
+
+        /// <summary>
+        /// Reads a bool field from the stream.
+        /// </summary>
+        public bool ReadBool()
+        {
+            return ReadRawVarint32() != 0;
+        }
+
+        /// <summary>
+        /// Reads a string field from the stream.
+        /// </summary>
+        public string ReadString()
+        {
+            int length = ReadLength();
+            // No need to read any data for an empty string.
+            if (length == 0)
+            {
+                return "";
+            }
+            if (length <= bufferSize - bufferPos)
+            {
+                // Fast path:  We already have the bytes in a contiguous buffer, so
+                //   just copy directly from it.
+                String result = CodedOutputStream.Utf8Encoding.GetString(buffer, bufferPos, length);
+                bufferPos += length;
+                return result;
+            }
+            // Slow path: Build a byte array first then copy it.
+            return CodedOutputStream.Utf8Encoding.GetString(ReadRawBytes(length), 0, length);
+        }
+
+        /// <summary>
+        /// Reads an embedded message field value from the stream.
+        /// </summary>   
+        public void ReadMessage(IMessage builder)
+        {
+            int length = ReadLength();
+            if (recursionDepth >= recursionLimit)
+            {
+                throw InvalidProtocolBufferException.RecursionLimitExceeded();
+            }
+            int oldLimit = PushLimit(length);
+            ++recursionDepth;
+            builder.MergeFrom(this);
+            CheckReadEndOfStreamTag();
+            // Check that we've read exactly as much data as expected.
+            if (!ReachedLimit)
+            {
+                throw InvalidProtocolBufferException.TruncatedMessage();
+            }
+            --recursionDepth;
+            PopLimit(oldLimit);
+        }
+
+        /// <summary>
+        /// Reads a bytes field value from the stream.
+        /// </summary>   
+        public ByteString ReadBytes()
+        {
+            int length = ReadLength();
+            if (length <= bufferSize - bufferPos && length > 0)
+            {
+                // Fast path:  We already have the bytes in a contiguous buffer, so
+                //   just copy directly from it.
+                ByteString result = ByteString.CopyFrom(buffer, bufferPos, length);
+                bufferPos += length;
+                return result;
+            }
+            else
+            {
+                // Slow path:  Build a byte array and attach it to a new ByteString.
+                return ByteString.AttachBytes(ReadRawBytes(length));
+            }
+        }
+
+        /// <summary>
+        /// Reads a uint32 field value from the stream.
+        /// </summary>   
+        public uint ReadUInt32()
+        {
+            return ReadRawVarint32();
+        }
+
+        /// <summary>
+        /// Reads an enum field value from the stream. If the enum is valid for type T,
+        /// then the ref value is set and it returns true.  Otherwise the unknown output
+        /// value is set and this method returns false.
+        /// </summary>   
+        public int ReadEnum()
+        {
+            // Currently just a pass-through, but it's nice to separate it logically from WriteInt32.
+            return (int) ReadRawVarint32();
+        }
+
+        /// <summary>
+        /// Reads an sfixed32 field value from the stream.
+        /// </summary>   
+        public int ReadSFixed32()
+        {
+            return (int) ReadRawLittleEndian32();
+        }
+
+        /// <summary>
+        /// Reads an sfixed64 field value from the stream.
+        /// </summary>   
+        public long ReadSFixed64()
+        {
+            return (long) ReadRawLittleEndian64();
+        }
+
+        /// <summary>
+        /// Reads an sint32 field value from the stream.
+        /// </summary>   
+        public int ReadSInt32()
+        {
+            return DecodeZigZag32(ReadRawVarint32());
+        }
+
+        /// <summary>
+        /// Reads an sint64 field value from the stream.
+        /// </summary>   
+        public long ReadSInt64()
+        {
+            return DecodeZigZag64(ReadRawVarint64());
+        }
+
+        /// <summary>
+        /// Reads a length for length-delimited data.
+        /// </summary>
+        /// <remarks>
+        /// This is internally just reading a varint, but this method exists
+        /// to make the calling code clearer.
+        /// </remarks>
+        public int ReadLength()
+        {
+            return (int) ReadRawVarint32();
+        }
+
+        /// <summary>
+        /// 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>
+        public bool MaybeConsumeTag(uint tag)
+        {
+            if (PeekTag() == tag)
+            {
+                hasNextTag = false;
+                return true;
+            }
+            return false;
+        }
+
+        #endregion
+
+        #region Underlying reading primitives
+
+        /// <summary>
+        /// Same code as ReadRawVarint32, but read each byte individually, checking for
+        /// buffer overflow.
+        /// </summary>
+        private uint SlowReadRawVarint32()
+        {
+            int tmp = ReadRawByte();
+            if (tmp < 128)
+            {
+                return (uint) tmp;
+            }
+            int result = tmp & 0x7f;
+            if ((tmp = ReadRawByte()) < 128)
+            {
+                result |= tmp << 7;
+            }
+            else
+            {
+                result |= (tmp & 0x7f) << 7;
+                if ((tmp = ReadRawByte()) < 128)
+                {
+                    result |= tmp << 14;
+                }
+                else
+                {
+                    result |= (tmp & 0x7f) << 14;
+                    if ((tmp = ReadRawByte()) < 128)
+                    {
+                        result |= tmp << 21;
+                    }
+                    else
+                    {
+                        result |= (tmp & 0x7f) << 21;
+                        result |= (tmp = ReadRawByte()) << 28;
+                        if (tmp >= 128)
+                        {
+                            // Discard upper 32 bits.
+                            for (int i = 0; i < 5; i++)
+                            {
+                                if (ReadRawByte() < 128)
+                                {
+                                    return (uint) result;
+                                }
+                            }
+                            throw InvalidProtocolBufferException.MalformedVarint();
+                        }
+                    }
+                }
+            }
+            return (uint) result;
+        }
+
+        /// <summary>
+        /// Reads a raw Varint from the stream.  If larger than 32 bits, discard the upper bits.
+        /// This method is optimised for the case where we've got lots of data in the buffer.
+        /// That means we can check the size just once, then just read directly from the buffer
+        /// without constant rechecking of the buffer length.
+        /// </summary>
+        internal uint ReadRawVarint32()
+        {
+            if (bufferPos + 5 > bufferSize)
+            {
+                return SlowReadRawVarint32();
+            }
+
+            int tmp = buffer[bufferPos++];
+            if (tmp < 128)
+            {
+                return (uint) tmp;
+            }
+            int result = tmp & 0x7f;
+            if ((tmp = buffer[bufferPos++]) < 128)
+            {
+                result |= tmp << 7;
+            }
+            else
+            {
+                result |= (tmp & 0x7f) << 7;
+                if ((tmp = buffer[bufferPos++]) < 128)
+                {
+                    result |= tmp << 14;
+                }
+                else
+                {
+                    result |= (tmp & 0x7f) << 14;
+                    if ((tmp = buffer[bufferPos++]) < 128)
+                    {
+                        result |= tmp << 21;
+                    }
+                    else
+                    {
+                        result |= (tmp & 0x7f) << 21;
+                        result |= (tmp = buffer[bufferPos++]) << 28;
+                        if (tmp >= 128)
+                        {
+                            // Discard upper 32 bits.
+                            // Note that this has to use ReadRawByte() as we only ensure we've
+                            // got at least 5 bytes at the start of the method. This lets us
+                            // use the fast path in more cases, and we rarely hit this section of code.
+                            for (int i = 0; i < 5; i++)
+                            {
+                                if (ReadRawByte() < 128)
+                                {
+                                    return (uint) result;
+                                }
+                            }
+                            throw InvalidProtocolBufferException.MalformedVarint();
+                        }
+                    }
+                }
+            }
+            return (uint) result;
+        }
+
+        /// <summary>
+        /// Reads a varint from the input one byte at a time, so that it does not
+        /// read any bytes after the end of the varint. If you simply wrapped the
+        /// stream in a CodedInputStream and used ReadRawVarint32(Stream)
+        /// then you would probably end up reading past the end of the varint since
+        /// CodedInputStream buffers its input.
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        internal static uint ReadRawVarint32(Stream input)
+        {
+            int result = 0;
+            int offset = 0;
+            for (; offset < 32; offset += 7)
+            {
+                int b = input.ReadByte();
+                if (b == -1)
+                {
+                    throw InvalidProtocolBufferException.TruncatedMessage();
+                }
+                result |= (b & 0x7f) << offset;
+                if ((b & 0x80) == 0)
+                {
+                    return (uint) result;
+                }
+            }
+            // Keep reading up to 64 bits.
+            for (; offset < 64; offset += 7)
+            {
+                int b = input.ReadByte();
+                if (b == -1)
+                {
+                    throw InvalidProtocolBufferException.TruncatedMessage();
+                }
+                if ((b & 0x80) == 0)
+                {
+                    return (uint) result;
+                }
+            }
+            throw InvalidProtocolBufferException.MalformedVarint();
+        }
+
+        /// <summary>
+        /// Reads a raw varint from the stream.
+        /// </summary>
+        internal ulong ReadRawVarint64()
+        {
+            int shift = 0;
+            ulong result = 0;
+            while (shift < 64)
+            {
+                byte b = ReadRawByte();
+                result |= (ulong) (b & 0x7F) << shift;
+                if ((b & 0x80) == 0)
+                {
+                    return result;
+                }
+                shift += 7;
+            }
+            throw InvalidProtocolBufferException.MalformedVarint();
+        }
+
+        /// <summary>
+        /// Reads a 32-bit little-endian integer from the stream.
+        /// </summary>
+        internal uint ReadRawLittleEndian32()
+        {
+            uint b1 = ReadRawByte();
+            uint b2 = ReadRawByte();
+            uint b3 = ReadRawByte();
+            uint b4 = ReadRawByte();
+            return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24);
+        }
+
+        /// <summary>
+        /// Reads a 64-bit little-endian integer from the stream.
+        /// </summary>
+        internal ulong ReadRawLittleEndian64()
+        {
+            ulong b1 = ReadRawByte();
+            ulong b2 = ReadRawByte();
+            ulong b3 = ReadRawByte();
+            ulong b4 = ReadRawByte();
+            ulong b5 = ReadRawByte();
+            ulong b6 = ReadRawByte();
+            ulong b7 = ReadRawByte();
+            ulong b8 = ReadRawByte();
+            return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24)
+                   | (b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56);
+        }
+
+        /// <summary>
+        /// Decode a 32-bit value with ZigZag encoding.
+        /// </summary>
+        /// <remarks>
+        /// ZigZag encodes signed integers into values that can be efficiently
+        /// encoded with varint.  (Otherwise, negative values must be 
+        /// sign-extended to 64 bits to be varint encoded, thus always taking
+        /// 10 bytes on the wire.)
+        /// </remarks>
+        internal static int DecodeZigZag32(uint n)
+        {
+            return (int)(n >> 1) ^ -(int)(n & 1);
+        }
+
+        /// <summary>
+        /// Decode a 32-bit value with ZigZag encoding.
+        /// </summary>
+        /// <remarks>
+        /// ZigZag encodes signed integers into values that can be efficiently
+        /// encoded with varint.  (Otherwise, negative values must be 
+        /// sign-extended to 64 bits to be varint encoded, thus always taking
+        /// 10 bytes on the wire.)
+        /// </remarks>
+        internal static long DecodeZigZag64(ulong n)
+        {
+            return (long)(n >> 1) ^ -(long)(n & 1);
+        }
+        #endregion
+
+        #region Internal reading and buffer management
+
+        /// <summary>
+        /// Sets currentLimit to (current position) + byteLimit. This is called
+        /// when descending into a length-delimited embedded message. The previous
+        /// limit is returned.
+        /// </summary>
+        /// <returns>The old limit.</returns>
+        internal int PushLimit(int byteLimit)
+        {
+            if (byteLimit < 0)
+            {
+                throw InvalidProtocolBufferException.NegativeSize();
+            }
+            byteLimit += totalBytesRetired + bufferPos;
+            int oldLimit = currentLimit;
+            if (byteLimit > oldLimit)
+            {
+                throw InvalidProtocolBufferException.TruncatedMessage();
+            }
+            currentLimit = byteLimit;
+
+            RecomputeBufferSizeAfterLimit();
+
+            return oldLimit;
+        }
+
+        private void RecomputeBufferSizeAfterLimit()
+        {
+            bufferSize += bufferSizeAfterLimit;
+            int bufferEnd = totalBytesRetired + bufferSize;
+            if (bufferEnd > currentLimit)
+            {
+                // Limit is in current buffer.
+                bufferSizeAfterLimit = bufferEnd - currentLimit;
+                bufferSize -= bufferSizeAfterLimit;
+            }
+            else
+            {
+                bufferSizeAfterLimit = 0;
+            }
+        }
+
+        /// <summary>
+        /// Discards the current limit, returning the previous limit.
+        /// </summary>
+        internal void PopLimit(int oldLimit)
+        {
+            currentLimit = oldLimit;
+            RecomputeBufferSizeAfterLimit();
+        }
+
+        /// <summary>
+        /// Returns whether or not all the data before the limit has been read.
+        /// </summary>
+        /// <returns></returns>
+        internal bool ReachedLimit
+        {
+            get
+            {
+                if (currentLimit == int.MaxValue)
+                {
+                    return false;
+                }
+                int currentAbsolutePosition = totalBytesRetired + bufferPos;
+                return currentAbsolutePosition >= currentLimit;
+            }
+        }
+
+        /// <summary>
+        /// Returns true if the stream has reached the end of the input. This is the
+        /// case if either the end of the underlying input source has been reached or
+        /// the stream has reached a limit created using PushLimit.
+        /// </summary>
+        public bool IsAtEnd
+        {
+            get { return bufferPos == bufferSize && !RefillBuffer(false); }
+        }
+
+        /// <summary>
+        /// Called when buffer is empty to read more bytes from the
+        /// input.  If <paramref name="mustSucceed"/> is true, RefillBuffer() gurantees that
+        /// either there will be at least one byte in the buffer when it returns
+        /// or it will throw an exception.  If <paramref name="mustSucceed"/> is false,
+        /// RefillBuffer() returns false if no more bytes were available.
+        /// </summary>
+        /// <param name="mustSucceed"></param>
+        /// <returns></returns>
+        private bool RefillBuffer(bool mustSucceed)
+        {
+            if (bufferPos < bufferSize)
+            {
+                throw new InvalidOperationException("RefillBuffer() called when buffer wasn't empty.");
+            }
+
+            if (totalBytesRetired + bufferSize == currentLimit)
+            {
+                // Oops, we hit a limit.
+                if (mustSucceed)
+                {
+                    throw InvalidProtocolBufferException.TruncatedMessage();
+                }
+                else
+                {
+                    return false;
+                }
+            }
+
+            totalBytesRetired += bufferSize;
+
+            bufferPos = 0;
+            bufferSize = (input == null) ? 0 : input.Read(buffer, 0, buffer.Length);
+            if (bufferSize < 0)
+            {
+                throw new InvalidOperationException("Stream.Read returned a negative count");
+            }
+            if (bufferSize == 0)
+            {
+                if (mustSucceed)
+                {
+                    throw InvalidProtocolBufferException.TruncatedMessage();
+                }
+                else
+                {
+                    return false;
+                }
+            }
+            else
+            {
+                RecomputeBufferSizeAfterLimit();
+                int totalBytesRead =
+                    totalBytesRetired + bufferSize + bufferSizeAfterLimit;
+                if (totalBytesRead > sizeLimit || totalBytesRead < 0)
+                {
+                    throw InvalidProtocolBufferException.SizeLimitExceeded();
+                }
+                return true;
+            }
+        }
+
+        /// <summary>
+        /// Read one byte from the input.
+        /// </summary>
+        /// <exception cref="InvalidProtocolBufferException">
+        /// the end of the stream or the current limit was reached
+        /// </exception>
+        internal byte ReadRawByte()
+        {
+            if (bufferPos == bufferSize)
+            {
+                RefillBuffer(true);
+            }
+            return buffer[bufferPos++];
+        }
+
+        /// <summary>
+        /// Reads a fixed size of bytes from the input.
+        /// </summary>
+        /// <exception cref="InvalidProtocolBufferException">
+        /// the end of the stream or the current limit was reached
+        /// </exception>
+        internal byte[] ReadRawBytes(int size)
+        {
+            if (size < 0)
+            {
+                throw InvalidProtocolBufferException.NegativeSize();
+            }
+
+            if (totalBytesRetired + bufferPos + size > currentLimit)
+            {
+                // Read to the end of the stream (up to the current limit) anyway.
+                SkipRawBytes(currentLimit - totalBytesRetired - bufferPos);
+                // Then fail.
+                throw InvalidProtocolBufferException.TruncatedMessage();
+            }
+
+            if (size <= bufferSize - bufferPos)
+            {
+                // We have all the bytes we need already.
+                byte[] bytes = new byte[size];
+                ByteArray.Copy(buffer, bufferPos, bytes, 0, size);
+                bufferPos += size;
+                return bytes;
+            }
+            else if (size < buffer.Length)
+            {
+                // Reading more bytes than are in the buffer, but not an excessive number
+                // of bytes.  We can safely allocate the resulting array ahead of time.
+
+                // First copy what we have.
+                byte[] bytes = new byte[size];
+                int pos = bufferSize - bufferPos;
+                ByteArray.Copy(buffer, bufferPos, bytes, 0, pos);
+                bufferPos = bufferSize;
+
+                // We want to use RefillBuffer() and then copy from the buffer into our
+                // byte array rather than reading directly into our byte array because
+                // the input may be unbuffered.
+                RefillBuffer(true);
+
+                while (size - pos > bufferSize)
+                {
+                    Buffer.BlockCopy(buffer, 0, bytes, pos, bufferSize);
+                    pos += bufferSize;
+                    bufferPos = bufferSize;
+                    RefillBuffer(true);
+                }
+
+                ByteArray.Copy(buffer, 0, bytes, pos, size - pos);
+                bufferPos = size - pos;
+
+                return bytes;
+            }
+            else
+            {
+                // The size is very large.  For security reasons, we can't allocate the
+                // entire byte array yet.  The size comes directly from the input, so a
+                // maliciously-crafted message could provide a bogus very large size in
+                // order to trick the app into allocating a lot of memory.  We avoid this
+                // by allocating and reading only a small chunk at a time, so that the
+                // malicious message must actually *be* extremely large to cause
+                // problems.  Meanwhile, we limit the allowed size of a message elsewhere.
+
+                // Remember the buffer markers since we'll have to copy the bytes out of
+                // it later.
+                int originalBufferPos = bufferPos;
+                int originalBufferSize = bufferSize;
+
+                // Mark the current buffer consumed.
+                totalBytesRetired += bufferSize;
+                bufferPos = 0;
+                bufferSize = 0;
+
+                // Read all the rest of the bytes we need.
+                int sizeLeft = size - (originalBufferSize - originalBufferPos);
+                List<byte[]> chunks = new List<byte[]>();
+
+                while (sizeLeft > 0)
+                {
+                    byte[] chunk = new byte[Math.Min(sizeLeft, buffer.Length)];
+                    int pos = 0;
+                    while (pos < chunk.Length)
+                    {
+                        int n = (input == null) ? -1 : input.Read(chunk, pos, chunk.Length - pos);
+                        if (n <= 0)
+                        {
+                            throw InvalidProtocolBufferException.TruncatedMessage();
+                        }
+                        totalBytesRetired += n;
+                        pos += n;
+                    }
+                    sizeLeft -= chunk.Length;
+                    chunks.Add(chunk);
+                }
+
+                // OK, got everything.  Now concatenate it all into one buffer.
+                byte[] bytes = new byte[size];
+
+                // Start by copying the leftover bytes from this.buffer.
+                int newPos = originalBufferSize - originalBufferPos;
+                ByteArray.Copy(buffer, originalBufferPos, bytes, 0, newPos);
+
+                // And now all the chunks.
+                foreach (byte[] chunk in chunks)
+                {
+                    Buffer.BlockCopy(chunk, 0, bytes, newPos, chunk.Length);
+                    newPos += chunk.Length;
+                }
+
+                // Done.
+                return bytes;
+            }
+        }
+
+        /// <summary>
+        /// Reads and discards <paramref name="size"/> bytes.
+        /// </summary>
+        /// <exception cref="InvalidProtocolBufferException">the end of the stream
+        /// or the current limit was reached</exception>
+        private void SkipRawBytes(int size)
+        {
+            if (size < 0)
+            {
+                throw InvalidProtocolBufferException.NegativeSize();
+            }
+
+            if (totalBytesRetired + bufferPos + size > currentLimit)
+            {
+                // Read to the end of the stream anyway.
+                SkipRawBytes(currentLimit - totalBytesRetired - bufferPos);
+                // Then fail.
+                throw InvalidProtocolBufferException.TruncatedMessage();
+            }
+
+            if (size <= bufferSize - bufferPos)
+            {
+                // We have all the bytes we need already.
+                bufferPos += size;
+            }
+            else
+            {
+                // Skipping more bytes than are in the buffer.  First skip what we have.
+                int pos = bufferSize - bufferPos;
+
+                // ROK 5/7/2013 Issue #54: should retire all bytes in buffer (bufferSize)
+                // totalBytesRetired += pos;
+                totalBytesRetired += bufferSize;
+                
+                bufferPos = 0;
+                bufferSize = 0;
+
+                // Then skip directly from the InputStream for the rest.
+                if (pos < size)
+                {
+                    if (input == null)
+                    {
+                        throw InvalidProtocolBufferException.TruncatedMessage();
+                    }
+                    SkipImpl(size - pos);
+                    totalBytesRetired += size - pos;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Abstraction of skipping to cope with streams which can't really skip.
+        /// </summary>
+        private void SkipImpl(int amountToSkip)
+        {
+            if (input.CanSeek)
+            {
+                long previousPosition = input.Position;
+                input.Position += amountToSkip;
+                if (input.Position != previousPosition + amountToSkip)
+                {
+                    throw InvalidProtocolBufferException.TruncatedMessage();
+                }
+            }
+            else
+            {
+                byte[] skipBuffer = new byte[Math.Min(1024, amountToSkip)];
+                while (amountToSkip > 0)
+                {
+                    int bytesRead = input.Read(skipBuffer, 0, Math.Min(skipBuffer.Length, amountToSkip));
+                    if (bytesRead <= 0)
+                    {
+                        throw InvalidProtocolBufferException.TruncatedMessage();
+                    }
+                    amountToSkip -= bytesRead;
+                }
+            }
+        }
+
+        #endregion
+    }
+}

+ 304 - 0
csharp/src/Google.Protobuf/CodedOutputStream.ComputeSize.cs

@@ -0,0 +1,304 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using System;
+
+namespace Google.Protobuf
+{
+    // This part of CodedOutputStream provides all the static entry points that are used
+    // by generated code and internally to compute the size of messages prior to being
+    // written to an instance of CodedOutputStream.
+    public sealed partial class CodedOutputStream
+    {
+        private const int LittleEndian64Size = 8;
+        private const int LittleEndian32Size = 4;        
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// double field, including the tag.
+        /// </summary>
+        public static int ComputeDoubleSize(double value)
+        {
+            return LittleEndian64Size;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// float field, including the tag.
+        /// </summary>
+        public static int ComputeFloatSize(float value)
+        {
+            return LittleEndian32Size;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// uint64 field, including the tag.
+        /// </summary>
+        public static int ComputeUInt64Size(ulong value)
+        {
+            return ComputeRawVarint64Size(value);
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode an
+        /// int64 field, including the tag.
+        /// </summary>
+        public static int ComputeInt64Size(long value)
+        {
+            return ComputeRawVarint64Size((ulong) value);
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode an
+        /// int32 field, including the tag.
+        /// </summary>
+        public static int ComputeInt32Size(int value)
+        {
+            if (value >= 0)
+            {
+                return ComputeRawVarint32Size((uint) value);
+            }
+            else
+            {
+                // Must sign-extend.
+                return 10;
+            }
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// fixed64 field, including the tag.
+        /// </summary>
+        public static int ComputeFixed64Size(ulong value)
+        {
+            return LittleEndian64Size;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// fixed32 field, including the tag.
+        /// </summary>
+        public static int ComputeFixed32Size(uint value)
+        {
+            return LittleEndian32Size;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// bool field, including the tag.
+        /// </summary>
+        public static int ComputeBoolSize(bool value)
+        {
+            return 1;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// string field, including the tag.
+        /// </summary>
+        public static int ComputeStringSize(String value)
+        {
+            int byteArraySize = Utf8Encoding.GetByteCount(value);
+            return ComputeLengthSize(byteArraySize) + byteArraySize;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// group field, including the tag.
+        /// </summary>
+        public static int ComputeGroupSize(IMessage value)
+        {
+            return value.CalculateSize();
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode an
+        /// embedded message field, including the tag.
+        /// </summary>
+        public static int ComputeMessageSize(IMessage value)
+        {
+            int size = value.CalculateSize();
+            return ComputeLengthSize(size) + size;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// bytes field, including the tag.
+        /// </summary>
+        public static int ComputeBytesSize(ByteString value)
+        {
+            return ComputeLengthSize(value.Length) + value.Length;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// uint32 field, including the tag.
+        /// </summary>
+        public static int ComputeUInt32Size(uint value)
+        {
+            return ComputeRawVarint32Size(value);
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a
+        /// enum field, including the tag. The caller is responsible for
+        /// converting the enum value to its numeric value.
+        /// </summary>
+        public static int ComputeEnumSize(int value)
+        {
+            // Currently just a pass-through, but it's nice to separate it logically.
+            return ComputeInt32Size(value);
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode an
+        /// sfixed32 field, including the tag.
+        /// </summary>
+        public static int ComputeSFixed32Size(int value)
+        {
+            return LittleEndian32Size;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode an
+        /// sfixed64 field, including the tag.
+        /// </summary>
+        public static int ComputeSFixed64Size(long value)
+        {
+            return LittleEndian64Size;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode an
+        /// sint32 field, including the tag.
+        /// </summary>
+        public static int ComputeSInt32Size(int value)
+        {
+            return ComputeRawVarint32Size(EncodeZigZag32(value));
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode an
+        /// sint64 field, including the tag.
+        /// </summary>
+        public static int ComputeSInt64Size(long value)
+        {
+            return ComputeRawVarint64Size(EncodeZigZag64(value));
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a length,
+        /// as written by <see cref="WriteLength"/>.
+        /// </summary>
+        public static int ComputeLengthSize(int length)
+        {
+            return ComputeRawVarint32Size((uint) length);
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a varint.
+        /// </summary>
+        public static int ComputeRawVarint32Size(uint value)
+        {
+            if ((value & (0xffffffff << 7)) == 0)
+            {
+                return 1;
+            }
+            if ((value & (0xffffffff << 14)) == 0)
+            {
+                return 2;
+            }
+            if ((value & (0xffffffff << 21)) == 0)
+            {
+                return 3;
+            }
+            if ((value & (0xffffffff << 28)) == 0)
+            {
+                return 4;
+            }
+            return 5;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a varint.
+        /// </summary>
+        public static int ComputeRawVarint64Size(ulong value)
+        {
+            if ((value & (0xffffffffffffffffL << 7)) == 0)
+            {
+                return 1;
+            }
+            if ((value & (0xffffffffffffffffL << 14)) == 0)
+            {
+                return 2;
+            }
+            if ((value & (0xffffffffffffffffL << 21)) == 0)
+            {
+                return 3;
+            }
+            if ((value & (0xffffffffffffffffL << 28)) == 0)
+            {
+                return 4;
+            }
+            if ((value & (0xffffffffffffffffL << 35)) == 0)
+            {
+                return 5;
+            }
+            if ((value & (0xffffffffffffffffL << 42)) == 0)
+            {
+                return 6;
+            }
+            if ((value & (0xffffffffffffffffL << 49)) == 0)
+            {
+                return 7;
+            }
+            if ((value & (0xffffffffffffffffL << 56)) == 0)
+            {
+                return 8;
+            }
+            if ((value & (0xffffffffffffffffL << 63)) == 0)
+            {
+                return 9;
+            }
+            return 10;
+        }
+
+        /// <summary>
+        /// Computes the number of bytes that would be needed to encode a tag.
+        /// </summary>
+        public static int ComputeTagSize(int fieldNumber)
+        {
+            return ComputeRawVarint32Size(WireFormat.MakeTag(fieldNumber, 0));
+        }
+    }
+}

+ 708 - 0
csharp/src/Google.Protobuf/CodedOutputStream.cs

@@ -0,0 +1,708 @@
+#region Copyright notice and license
+// 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.
+#endregion
+
+using Google.Protobuf.Collections;
+using System;
+using System.IO;
+using System.Text;
+
+namespace Google.Protobuf
+{
+    /// <summary>
+    /// Encodes and writes protocol message fields.
+    /// </summary>
+    /// <remarks>
+    /// <para>
+    /// This class is generally used by generated code to write appropriate
+    /// primitives to the stream. It effectively encapsulates the lowest
+    /// levels of protocol buffer format. Unlike some other implementations,
+    /// this does not include combined "write tag and value" methods. Generated
+    /// code knows the exact byte representations of the tags they're going to write,
+    /// so there's no need to re-encode them each time. Manually-written code calling
+    /// this class should just call one of the <c>WriteTag</c> overloads before each value.
+    /// </para>
+    /// <para>
+    /// Repeated fields and map fields are not handled by this class; use <c>RepeatedField&lt;T&gt;</c>
+    /// and <c>MapField&lt;TKey, TValue&gt;</c> to serialize such fields.
+    /// </para>
+    /// </remarks>
+    public sealed partial class CodedOutputStream
+    {
+        // "Local" copy of Encoding.UTF8, for efficiency. (Yes, it makes a difference.)
+        internal static readonly Encoding Utf8Encoding = Encoding.UTF8;
+
+        /// <summary>
+        /// The buffer size used by CreateInstance(Stream).
+        /// </summary>
+        public static readonly int DefaultBufferSize = 4096;
+
+        private readonly byte[] buffer;
+        private readonly int limit;
+        private int position;
+        private readonly Stream output;
+
+        #region Construction
+        /// <summary>
+        /// Creates a new CodedOutputStream that writes directly to the given
+        /// byte array. If more bytes are written than fit in the array,
+        /// OutOfSpaceException will be thrown.
+        /// </summary>
+        public CodedOutputStream(byte[] flatArray) : this(flatArray, 0, flatArray.Length)
+        {
+        }
+
+        /// <summary>
+        /// Creates a new CodedOutputStream that writes directly to the given
+        /// byte array slice. If more bytes are written than fit in the array,
+        /// OutOfSpaceException will be thrown.
+        /// </summary>
+        private CodedOutputStream(byte[] buffer, int offset, int length)
+        {
+            this.output = null;
+            this.buffer = buffer;
+            this.position = offset;
+            this.limit = offset + length;
+        }
+
+        private CodedOutputStream(Stream output, byte[] buffer)
+        {
+            this.output = output;
+            this.buffer = buffer;
+            this.position = 0;
+            this.limit = buffer.Length;
+        }
+
+        /// <summary>
+        /// Creates a new CodedOutputStream which write to the given stream.
+        /// </summary>
+        public CodedOutputStream(Stream output) : this(output, DefaultBufferSize)
+        {
+        }
+
+        /// <summary>
+        /// Creates a new CodedOutputStream which write to the given stream and uses
+        /// the specified buffer size.
+        /// </summary>
+        public CodedOutputStream(Stream output, int bufferSize) : this(output, new byte[bufferSize])
+        {
+        }    
+        #endregion
+
+        /// <summary>
+        /// Returns the current position in the stream, or the position in the output buffer
+        /// </summary>
+        public long Position
+        {
+            get
+            {
+                if (output != null)
+                {
+                    return output.Position + position;
+                }
+                return position;
+            }
+        }
+
+        #region Writing of values (not including tags)
+
+        /// <summary>
+        /// Writes a double field value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteDouble(double value)
+        {
+            WriteRawLittleEndian64((ulong)BitConverter.DoubleToInt64Bits(value));
+        }
+
+        /// <summary>
+        /// Writes a float field value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteFloat(float value)
+        {
+            byte[] rawBytes = BitConverter.GetBytes(value);
+            if (!BitConverter.IsLittleEndian)
+            {
+                ByteArray.Reverse(rawBytes);
+            }
+
+            if (limit - position >= 4)
+            {
+                buffer[position++] = rawBytes[0];
+                buffer[position++] = rawBytes[1];
+                buffer[position++] = rawBytes[2];
+                buffer[position++] = rawBytes[3];
+            }
+            else
+            {
+                WriteRawBytes(rawBytes, 0, 4);
+            }
+        }
+
+        /// <summary>
+        /// Writes a uint64 field value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteUInt64(ulong value)
+        {
+            WriteRawVarint64(value);
+        }
+
+        /// <summary>
+        /// Writes an int64 field value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteInt64(long value)
+        {
+            WriteRawVarint64((ulong) value);
+        }
+
+        /// <summary>
+        /// Writes an int32 field value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteInt32(int value)
+        {
+            if (value >= 0)
+            {
+                WriteRawVarint32((uint) value);
+            }
+            else
+            {
+                // Must sign-extend.
+                WriteRawVarint64((ulong) value);
+            }
+        }
+
+        /// <summary>
+        /// Writes a fixed64 field value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteFixed64(ulong value)
+        {
+            WriteRawLittleEndian64(value);
+        }
+
+        /// <summary>
+        /// Writes a fixed32 field value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteFixed32(uint value)
+        {
+            WriteRawLittleEndian32(value);
+        }
+
+        /// <summary>
+        /// Writes a bool field value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteBool(bool value)
+        {
+            WriteRawByte(value ? (byte) 1 : (byte) 0);
+        }
+
+        /// <summary>
+        /// Writes a string field value, without a tag, to the stream.
+        /// The data is length-prefixed.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteString(string value)
+        {
+            // Optimise the case where we have enough space to write
+            // the string directly to the buffer, which should be common.
+            int length = Utf8Encoding.GetByteCount(value);
+            WriteLength(length);
+            if (limit - position >= length)
+            {
+                if (length == value.Length) // Must be all ASCII...
+                {
+                    for (int i = 0; i < length; i++)
+                    {
+                        buffer[position + i] = (byte)value[i];
+                    }
+                }
+                else
+                {
+                    Utf8Encoding.GetBytes(value, 0, value.Length, buffer, position);
+                }
+                position += length;
+            }
+            else
+            {
+                byte[] bytes = Utf8Encoding.GetBytes(value);
+                WriteRawBytes(bytes);
+            }
+        }
+
+        /// <summary>
+        /// Writes a message, without a tag, to the stream.
+        /// The data is length-prefixed.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteMessage(IMessage value)
+        {
+            WriteLength(value.CalculateSize());
+            value.WriteTo(this);
+        }
+
+        /// <summary>
+        /// Write a byte string, without a tag, to the stream.
+        /// The data is length-prefixed.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteBytes(ByteString value)
+        {
+            WriteLength(value.Length);
+            value.WriteRawBytesTo(this);
+        }
+
+        /// <summary>
+        /// Writes a uint32 value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteUInt32(uint value)
+        {
+            WriteRawVarint32(value);
+        }
+
+        /// <summary>
+        /// Writes an enum value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteEnum(int value)
+        {
+            WriteInt32(value);
+        }
+
+        /// <summary>
+        /// Writes an sfixed32 value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write.</param>
+        public void WriteSFixed32(int value)
+        {
+            WriteRawLittleEndian32((uint) value);
+        }
+
+        /// <summary>
+        /// Writes an sfixed64 value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteSFixed64(long value)
+        {
+            WriteRawLittleEndian64((ulong) value);
+        }
+
+        /// <summary>
+        /// Writes an sint32 value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteSInt32(int value)
+        {
+            WriteRawVarint32(EncodeZigZag32(value));
+        }
+
+        /// <summary>
+        /// Writes an sint64 value, without a tag, to the stream.
+        /// </summary>
+        /// <param name="value">The value to write</param>
+        public void WriteSInt64(long value)
+        {
+            WriteRawVarint64(EncodeZigZag64(value));
+        }
+
+        /// <summary>
+        /// Writes a length (in bytes) for length-delimited data.
+        /// </summary>
+        /// <remarks>
+        /// This method simply writes a rawint, but exists for clarity in calling code.
+        /// </remarks>
+        /// <param name="length">Length value, in bytes.</param>
+        public void WriteLength(int length)
+        {
+            WriteRawVarint32((uint) length);
+        }
+
+        #endregion
+
+        #region Raw tag writing
+        /// <summary>
+        /// Encodes and writes a tag.
+        /// </summary>
+        /// <param name="fieldNumber">The number of the field to write the tag for</param>
+        /// <param name="type">The wire format type of the tag to write</param>
+        public void WriteTag(int fieldNumber, WireFormat.WireType type)
+        {
+            WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type));
+        }
+
+        /// <summary>
+        /// Writes an already-encoded tag.
+        /// </summary>
+        /// <param name="tag">The encoded tag</param>
+        public void WriteTag(uint tag)
+        {
+            WriteRawVarint32(tag);
+        }
+
+        /// <summary>
+        /// Writes the given single-byte tag directly to the stream.
+        /// </summary>
+        /// <param name="b1">The encoded tag</param>
+        public void WriteRawTag(byte b1)
+        {
+            WriteRawByte(b1);
+        }
+
+        /// <summary>
+        /// Writes the given two-byte tag directly to the stream.
+        /// </summary>
+        /// <param name="b1">The first byte of the encoded tag</param>
+        /// <param name="b2">The second byte of the encoded tag</param>
+        public void WriteRawTag(byte b1, byte b2)
+        {
+            WriteRawByte(b1);
+            WriteRawByte(b2);
+        }
+
+        /// <summary>
+        /// Writes the given three-byte tag directly to the stream.
+        /// </summary>
+        /// <param name="b1">The first byte of the encoded tag</param>
+        /// <param name="b2">The second byte of the encoded tag</param>
+        /// <param name="b3">The third byte of the encoded tag</param>
+        public void WriteRawTag(byte b1, byte b2, byte b3)
+        {
+            WriteRawByte(b1);
+            WriteRawByte(b2);
+            WriteRawByte(b3);
+        }
+
+        /// <summary>
+        /// Writes the given four-byte tag directly to the stream.
+        /// </summary>
+        /// <param name="b1">The first byte of the encoded tag</param>
+        /// <param name="b2">The second byte of the encoded tag</param>
+        /// <param name="b3">The third byte of the encoded tag</param>
+        /// <param name="b4">The fourth byte of the encoded tag</param>
+        public void WriteRawTag(byte b1, byte b2, byte b3, byte b4)
+        {
+            WriteRawByte(b1);
+            WriteRawByte(b2);
+            WriteRawByte(b3);
+            WriteRawByte(b4);
+        }
+
+        /// <summary>
+        /// Writes the given five-byte tag directly to the stream.
+        /// </summary>
+        /// <param name="b1">The first byte of the encoded tag</param>
+        /// <param name="b2">The second byte of the encoded tag</param>
+        /// <param name="b3">The third byte of the encoded tag</param>
+        /// <param name="b4">The fourth byte of the encoded tag</param>
+        /// <param name="b5">The fifth byte of the encoded tag</param>
+        public void WriteRawTag(byte b1, byte b2, byte b3, byte b4, byte b5)
+        {
+            WriteRawByte(b1);
+            WriteRawByte(b2);
+            WriteRawByte(b3);
+            WriteRawByte(b4);
+            WriteRawByte(b5);
+        }
+        #endregion
+
+        #region Underlying writing primitives
+        /// <summary>
+        /// Writes a 32 bit value as a varint. The fast route is taken when
+        /// there's enough buffer space left to whizz through without checking
+        /// for each byte; otherwise, we resort to calling WriteRawByte each time.
+        /// </summary>
+        internal void WriteRawVarint32(uint value)
+        {
+            // Optimize for the common case of a single byte value
+            if (value < 128 && position < limit)
+            {
+                buffer[position++] = (byte)value;
+                return;
+            }
+
+            while (value > 127 && position < limit)
+            {
+                buffer[position++] = (byte) ((value & 0x7F) | 0x80);
+                value >>= 7;
+            }
+            while (value > 127)
+            {
+                WriteRawByte((byte) ((value & 0x7F) | 0x80));
+                value >>= 7;
+            }
+            if (position < limit)
+            {
+                buffer[position++] = (byte) value;
+            }
+            else
+            {
+                WriteRawByte((byte) value);
+            }
+        }
+
+        internal void WriteRawVarint64(ulong value)
+        {
+            while (value > 127 && position < limit)
+            {
+                buffer[position++] = (byte) ((value & 0x7F) | 0x80);
+                value >>= 7;
+            }
+            while (value > 127)
+            {
+                WriteRawByte((byte) ((value & 0x7F) | 0x80));
+                value >>= 7;
+            }
+            if (position < limit)
+            {
+                buffer[position++] = (byte) value;
+            }
+            else
+            {
+                WriteRawByte((byte) value);
+            }
+        }
+
+        internal void WriteRawLittleEndian32(uint value)
+        {
+            if (position + 4 > limit)
+            {
+                WriteRawByte((byte) value);
+                WriteRawByte((byte) (value >> 8));
+                WriteRawByte((byte) (value >> 16));
+                WriteRawByte((byte) (value >> 24));
+            }
+            else
+            {
+                buffer[position++] = ((byte) value);
+                buffer[position++] = ((byte) (value >> 8));
+                buffer[position++] = ((byte) (value >> 16));
+                buffer[position++] = ((byte) (value >> 24));
+            }
+        }
+
+        internal void WriteRawLittleEndian64(ulong value)
+        {
+            if (position + 8 > limit)
+            {
+                WriteRawByte((byte) value);
+                WriteRawByte((byte) (value >> 8));
+                WriteRawByte((byte) (value >> 16));
+                WriteRawByte((byte) (value >> 24));
+                WriteRawByte((byte) (value >> 32));
+                WriteRawByte((byte) (value >> 40));
+                WriteRawByte((byte) (value >> 48));
+                WriteRawByte((byte) (value >> 56));
+            }
+            else
+            {
+                buffer[position++] = ((byte) value);
+                buffer[position++] = ((byte) (value >> 8));
+                buffer[position++] = ((byte) (value >> 16));
+                buffer[position++] = ((byte) (value >> 24));
+                buffer[position++] = ((byte) (value >> 32));
+                buffer[position++] = ((byte) (value >> 40));
+                buffer[position++] = ((byte) (value >> 48));
+                buffer[position++] = ((byte) (value >> 56));
+            }
+        }
+
+        internal void WriteRawByte(byte value)
+        {
+            if (position == limit)
+            {
+                RefreshBuffer();
+            }
+
+            buffer[position++] = value;
+        }
+
+        internal void WriteRawByte(uint value)
+        {
+            WriteRawByte((byte) value);
+        }
+
+        /// <summary>
+        /// Writes out an array of bytes.
+        /// </summary>
+        internal void WriteRawBytes(byte[] value)
+        {
+            WriteRawBytes(value, 0, value.Length);
+        }
+
+        /// <summary>
+        /// Writes out part of an array of bytes.
+        /// </summary>
+        internal void WriteRawBytes(byte[] value, int offset, int length)
+        {
+            if (limit - position >= length)
+            {
+                ByteArray.Copy(value, offset, buffer, position, length);
+                // We have room in the current buffer.
+                position += length;
+            }
+            else
+            {
+                // Write extends past current buffer.  Fill the rest of this buffer and
+                // flush.
+                int bytesWritten = limit - position;
+                ByteArray.Copy(value, offset, buffer, position, bytesWritten);
+                offset += bytesWritten;
+                length -= bytesWritten;
+                position = limit;
+                RefreshBuffer();
+
+                // Now deal with the rest.
+                // Since we have an output stream, this is our buffer
+                // and buffer offset == 0
+                if (length <= limit)
+                {
+                    // Fits in new buffer.
+                    ByteArray.Copy(value, offset, buffer, 0, length);
+                    position = length;
+                }
+                else
+                {
+                    // Write is very big.  Let's do it all at once.
+                    output.Write(value, offset, length);
+                }
+            }
+        }
+
+        #endregion
+
+        /// <summary>
+        /// Encode a 32-bit value with ZigZag encoding.
+        /// </summary>
+        /// <remarks>
+        /// ZigZag encodes signed integers into values that can be efficiently
+        /// encoded with varint.  (Otherwise, negative values must be 
+        /// sign-extended to 64 bits to be varint encoded, thus always taking
+        /// 10 bytes on the wire.)
+        /// </remarks>
+        internal static uint EncodeZigZag32(int n)
+        {
+            // Note:  the right-shift must be arithmetic
+            return (uint) ((n << 1) ^ (n >> 31));
+        }
+
+        /// <summary>
+        /// Encode a 64-bit value with ZigZag encoding.
+        /// </summary>
+        /// <remarks>
+        /// ZigZag encodes signed integers into values that can be efficiently
+        /// encoded with varint.  (Otherwise, negative values must be 
+        /// sign-extended to 64 bits to be varint encoded, thus always taking
+        /// 10 bytes on the wire.)
+        /// </remarks>
+        internal static ulong EncodeZigZag64(long n)
+        {
+            return (ulong) ((n << 1) ^ (n >> 63));
+        }
+
+        private void RefreshBuffer()
+        {
+            if (output == null)
+            {
+                // We're writing to a single buffer.
+                throw new OutOfSpaceException();
+            }
+
+            // Since we have an output stream, this is our buffer
+            // and buffer offset == 0
+            output.Write(buffer, 0, position);
+            position = 0;
+        }
+
+        /// <summary>
+        /// Indicates that a CodedOutputStream wrapping a flat byte array
+        /// ran out of space.
+        /// </summary>
+        public sealed class OutOfSpaceException : IOException
+        {
+            internal OutOfSpaceException()
+                : base("CodedOutputStream was writing to a flat byte array and ran out of space.")
+            {
+            }
+        }
+
+        /// <summary>
+        /// Flushes any buffered data to the underlying stream (if there is one).
+        /// </summary>
+        public void Flush()
+        {
+            if (output != null)
+            {
+                RefreshBuffer();
+            }
+        }
+
+        /// <summary>
+        /// Verifies that SpaceLeft returns zero. It's common to create a byte array
+        /// that is exactly big enough to hold a message, then write to it with
+        /// a CodedOutputStream. Calling CheckNoSpaceLeft after writing verifies that
+        /// the message was actually as big as expected, which can help bugs.
+        /// </summary>
+        public void CheckNoSpaceLeft()
+        {
+            if (SpaceLeft != 0)
+            {
+                throw new InvalidOperationException("Did not write as much data as expected.");
+            }
+        }
+
+        /// <summary>
+        /// If writing to a flat array, returns the space left in the array. Otherwise,
+        /// throws an InvalidOperationException.
+        /// </summary>
+        public int SpaceLeft
+        {
+            get
+            {
+                if (output == null)
+                {
+                    return limit - position;
+                }
+                else
+                {
+                    throw new InvalidOperationException(
+                        "SpaceLeft can only be called on CodedOutputStreams that are " +
+                        "writing to a flat array.");
+                }
+            }
+        }
+    }
+}

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov